From 828c12c63ead009a140b9ab334807ad91992d8ec Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 10:45:23 -0600 Subject: [PATCH 01/34] Fix "Not able to set default page breaks before expression" --- src/calibre/ebooks/conversion/plumber.py | 6 ++++-- src/calibre/gui2/dialogs/config/__init__.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index e2bd1128f5..2261d071ed 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -46,7 +46,8 @@ class Plumber(object): 'tags', 'book_producer', 'language' ] - def __init__(self, input, output, log, report_progress=DummyReporter(), dummy=False): + def __init__(self, input, output, log, report_progress=DummyReporter(), + dummy=False, merge_plugin_recs=True): ''' :param input: Path to input file. :param output: Path to output file/directory @@ -483,7 +484,8 @@ OptionRecommendation(name='language', for x in getattr(self, w): temp.add(x.clone()) setattr(self, w, temp) - self.merge_plugin_recommendations() + if merge_plugin_recs: + self.merge_plugin_recommendations() @classmethod def unarchive(self, path, tdir): diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py index d719f24d66..ba63fa560b 100644 --- a/src/calibre/gui2/dialogs/config/__init__.py +++ b/src/calibre/gui2/dialogs/config/__init__.py @@ -41,7 +41,8 @@ class ConfigTabs(QTabWidget): log = Log() log.outputs = [] - self.plumber = Plumber('dummy.epub', 'dummy.epub', log, dummy=True) + self.plumber = Plumber('dummy.epub', 'dummy.epub', log, dummy=True, + merge_plugin_recs=False) def widget_factory(cls): return cls(self, self.plumber.get_option_by_name, From ddc5bd4bbf113749c10b9b6509a965ca3bccdda8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 10:46:40 -0600 Subject: [PATCH 02/34] Change default save to disk template to {author_sort}/{title}/{title} - {authors} --- src/calibre/library/save_to_disk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index cafe8addc8..adaa9c8689 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -17,7 +17,7 @@ from calibre.constants import preferred_encoding, filesystem_encoding from calibre import strftime -DEFAULT_TEMPLATE = '{author_sort}/{title} - {authors}' +DEFAULT_TEMPLATE = '{author_sort}/{title}/{title} - {authors}' FORMAT_ARG_DESCS = dict( title=_('The title'), authors=_('The authors'), From ce5f382390acabc78d1a4633cfd0159ed41b9327 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 11:20:31 -0600 Subject: [PATCH 03/34] IGN:Fix #2152 (Typo in GUI) --- src/calibre/ebooks/fb2/output.py | 8 +- src/calibre/ebooks/pdb/output.py | 2 +- src/calibre/ebooks/pml/output.py | 2 +- src/calibre/ebooks/rb/output.py | 2 +- src/calibre/ebooks/txt/output.py | 4 +- src/calibre/translations/calibre.pot | 361 ++++++++++++++------------- 6 files changed, 195 insertions(+), 184 deletions(-) diff --git a/src/calibre/ebooks/fb2/output.py b/src/calibre/ebooks/fb2/output.py index 67ea135c1b..2bb49318af 100644 --- a/src/calibre/ebooks/fb2/output.py +++ b/src/calibre/ebooks/fb2/output.py @@ -18,10 +18,10 @@ class FB2Output(OutputFormatPlugin): options = set([ OptionRecommendation(name='inline_toc', recommended_value=False, level=OptionRecommendation.LOW, - help=_('Add Table of Contents to begenning of the book.')), + help=_('Add Table of Contents to beginning of the book.')), ]) - def convert(self, oeb_book, output_path, input_plugin, opts, log): + def convert(self, oeb_book, output_path, input_plugin, opts, log): fb2mlizer = FB2MLizer(log) fb2_content = fb2mlizer.extract_content(oeb_book, opts) @@ -33,11 +33,11 @@ class FB2Output(OutputFormatPlugin): out_stream = open(output_path, 'wb') else: out_stream = output_path - + out_stream.seek(0) out_stream.truncate() out_stream.write(fb2_content.encode('utf-8', 'replace')) - + if close: out_stream.close() diff --git a/src/calibre/ebooks/pdb/output.py b/src/calibre/ebooks/pdb/output.py index 9a844d2136..06f2f20d10 100644 --- a/src/calibre/ebooks/pdb/output.py +++ b/src/calibre/ebooks/pdb/output.py @@ -29,7 +29,7 @@ class PDBOutput(OutputFormatPlugin): 'formats.')), OptionRecommendation(name='inline_toc', recommended_value=False, level=OptionRecommendation.LOW, - help=_('Add Table of Contents to begenning of the book.')), + help=_('Add Table of Contents to beginning of the book.')), ]) def convert(self, oeb_book, output_path, input_plugin, opts, log): diff --git a/src/calibre/ebooks/pml/output.py b/src/calibre/ebooks/pml/output.py index 970bcd3594..360e63c98e 100644 --- a/src/calibre/ebooks/pml/output.py +++ b/src/calibre/ebooks/pml/output.py @@ -34,7 +34,7 @@ class PMLOutput(OutputFormatPlugin): 'The default is cp1252.')), OptionRecommendation(name='inline_toc', recommended_value=False, level=OptionRecommendation.LOW, - help=_('Add Table of Contents to begenning of the book.')), + help=_('Add Table of Contents to beginning of the book.')), ]) def convert(self, oeb_book, output_path, input_plugin, opts, log): diff --git a/src/calibre/ebooks/rb/output.py b/src/calibre/ebooks/rb/output.py index 0e0bd27326..a16e408b0f 100644 --- a/src/calibre/ebooks/rb/output.py +++ b/src/calibre/ebooks/rb/output.py @@ -18,7 +18,7 @@ class RBOutput(OutputFormatPlugin): options = set([ OptionRecommendation(name='inline_toc', recommended_value=False, level=OptionRecommendation.LOW, - help=_('Add Table of Contents to begenning of the book.')), + help=_('Add Table of Contents to beginning of the book.')), ]) def convert(self, oeb_book, output_path, input_plugin, opts, log): diff --git a/src/calibre/ebooks/txt/output.py b/src/calibre/ebooks/txt/output.py index 38d1b3ebb7..6f0a768b8f 100644 --- a/src/calibre/ebooks/txt/output.py +++ b/src/calibre/ebooks/txt/output.py @@ -32,13 +32,13 @@ class TXTOutput(OutputFormatPlugin): 'formats.')), OptionRecommendation(name='inline_toc', recommended_value=False, level=OptionRecommendation.LOW, - help=_('Add Table of Contents to begenning of the book.')), + help=_('Add Table of Contents to beginning of the book.')), ]) def convert(self, oeb_book, output_path, input_plugin, opts, log): writer = TXTMLizer(log) txt = writer.extract_content(oeb_book, opts) - + log.debug('\tReplacing newlines with selected type...') txt = specified_newlines(TxtNewlines(opts.newline).newline, txt) diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 64111480cd..cf2695ebb1 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.8\n" -"POT-Creation-Date: 2009-08-21 15:14+MDT\n" -"PO-Revision-Date: 2009-08-21 15:14+MDT\n" +"POT-Creation-Date: 2009-08-23 11:19+MDT\n" +"PO-Revision-Date: 2009-08-23 11:19+MDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -693,234 +693,234 @@ msgstr "" msgid "Output saved to" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:68 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:69 msgid "Level of verbosity. Specify multiple times for greater verbosity." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:75 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:76 msgid "Specify the input profile. The input profile gives the conversion system information on how to interpret various information in the input document. For example resolution dependent lengths (i.e. lengths in pixels). Choices are:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:86 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:87 msgid "Specify the output profile. The output profile tells the conversion system how to optimize the created document for the specified device. In some cases, an output profile is required to produce documents that will work on a device. For example EPUB on the SONY reader. Choices are:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:97 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:98 msgid "The base font size in pts. All font sizes in the produced book will be rescaled based on this size. By choosing a larger size you can make the fonts in the output bigger and vice versa. By default, the base font size is chosen based on the output profile you chose." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:107 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:108 msgid "Mapping from CSS font names to font sizes in pts. An example setting is 12,12,14,16,18,20,22,24. These are the mappings for the sizes xx-small to xx-large, with the final size being for huge fonts. The font rescaling algorithm uses these sizes to intelligently rescale fonts. The default is to use a mapping based on the output profile you chose." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:119 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:120 msgid "Disable all rescaling of font sizes." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:126 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:127 msgid "The line height in pts. Controls spacing between consecutive lines of text. By default no line height manipulation is performed." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:134 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:135 msgid "Some badly designed documents use tables to control the layout of text on the page. When converted these documents often have text that runs off the page and other artifacts. This option will extract the content from the tables and present it in a linear fashion." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:144 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:145 msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level one. If this is specified, it takes precedence over other forms of auto-detection." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:153 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:154 msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level two. Each entry is added under the previous level one entry." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:161 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:162 msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level three. Each entry is added under the previous level two entry." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:169 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:170 msgid "Normally, if the source file already has a Table of Contents, it is used in preference to the auto-generated one. With this option, the auto-generated one is always used." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:177 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:178 msgid "Don't add auto-detected chapters to the Table of Contents." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:184 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:185 msgid "If fewer than this number of chapters is detected, then links are added to the Table of Contents. Default: %default" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:191 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:192 msgid "Maximum number of links to insert into the TOC. Set to 0 to disable. Default is: %default. Links are only added to the TOC if less than the threshold number of chapters were detected." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:199 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:200 msgid "Remove entries from the Table of Contents whose titles match the specified regular expression. Matching entries and all their children are removed." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:210 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:211 msgid "An XPath expression to detect chapter titles. The default is to consider

or

tags that contain the words \"chapter\",\"book\",\"section\" or \"part\" as chapter titles as well as any tags that have class=\"chapter\". The expression used must evaluate to a list of elements. To disable chapter detection, use the expression \"/\". See the XPath Tutorial in the calibre User Manual for further help on using this feature." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:224 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:225 msgid "Specify how to mark detected chapters. A value of \"pagebreak\" will insert page breaks before chapters. A value of \"rule\" will insert a line before chapters. A value of \"none\" will disable chapter marking and a value of \"both\" will use both page breaks and lines to mark chapters." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:234 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:235 msgid "Either the path to a CSS stylesheet or raw CSS. This CSS will be appended to the style rules from the source file, so it can be used to override those rules." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:243 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:244 msgid "An XPath expression. Page breaks are inserted before the specified elements." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:249 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:250 msgid "Set the top margin in pts. Default is %default. Note: 72 pts equals 1 inch" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:254 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:255 msgid "Set the bottom margin in pts. Default is %default. Note: 72 pts equals 1 inch" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:259 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:260 msgid "Set the left margin in pts. Default is %default. Note: 72 pts equals 1 inch" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:264 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:265 msgid "Set the right margin in pts. Default is %default. Note: 72 pts equals 1 inch" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:269 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:270 msgid "Do not force text to be justified in output. Whether text is actually displayed justified or not depends on whether the ebook format and reading device support justification." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:276 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:277 msgid "Remove spacing between paragraphs. Also sets an indent on paragraphs of 1.5em. Spacing removal will not work if the source file does not use paragraphs (

or

tags)." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:283 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:284 msgid "Use the cover detected from the source file in preference to the specified cover." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:289 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:290 msgid "Insert a blank line between paragraphs. Will not work if the source file does not use paragraphs (

or

tags)." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:296 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:297 msgid "Remove the first image from the input ebook. Useful if the first image in the source file is a cover and you are specifying an external cover." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:304 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:305 msgid "Insert the book metadata at the start of the book. This is useful if your ebook reader does not support displaying/searching metadata directly." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:312 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:313 msgid "Attempt to detect and correct hard line breaks and other problems in the source file. This may make things worse, so use with care." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:320 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:321 msgid "Use a regular expression to try and remove the header." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:327 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:328 msgid "The regular expression to use to remove the header." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:333 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:334 msgid "Use a regular expression to try and remove the footer." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:340 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:341 msgid "The regular expression to use to remove the footer." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:347 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:348 msgid "Read metadata from the specified OPF file. Metadata read from this file will override any metadata in the source file." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:354 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:355 msgid "Transliterate unicode characters to an ASCII representation. Use with care because this will replace unicode characters with ASCII. For instance it will replace \"%s\" with \"Mikhail Gorbachiov\". Also, note that in cases where there are multiple representations of a character (characters shared by Chinese and Japanese for instance) the representation used by the largest number of people will be used (Chinese in the previous example)." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:369 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:370 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:37 msgid "Set the title." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:373 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:374 msgid "Set the authors. Multiple authors should be separated by ampersands." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:378 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:379 msgid "The version of the title to be used for sorting. " msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:382 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:383 msgid "String to be used when sorting by author. " msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:386 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:387 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:51 msgid "Set the cover to the specified file." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:390 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:391 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:53 msgid "Set the ebook description." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:394 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:395 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:55 msgid "Set the ebook publisher." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:398 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:399 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:59 msgid "Set the series this ebook belongs to." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:402 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:403 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:61 msgid "Set the index of the book in this series." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:406 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:407 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:63 msgid "Set the rating. Should be a number between 1 and 5." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:410 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:411 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:65 msgid "Set the ISBN of the book." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:414 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:415 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:67 msgid "Set the tags for the book. Should be a comma separated list." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:418 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:419 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:69 msgid "Set the book producer." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:422 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:423 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:71 msgid "Set the language." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:513 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:515 msgid "Could not find an ebook inside the archive" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:651 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:653 msgid "Converting input to HTML..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:668 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:670 msgid "Running transforms on ebook..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:743 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:745 msgid "Creating" msgstr "" @@ -956,7 +956,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/pml/output.py:37 #: /home/kovid/work/calibre/src/calibre/ebooks/rb/output.py:21 #: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:35 -msgid "Add Table of Contents to begenning of the book." +msgid "Add Table of Contents to beginning of the book." msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:242 @@ -1352,27 +1352,27 @@ msgstr "" msgid "Set the BookID in LRF files" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:143 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:144 msgid "No file specified" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:158 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:159 msgid "Original metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:175 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:176 msgid "Changed metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:187 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:188 msgid "OPF created in" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:193 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:194 msgid "Cover saved to" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:195 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:196 msgid "No cover found" msgstr "" @@ -2250,6 +2250,7 @@ msgid "Set the metadata. The output file will contain as much of this metadata a msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:134 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:95 msgid "Choose cover for " msgstr "" @@ -2870,7 +2871,7 @@ msgid "Attached, you will find the e-book" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/device.py:550 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:175 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:177 msgid "by" msgstr "" @@ -2970,7 +2971,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:88 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:89 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:92 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:214 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:216 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:344 #: /home/kovid/work/calibre/src/calibre/gui2/status.py:57 #: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:83 @@ -3009,166 +3010,173 @@ msgstr "" msgid "&Profile:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:168 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:170 msgid "%(plugin_type)s %(plugins)s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:169 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:171 msgid "plugins" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:194 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196 msgid "Conversion" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:194 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196 msgid "General" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:194 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196 msgid "Interface" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:195 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:197 msgid "Add/Save" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:195 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:197 msgid "" "Email\n" "Delivery" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:198 msgid "Advanced" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:198 msgid "" "Content\n" "Server" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:196 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:198 msgid "Plugins" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:214 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:216 msgid "Auto send" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:214 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:216 msgid "Email" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:219 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:221 msgid "Formats to email. The first matching format will be sent." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:220 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:222 msgid "If checked, downloaded news will be automatically mailed
to this email address (provided it is in one of the listed formats)." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:294 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:296 msgid "new email address" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:505 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:507 msgid "No valid plugin path" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:506 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:508 msgid "%s is not a valid plugin path" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:509 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:511 msgid "Choose plugin" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:521 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:523 msgid "Plugin cannot be disabled" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:522 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:524 msgid "The plugin: %s cannot be disabled" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:531 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:533 msgid "Plugin not customizable" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:532 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:534 msgid "Plugin: %s does not need customization" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:556 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:558 msgid "Customize %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:566 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:568 msgid "Cannot remove builtin plugin" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:567 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:569 msgid " cannot be removed. It is a builtin plugin. Try disabling it instead." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:600 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:602 msgid "Error log:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:607 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:609 msgid "Access log:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:632 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:634 #: /home/kovid/work/calibre/src/calibre/gui2/main.py:564 msgid "Failed to start content server" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:656 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:658 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:469 msgid "Select location for books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:673 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:675 msgid "Invalid size" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:674 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:676 msgid "The size %s is invalid. must be of the form widthxheight" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:718 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:723 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:720 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:725 msgid "Invalid database location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:719 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:721 msgid "Invalid database location " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:720 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:722 msgid "
Must be a directory." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:724 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:726 msgid "Invalid database location.
Cannot write to " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:749 -msgid "Checking..." -msgstr "" - -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:750 -msgid "Checking database integrity. This may take a while." -msgstr "" - #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:763 +msgid "Checking database integrity" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:782 +#: /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/dialogs/config/__init__.py:783 +msgid "Failed to check database integrity" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:788 msgid "Some inconsistencies found" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:764 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:789 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 "" @@ -4460,12 +4468,6 @@ msgstr "" 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:142 msgid "Error communicating with device" msgstr "" @@ -4536,7 +4538,7 @@ msgid "Save to disk in a single directory" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/main.py:280 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1472 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1474 msgid "Save only %s format to disk" msgstr "" @@ -4571,7 +4573,7 @@ msgid "Bad database location" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/main.py:428 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1600 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1602 msgid "Choose a location for your ebook library." msgstr "" @@ -4675,7 +4677,7 @@ msgstr "" #: /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 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1198 msgid "No books selected" msgstr "" @@ -4716,187 +4718,187 @@ msgstr "" msgid "Choose destination directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1088 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1090 msgid "Error while saving" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1089 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1091 msgid "There was an error while saving." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1096 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1097 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1098 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1099 msgid "Could not save some books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1098 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1100 msgid "Click the show details button to see which ones." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1117 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1119 msgid "Fetching news from " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1130 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1132 msgid " fetched." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1195 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1197 msgid "Cannot convert" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1365 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1384 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1367 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1386 msgid "No book selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1365 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1417 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1367 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1419 msgid "Cannot view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1371 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1373 msgid "Choose the format to view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1383 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1385 msgid "Cannot open folder" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1400 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1402 msgid "Multiple Books Selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1401 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1403 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:1418 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1420 msgid "%s has no available formats." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1456 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1458 msgid "Cannot configure" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1457 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1459 msgid "Cannot configure while there are running jobs." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1501 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1503 msgid "No detailed info available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1502 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1504 msgid "No detailed information is available for books on the device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1550 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1552 msgid "Error talking to device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1551 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1553 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:1568 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1583 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1570 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1585 msgid "Conversion Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1569 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1571 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:1584 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1586 msgid "Failed" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1609 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1611 msgid "Invalid library location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1610 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1612 msgid "Could not access %s. Using %s as the library." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1658 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1660 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:1682 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1684 msgid "There are active jobs. Are you sure you want to quit?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1685 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1687 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:1689 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1691 msgid "WARNING: Active jobs" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1740 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1742 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:1759 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1761 msgid "Latest version: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1767 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1769 msgid "Update available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1768 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1770 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:1786 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1788 msgid "Use the library located at the specified path." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1788 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1790 msgid "Start minimized to system tray." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1790 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1792 msgid "Log debugging information to console" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1838 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1840 msgid "If you are sure it is not running" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1840 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1842 msgid "Cannot Start " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1841 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1843 msgid "%s is already running." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1844 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1846 msgid "may be running in the system tray, in the" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1846 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1848 msgid "upper right region of the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1848 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1850 msgid "lower right region of the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1851 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1853 msgid "try rebooting your computer." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1853 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1873 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1855 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1875 msgid "try deleting the file" msgstr "" @@ -5970,6 +5972,18 @@ msgstr "" msgid "Compacting database" msgstr "" +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1674 +msgid "Checking SQL integrity..." +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1702 +msgid "Checking for missing files." +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1726 +msgid "Checked id" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/library/save_to_disk.py:22 msgid "The title" msgstr "" @@ -6065,10 +6079,6 @@ msgid "" "Start the calibre content server." msgstr "" -#: /home/kovid/work/calibre/src/calibre/manual/qthelp.py:163 -msgid "Global Module Index" -msgstr "" - #: /home/kovid/work/calibre/src/calibre/utils/config.py:43 msgid "" "%sUsage%s: %s\n" @@ -6258,7 +6268,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_instapaper.py:59 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_lamujerdemivida.py:59 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_laprensa_ni.py:63 -#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_monitor.py:65 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_monitor.py:78 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_pobjeda.py:83 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_republika.py:66 msgid "Fetching feed" @@ -6367,6 +6377,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_economist.py:17 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_endgadget.py:16 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_espn.py:17 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_esquire.py:25 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_exiled.py:23 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_fastcompany.py:25 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_financial_times.py:16 @@ -6411,7 +6422,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nytimes.py:17 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nytimes_sub.py:17 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_ourdailybread.py:16 -#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_outlook_india.py:17 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_outlook_india.py:15 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_phd_comics.py:16 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_physics_today.py:11 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_physics_world.py:8 From e9d1b7b72a4a3273db287592c8d2d7f9eb26f924 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 11:39:53 -0600 Subject: [PATCH 04/34] No longer strip the [] characters from filenames --- src/calibre/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index 2932d71064..bfe101ffa7 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -69,7 +69,7 @@ def osx_version(): return int(m.group(1)), int(m.group(2)), int(m.group(3)) -_filename_sanitize = re.compile(r'[\xae\0\\|\?\*<":>\+\[\]/]') +_filename_sanitize = re.compile(r'[\xae\0\\|\?\*<":>\+/]') def sanitize_file_name(name, substitute='_', as_unicode=False): ''' From 5b361e348b63c945c17be7c262385194bf696b3f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 12:03:24 -0600 Subject: [PATCH 05/34] Updated recipe for Outlook India --- src/calibre/web/feeds/news.py | 2 +- .../web/feeds/recipes/recipe_outlook_india.py | 168 +++++++++--------- 2 files changed, 89 insertions(+), 81 deletions(-) diff --git a/src/calibre/web/feeds/news.py b/src/calibre/web/feeds/news.py index 05c62af725..91e00cc213 100644 --- a/src/calibre/web/feeds/news.py +++ b/src/calibre/web/feeds/news.py @@ -679,7 +679,7 @@ class BasicNewsRecipe(Recipe): fetcher.browser_lock = fetcher.DUMMY_LOCK res, path, failures = fetcher.start_fetch(url), fetcher.downloaded_paths, fetcher.failed_links if not res or not os.path.exists(res): - raise Exception(_('Could not fetch article. Run with --debug to see the reason')) + raise Exception(_('Could not fetch article. Run with -vv to see the reason')) return res, path, failures def fetch_article(self, url, dir, f, a, num_of_feeds): diff --git a/src/calibre/web/feeds/recipes/recipe_outlook_india.py b/src/calibre/web/feeds/recipes/recipe_outlook_india.py index 8576b41f39..5c440b424d 100644 --- a/src/calibre/web/feeds/recipes/recipe_outlook_india.py +++ b/src/calibre/web/feeds/recipes/recipe_outlook_india.py @@ -1,87 +1,95 @@ #!/usr/bin/env python __license__ = 'GPL v3' -__copyright__ = '2008, Kovid Goyal ' -''' -outlookindia.com -''' - -from calibre.web.feeds.news import BasicNewsRecipe +__copyright__ = '2009, Kovid Goyal ' import re +from calibre.web.feeds.news import BasicNewsRecipe class OutlookIndia(BasicNewsRecipe): - - title = 'Outlook India' - __author__ = 'Kovid Goyal' - description = 'Weekly news magazine focused on India.' - language = _('English') - recursions = 1 - match_regexp = r'full.asp.*&pn=\d+' - - remove_tags = [ - dict(name='img', src="images/space.gif"), - dict(name=lambda tag: tag.name == 'tr' and tag.find('img', src="image/tl.gif") is not None ), - dict(name=lambda tag: tag.name == 'table' and tag.find('font', attrs={'class':'fontemailfeed'}) is not None), - ] - - preprocess_regexps = [ - (re.compile(r'', re.DOTALL|re.IGNORECASE), - lambda match: ''), - - (re.compile(r'>More Stories:.*', re.DOTALL), - lambda match: '>'), - - (re.compile(r'.*', re.DOTALL), - lambda match: ''), - ] - - def parse_index(self): - soup = self.index_to_soup('http://www.outlookindia.com/archivecontents.asp') - feeds = [] - title = None - bogus = True - for table in soup.findAll('table'): - if title is None: - td = table.find('td', background="images/content_band1.jpg") - if td is not None: - title = self.tag_to_string(td, False) - title = title.replace(u'\xa0', u'').strip() - if 'Cover Story' in title and bogus: - bogus = False - title = None - else: - articles = [] - for a in table.findAll('a', href=True): - if a.find('img') is not None: - continue - atitle = self.tag_to_string(a, use_alt=False) - desc = a.findNextSibling('font', attrs={'class':'fontintro'}) - if desc is not None: - desc = self.tag_to_string(desc) - if not desc: - desc = '' - articles.append({ - 'title':atitle, - 'description': desc, - 'content': '', - 'url':'http://www.outlookindia.com/'+a['href'], - 'date': '', - }) - feeds.append((title, articles)) - title = None - - - return feeds - def postprocess_html(self, soup, first_fetch): - bad = [] - for table in soup.findAll('table'): - if table.find(text=re.compile(r'\(\d+ of \d+\)')): - bad.append(table) - for b in bad: - b.extract() - soup = soup.findAll('html')[0] - for t in soup.findAll(['table', 'tr', 'td']): - t.name = 'div' - return soup - + title = 'Outlook India' + __author__ = 'Kovid Goyal and Sujata Raman' + description = 'Weekly news and current affairs in India' + no_stylesheets = True + encoding = 'utf-8' + language = _('English') + keep_only_tags = [ + dict(name='div', attrs={'id':["ctl00_cphpagemiddle_reparticle_ctl00_divfullstorytext","ctl00_cphpagemiddle_reparticle_ctl00_divartpic","ctl00_cphpagemiddle_reparticle_ctl00_divfspheading", "ctl00_cphpagemiddle_reparticle_ctl00_divartpiccaption", "ctl00_cphpagemiddle_reparticle_ctl00_divartpiccredit","ctl00_cphpagemiddle_reparticle_ctl00_divfspintro", "ctl00_cphpagemiddle_reparticle_ctl00_divartbyline", ]}), + ] + remove_tags = [dict(name=['script','object'])] + + def get_browser(self): + br = BasicNewsRecipe.get_browser(self) + # This site sends article titles in the cookie which occasionally + # contain non ascii characters causing httplib to fail. Instead just + # disable cookies as they're not needed for download. Proper solution + # would be to implement a unicode aware cookie jar + br.set_cookiejar(None) + return br + + + def parse_index(self): + + + soup = self.index_to_soup('http://www.outlookindia.com/issues.aspx') +# find cover pic + div = soup.find('div', attrs={'class':re.compile('cententcellpadding')}) + + if div is None: return None + a = div.find('a') + + if a is not None: + href = 'http://www.outlookindia.com/' + a['href'] + + soup = self.index_to_soup(href) + cover = soup.find('img', attrs={'id':"ctl00_cphpagemiddle_dlissues_ctl00_imgcoverpic"}, src=True) + if cover is not None: + + self.cover_url = cover['src'] + + # end find cover pic + + div = soup.find('table', attrs={'id':re.compile('ctl00_cphpagemiddle_dlissues')}) + + if div is None: return None + a = div.find('a') + + if a is not None: + href = 'http://www.outlookindia.com/' + a['href'] + + soup = self.index_to_soup(href) + + articles = [] + + for a in soup.findAll('a', attrs={'class':'contentpgsubheadinglink'}): + + if a and a.has_key('href'): + url = 'http://www.outlookindia.com/' + a['href'] + else: + url ='' + title = self.tag_to_string(a) + + date = '' + description = '' + articles.append({ + 'title':title, + 'date':date, + 'url':url, + 'description':description + }) + + return [('Current Issue', articles)] + + def preprocess_html(self, soup): + for item in soup.findAll(style=True): + del item['style'] + return self.adeify_images(soup) + + def postrocess_html(self, soup, first): + + for tag in soup.findAll(name=['table', 'tr', 'td','tbody']): + tag.name = 'div' + + + return soup + From 6c31465eec788aff3e574b7f0dbbd2c56e4415fc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 12:41:55 -0600 Subject: [PATCH 06/34] IGN:Don't auto send to new email accounts be default if they are not the first email account --- src/calibre/gui2/dialogs/config/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py index ba63fa560b..32013b34fa 100644 --- a/src/calibre/gui2/dialogs/config/__init__.py +++ b/src/calibre/gui2/dialogs/config/__init__.py @@ -299,7 +299,8 @@ class EmailAccounts(QAbstractTableModel): while y in self.accounts: c += 1 y = x + str(c) - self.accounts[y] = ['MOBI, EPUB', True, + auto_send = len(self.accounts) < 1 + self.accounts[y] = ['MOBI, EPUB', auto_send, len(self.account_order) == 0] self.account_order = sorted(self.accounts.keys()) self.reset() From 5f81e69815f78aff75ff7b9d1a46d726453d6340 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 12:44:19 -0600 Subject: [PATCH 07/34] Implement #3261 (New recipe for Axxon news) --- src/calibre/gui2/images/news/axxon_news.png | Bin 0 -> 537 bytes src/calibre/web/feeds/recipes/__init__.py | 2 +- .../web/feeds/recipes/recipe_axxon_news.py | 61 ++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/calibre/gui2/images/news/axxon_news.png create mode 100644 src/calibre/web/feeds/recipes/recipe_axxon_news.py diff --git a/src/calibre/gui2/images/news/axxon_news.png b/src/calibre/gui2/images/news/axxon_news.png new file mode 100644 index 0000000000000000000000000000000000000000..c8b62364ef98e4290b8adc9906e956daa56f926e GIT binary patch literal 537 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI zAngIhZYQ(tK!Rljj_E*J0gT&!&6&%U&tX`Z?1KRLwDsfK2WSU_w(`I*?0W6+)y(5a$@cNM&4SR zpY`*(C0lYOUtdca1`>6)Y1xEhLrjD#UspY{-4Hb5;ZJY9|`q!k6KVA_j zxdPX-j7`5S+gdW~tFTdl@D%IQ5JA)cN%I`&D`GDHEqX9rf&z*IbVb%Pi?F5xHy?3CZ3&1?uVahiAPMmILo00`OdY!^mp>! z{BY>!d&W-(Q?2U+C%PUIRj&(OXi-ylXL(oV3l(ps`HlVao;GG%>HM23^X0_K1NAqb zu%6Aj_$khE(i>o~s+PD$l%yn}eUBjXT5BP(N5D?=dH%*w!E s@|tt=Q8eV{r(~v8B5N=(w=%Z0GBJZ_IOe*`6{vy1)78&qol`;+00VN;ZvX%Q literal 0 HcmV?d00001 diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index 061c5746f4..a214ca7fa6 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -42,7 +42,7 @@ recipe_modules = ['recipe_' + r for r in ( 'moneynews', 'der_standard', 'diepresse', 'nzz_ger', 'hna', 'seattle_times', 'scott_hanselman', 'coding_horror', 'twitchfilms', 'stackoverflow', 'telepolis_artikel', 'zaobao', 'usnews', - 'straitstimes', 'index_hu', 'pcworld_hu', 'hrt', 'rts', + 'straitstimes', 'index_hu', 'pcworld_hu', 'hrt', 'rts', 'axxon_news', 'h1', 'h2', 'h3', 'phd_comics', 'woz_die', 'elektrolese', 'climate_progress', 'carta', 'slashdot', 'publico', 'the_budget_fashionista', 'elperiodico_catalan', diff --git a/src/calibre/web/feeds/recipes/recipe_axxon_news.py b/src/calibre/web/feeds/recipes/recipe_axxon_news.py new file mode 100644 index 0000000000..cb9f5fca51 --- /dev/null +++ b/src/calibre/web/feeds/recipes/recipe_axxon_news.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +__license__ = 'GPL v3' +__copyright__ = '2009, Darko Miletic ' +''' +axxon.com.ar +''' +from calibre.web.feeds.news import BasicNewsRecipe +from calibre.ebooks.BeautifulSoup import Tag + +class Axxon_news(BasicNewsRecipe): + title = 'Axxon noticias' + __author__ = 'Darko Miletic' + description = 'Axxon, Ciencia Ficcion en Bits' + publisher = 'Axxon' + category = 'news, SF, Argentina, science, movies' + oldest_article = 7 + max_articles_per_feed = 100 + no_stylesheets = False + use_embedded_content = False + language = _('Spanish') + lang = 'es-AR' + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'language' : lang + , 'pretty_print' : True + } + + + keep_only_tags = [dict(name='div', attrs={'class':'post'})] + + remove_tags = [dict(name=['object','link','iframe','embed'])] + + feeds = [(u'Noticias', u'http://axxon.com.ar/noticias/feed/')] + + remove_attributes = ['style','width','height','font','border','align'] + + + def adeify_images2(cls, soup): + for item in soup.findAll('img'): + for attrib in ['height','width','border','align','style']: + if item.has_key(attrib): + del item[attrib] + oldParent = item.parent + if oldParent.name == 'a': + oldParent.name == 'p' + myIndex = oldParent.contents.index(item) + brtag = Tag(soup,'br') + oldParent.insert(myIndex+1,brtag) + return soup + + def preprocess_html(self, soup): + soup.html['xml:lang'] = self.lang + soup.html['lang'] = self.lang + mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)]) + soup.html.insert(0,mlang) + return self.adeify_images2(soup) + From cbfa60ae267df219d825b316dfea442b8ade2312 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 13:12:36 -0600 Subject: [PATCH 08/34] IGN:Fix Stanza FAQ entry --- src/calibre/manual/faq.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index 8b437f174a..626061eabb 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -95,13 +95,13 @@ turned into a collection on the reader. Note that the PRS-500 does not support c How do I use |app| with my iPhone? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -First install the Stanza reader on your iPhone from http://www.lexcycle.com . Then, +First install the Stanza reader on your iPhone using iTunes. - * Set the output format for calibre to EPUB (The output format can be set next to the big red heart) + * Set the Preferred Output Format in |app| to EPUB (The output format can be set under Preferences->General) * Convert the books you want to read on your iPhone to EPUB format by selecting them and clicking the Convert button. * Turn on the Content Server in |app|'s preferences and leave |app| running. -Now you should be able to access your books on your iPhone. +Now you should be able to access your books on your iPhone by opening Stanza and going to "Shared Books". Under Shared Books you will see an entry "Book in calibre". If you don't, make sure your iPhone is connected using the WiFi network in your house, not 3G. Why is my device not detected in linux? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 6261ba3f7272896e88a71f5fe56c9a7fe37c161d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Aug 2009 14:59:47 -0600 Subject: [PATCH 09/34] Fix regression in 0.6.8 that prevented calibre working with Stanza if you created a custom catalog in Stanza --- src/calibre/library/server.py | 7 +++++-- src/calibre/manual/faq.rst | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/calibre/library/server.py b/src/calibre/library/server.py index 10656a6df8..58cb457971 100644 --- a/src/calibre/library/server.py +++ b/src/calibre/library/server.py @@ -460,8 +460,11 @@ class LibraryServer(object): @expose def index(self, **kwargs): 'The / URL' - want_opds = cherrypy.request.headers.get('Stanza-Device-Name', 919) != \ - 919 or cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 + ua = cherrypy.request.headers.get('User-Agent', '').strip() + want_opds = \ + cherrypy.request.headers.get('Stanza-Device-Name', 919) != 919 or \ + cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 or \ + ua.startswith('Stanza') return self.stanza(search=kwargs.get('search', None), sortby=kwargs.get('sortby',None), authorid=kwargs.get('authorid',None)) if want_opds else self.static('index.html') diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index 626061eabb..500eda5e2f 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -101,7 +101,11 @@ First install the Stanza reader on your iPhone using iTunes. * Convert the books you want to read on your iPhone to EPUB format by selecting them and clicking the Convert button. * Turn on the Content Server in |app|'s preferences and leave |app| running. -Now you should be able to access your books on your iPhone by opening Stanza and going to "Shared Books". Under Shared Books you will see an entry "Book in calibre". If you don't, make sure your iPhone is connected using the WiFi network in your house, not 3G. +Now you should be able to access your books on your iPhone by opening Stanza and going to "Shared Books". Under Shared Books you will see an entry "Book in calibre". If you don't, make sure your iPhone is connected using the WiFi network in your house, not 3G. If the |app| catalog is still not detected in Stanza, you can add it manually in Stanza, by clicking "Online Catalog" and the clicking the plus icon in the lower right corner to add a new catalog. In the Add Catalog screen enter whatever name you like and in the URL field, enter the following:: + + http://192.168.1.2:8080/ + +Replace ``192.168.1.2`` with the local IP address of the computer running |app|. If you have changed the port the |app| content server is running on, you will have to change ``8080`` as well to the new port. The local IP address is the IP address you computer is assigned on your home network. A quick Google search will tell you how to find out your local IP address. Why is my device not detected in linux? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 8dd752d85070b63b5fa0f1697fae95ecb752b4d3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 24 Aug 2009 08:33:53 -0600 Subject: [PATCH 10/34] IGN:Updated recipe for Outlook India --- .../web/feeds/recipes/recipe_outlook_india.py | 59 +++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/src/calibre/web/feeds/recipes/recipe_outlook_india.py b/src/calibre/web/feeds/recipes/recipe_outlook_india.py index 5c440b424d..e931c89b4a 100644 --- a/src/calibre/web/feeds/recipes/recipe_outlook_india.py +++ b/src/calibre/web/feeds/recipes/recipe_outlook_india.py @@ -3,6 +3,8 @@ __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' import re +from calibre import strftime +from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag from calibre.web.feeds.news import BasicNewsRecipe class OutlookIndia(BasicNewsRecipe): @@ -13,10 +15,19 @@ class OutlookIndia(BasicNewsRecipe): no_stylesheets = True encoding = 'utf-8' language = _('English') + recursions = 1 + extra_css = ''' + body{font-family:Arial,Helvetica,sans-serif; font-size:xx-small;} + .fspheading{color:#AF0E25 ; font-family:"Times New Roman",Times,serif; font-weight:bold ; font-size:large; } + .fspauthor{color:#AF0E25; font-family:Arial,Helvetica,sans-serif; font-size:xx-small;} + .fspintro{color:#666666; font-family:Arial,Helvetica,sans-serif; font-size:xx-small;} + .fspchannelhome{font-family:Arial,Helvetica,sans-serif; font-size:x-small;} + .fspphotocredit{color:##999999; font-family:Arial,Helvetica,sans-serif; font-size:xx-small;} + ''' keep_only_tags = [ - dict(name='div', attrs={'id':["ctl00_cphpagemiddle_reparticle_ctl00_divfullstorytext","ctl00_cphpagemiddle_reparticle_ctl00_divartpic","ctl00_cphpagemiddle_reparticle_ctl00_divfspheading", "ctl00_cphpagemiddle_reparticle_ctl00_divartpiccaption", "ctl00_cphpagemiddle_reparticle_ctl00_divartpiccredit","ctl00_cphpagemiddle_reparticle_ctl00_divfspintro", "ctl00_cphpagemiddle_reparticle_ctl00_divartbyline", ]}), + dict(name='div', attrs={'id':["ctl00_cphpagemiddle_reparticle_ctl00_divfullstorytext","ctl00_cphpagemiddle_reparticle_ctl00_divartpic","ctl00_cphpagemiddle_reparticle_ctl00_divfspheading", "ctl00_cphpagemiddle_reparticle_ctl00_divartpiccaption", "ctl00_cphpagemiddle_reparticle_ctl00_divartpiccredit","ctl00_cphpagemiddle_reparticle_ctl00_divfspintro", "ctl00_cphpagemiddle_reparticle_ctl00_divartbyline", "ctl00_cphpagemiddle_divglitteratiregulars","ctl00_cphpagemiddle_divcartoon","feedbackslatestfirst","ctl00_cphpagemiddle_divregulars","ctl00_cphpagemiddle_divquotes"]}), ] - remove_tags = [dict(name=['script','object'])] + remove_tags = [dict(name=['script','object','hr']),] def get_browser(self): br = BasicNewsRecipe.get_browser(self) @@ -27,12 +38,11 @@ class OutlookIndia(BasicNewsRecipe): br.set_cookiejar(None) return br - def parse_index(self): soup = self.index_to_soup('http://www.outlookindia.com/issues.aspx') -# find cover pic + # find cover pic div = soup.find('div', attrs={'class':re.compile('cententcellpadding')}) if div is None: return None @@ -47,8 +57,8 @@ class OutlookIndia(BasicNewsRecipe): self.cover_url = cover['src'] - # end find cover pic - + # end find cover pic + #find current issue div = soup.find('table', attrs={'id':re.compile('ctl00_cphpagemiddle_dlissues')}) if div is None: return None @@ -58,25 +68,48 @@ class OutlookIndia(BasicNewsRecipe): href = 'http://www.outlookindia.com/' + a['href'] soup = self.index_to_soup(href) + #find current issue + #find the articles in the current issue articles = [] - for a in soup.findAll('a', attrs={'class':'contentpgsubheadinglink'}): + for a in soup.findAll('a', attrs={'class':['contentpgsubheadinglink',"contentpgtext6",]}): if a and a.has_key('href'): + url = 'http://www.outlookindia.com/' + a['href'] else: url ='' + title = self.tag_to_string(a) + desc = '' date = '' - description = '' articles.append({ 'title':title, 'date':date, 'url':url, - 'description':description + 'description':desc, }) + for a in soup.findAll('a', attrs={'id':["ctl00_cphpageleft_hlglitterati","ctl00_cphpageleft_hlposcape",]}): + + if a and a.has_key('href'): + + url = 'http://www.outlookindia.com/' + a['href'] + else: + url ='' + + title = self.tag_to_string(a) + + desc = '' + date = '' + articles.append({ + 'title':title, + 'date':date, + 'url':url, + 'description':desc, + }) + return [('Current Issue', articles)] @@ -85,11 +118,15 @@ class OutlookIndia(BasicNewsRecipe): del item['style'] return self.adeify_images(soup) + + def postrocess_html(self, soup, first): - for tag in soup.findAll(name=['table', 'tr', 'td','tbody']): - tag.name = 'div' + for item in soup.findAll(align = "left"): + del item['align'] + for tag in soup.findAll(name=['table', 'tr','td','tbody','ul','li','font','span']): + tag.name = 'div' return soup From 05f7f42400cc90fc43b223309d7a93d1d4a419c7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 24 Aug 2009 08:44:58 -0600 Subject: [PATCH 11/34] IGN:Fix #2152 (Typo in GUI) --- installer/linux/freeze.py | 11 +++- setup.py | 4 +- src/calibre/ebooks/epub/output.py | 2 +- src/calibre/translations/calibre.pot | 65 ++++++++++----------- upload.py | 85 +++++++++++++++++++++------- 5 files changed, 111 insertions(+), 56 deletions(-) diff --git a/installer/linux/freeze.py b/installer/linux/freeze.py index 3b272551ff..c0f4edfd01 100644 --- a/installer/linux/freeze.py +++ b/installer/linux/freeze.py @@ -9,7 +9,7 @@ Create linux binary. ''' def freeze(): - import glob, sys, tarfile, os, textwrap, shutil + import glob, sys, tarfile, os, textwrap, shutil, platform from contextlib import closing from cx_Freeze import Executable, setup from calibre.constants import __version__, __appname__ @@ -19,6 +19,9 @@ def freeze(): from calibre.ebooks.lrf.fonts import FONT_MAP import calibre + is64bit = platform.architecture()[0] == '64bit' + arch = 'x86_64' if is64bit else 'i686' + QTDIR = '/usr/lib/qt4' QTDLLS = ('QtCore', 'QtGui', 'QtNetwork', 'QtSvg', 'QtXml', @@ -47,7 +50,8 @@ def freeze(): '/usr/lib/libxslt.so.1', '/usr/lib/libxslt.so.1', '/usr/lib/libgthread-2.0.so.0', - '/usr/lib/gcc/i686-pc-linux-gnu/4.3.3/libstdc++.so.6', + '/usr/lib/gcc/***-pc-linux-gnu/4.4.1/libstdc++.so.6'.replace('***', + arch).replace('i686', 'i486'), '/usr/lib/libpng12.so.0', '/usr/lib/libexslt.so.0', '/usr/lib/libMagickWand.so', @@ -228,7 +232,8 @@ def freeze(): open(os.path.join(FREEZE_DIR, 'manifest'), 'wb').write('\n'.join(exes)) print 'Creating archive...' - dist = open(os.path.join(DIST_DIR, 'calibre-%s-i686.tar.bz2'%__version__), 'wb') + dist = open(os.path.join(DIST_DIR, 'calibre-%s-%s.tar.bz2'%(__version__, + arch)), 'wb') with closing(tarfile.open(fileobj=dist, mode='w:bz2', format=tarfile.PAX_FORMAT)) as tf: for f in walk(FREEZE_DIR): diff --git a/setup.py b/setup.py index 439eef6ce2..ed372920de 100644 --- a/setup.py +++ b/setup.py @@ -71,7 +71,7 @@ if __name__ == '__main__': tag_release, upload_demo, build_linux, build_windows, \ build_osx, upload_installers, upload_user_manual, \ upload_to_pypi, stage3, stage2, stage1, upload, \ - upload_rss, betas + upload_rss, betas, build_linux32, build_linux64 entry_points['console_scripts'].append( 'calibre_postinstall = calibre.linux:post_install') @@ -258,6 +258,8 @@ if __name__ == '__main__': 'tag_release' : tag_release, 'upload_demo' : upload_demo, 'build_linux' : build_linux, + 'build_linux32' : build_linux32, + 'build_linux64' : build_linux64, 'build_windows' : build_windows, 'build_osx' : build_osx, 'upload_installers': upload_installers, diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py index 8955906501..6c38a7d4d3 100644 --- a/src/calibre/ebooks/epub/output.py +++ b/src/calibre/ebooks/epub/output.py @@ -78,7 +78,7 @@ class EPUBOutput(OutputFormatPlugin): ), OptionRecommendation(name='no_default_epub_cover', recommended_value=False, - help=_('Normally, if the input file ahs no cover and you don\'t' + help=_('Normally, if the input file has no cover and you don\'t' ' specify one, a default cover is generated with the title, ' 'authors, etc. This option disables the generation of this cover.')), diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index cf2695ebb1..92b93cb92b 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.8\n" -"POT-Creation-Date: 2009-08-23 11:19+MDT\n" -"PO-Revision-Date: 2009-08-23 11:19+MDT\n" +"POT-Creation-Date: 2009-08-24 08:38+MDT\n" +"PO-Revision-Date: 2009-08-24 08:38+MDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -937,7 +937,7 @@ msgid "Split all HTML files larger than this size (in KB). This is necessary as msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:81 -msgid "Normally, if the input file ahs no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover." +msgid "Normally, if the input file has no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover." msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/fb2/fb2ml.py:123 @@ -3074,109 +3074,109 @@ msgstr "" msgid "new email address" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:507 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:508 msgid "No valid plugin path" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:508 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:509 msgid "%s is not a valid plugin path" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:511 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:512 msgid "Choose plugin" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:523 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:524 msgid "Plugin cannot be disabled" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:524 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:525 msgid "The plugin: %s cannot be disabled" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:533 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:534 msgid "Plugin not customizable" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:534 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:535 msgid "Plugin: %s does not need customization" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:558 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:559 msgid "Customize %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:568 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:569 msgid "Cannot remove builtin plugin" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:569 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:570 msgid " cannot be removed. It is a builtin plugin. Try disabling it instead." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:602 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:603 msgid "Error log:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:609 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:610 msgid "Access log:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:634 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:635 #: /home/kovid/work/calibre/src/calibre/gui2/main.py:564 msgid "Failed to start content server" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:658 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:659 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:469 msgid "Select location for books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:675 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:676 msgid "Invalid size" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:676 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:677 msgid "The size %s is invalid. must be of the form widthxheight" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:720 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:725 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:721 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:726 msgid "Invalid database location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:721 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:722 msgid "Invalid database location " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:722 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:723 msgid "
Must be a directory." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:726 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:727 msgid "Invalid database location.
Cannot write to " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:763 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:764 msgid "Checking database integrity" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:782 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:783 #: /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/dialogs/config/__init__.py:783 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:784 msgid "Failed to check database integrity" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:788 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:789 msgid "Some inconsistencies found" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:789 +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:790 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 "" @@ -6072,7 +6072,7 @@ msgstr "" msgid "Password to access your calibre library. Username is " msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/server.py:523 +#: /home/kovid/work/calibre/src/calibre/library/server.py:526 msgid "" "[options]\n" "\n" @@ -6219,7 +6219,7 @@ msgid "\tFailed links:" msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:682 -msgid "Could not fetch article. Run with --debug to see the reason" +msgid "Could not fetch article. Run with -vv to see the reason" msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:703 @@ -6309,6 +6309,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_7dias.py:23 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_ambito.py:61 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_axxon_news.py:21 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_buenosaireseconomico.py:23 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_clarin.py:26 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_criticadigital.py:17 @@ -6422,7 +6423,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nytimes.py:17 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nytimes_sub.py:17 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_ourdailybread.py:16 -#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_outlook_india.py:15 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_outlook_india.py:17 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_phd_comics.py:16 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_physics_today.py:11 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_physics_world.py:8 diff --git a/upload.py b/upload.py index 8dac5af79c..e82946af37 100644 --- a/upload.py +++ b/upload.py @@ -4,7 +4,7 @@ __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' import shutil, os, glob, re, cStringIO, sys, tempfile, time, textwrap, socket, \ - struct, subprocess + struct, subprocess, platform from datetime import datetime from setuptools.command.build_py import build_py as _build_py, convert_path from distutils.core import Command @@ -24,6 +24,7 @@ HTML2LRF = "src/calibre/ebooks/lrf/html/demo" TXT2LRF = "src/calibre/ebooks/lrf/txt/demo" MOBILEREAD = 'ftp://dev.mobileread.com/calibre/' +is64bit = platform.architecture()[0] == '64bit' def get_ip_address(ifname): import fcntl @@ -35,7 +36,7 @@ def get_ip_address(ifname): )[20:24]) try: - HOST=get_ip_address('eth0') + HOST=get_ip_address('br0') except: try: HOST=get_ip_address('wlan0') @@ -481,12 +482,12 @@ class upload_demo(OptionlessCommand): def installer_name(ext): if ext in ('exe', 'dmg'): return 'dist/%s-%s.%s'%(__appname__, __version__, ext) - return 'dist/%s-%s-i686.%s'%(__appname__, __version__, ext) + ans = 'dist/%s-%s-i686.%s'%(__appname__, __version__, ext) + if is64bit: + ans = ans.replace('i686', 'x86_64') + return ans - -class build_linux(OptionlessCommand): - description = 'Build linux installer' - def run(self): +def _build_linux(): installer = installer_name('tar.bz2') locals = {} exec open('installer/linux/freeze.py') in locals @@ -495,9 +496,15 @@ class build_linux(OptionlessCommand): raise Exception('Failed to build installer '+installer) return os.path.basename(installer) +class build_linux64(OptionlessCommand): + description = 'Build linux 64bit installer' + + def run(self): + return _build_linux() + class VMInstaller(OptionlessCommand): - user_options = [('dont-shutdown', 'd', 'Dont shutdown Vm after build')] + user_options = [('dont-shutdown', 'd', 'Dont shutdown VM after build')] boolean_options = ['dont-shutdown'] def initialize_options(self): @@ -521,10 +528,13 @@ class VMInstaller(OptionlessCommand): def get_build_script(self, subs): return self.BUILD_SCRIPT%subs - def start_vm(self, ssh_host, build_script, sleep=75): - build_script = self.get_build_script(build_script) + def run_vm(self): vmware = ('vmware', '-q', '-x', '-n', self.VM) - Popen(vmware) + self.__p = Popen(vmware) + + def start_vm(self, ssh_host, build_script, sleep=75): + self.run_vm() + build_script = self.get_build_script(build_script) t = tempfile.NamedTemporaryFile(suffix='.sh') t.write(build_script) t.flush() @@ -537,6 +547,28 @@ class VMInstaller(OptionlessCommand): check_call(('scp', t.name, ssh_host+':build-calibre')) check_call('ssh -t %s bash build-calibre'%ssh_host, shell=True) +class build_linux32(VMInstaller): + + description = 'Build linux 32bit installer' + + def run_vm(self): + self.__p = Popen('/vmware/bin/linux_build') + + def run(self): + if is64bit: + installer = installer_name('tar.bz2').replace('x86_64', 'i686') + self.start_vm('linux_build', ('python setup.py build_ext', + 'python', 'setup.py build_linux32')) + check_call(('scp', 'linux_build:build/calibre/dist/*.tar.bz2', 'dist')) + if not os.path.exists(installer): + raise Exception('Failed to build installer '+installer) + if not self.dont_shutdown: + Popen(('ssh', 'linux_build', 'sudo', '/sbin/poweroff')) + return os.path.basename(installer) + else: + return _build_linux() + + class build_windows(VMInstaller): description = 'Build windows installer' VM = '/mnt/backup/calibre_windows_xp_home/calibre_windows_xp_home.vmx' @@ -573,9 +605,7 @@ class build_windows(VMInstaller): class build_osx(VMInstaller): description = 'Build OS X app bundle' - VM = '/mnt/backup/calibre_os_x/Mac OSX.vmx' - if not os.path.exists(VM): - VM = '/home/kovid/calibre_os_x/Mac OSX.vmx' + VM = '/vmware/calibre_os_x/Mac OSX.vmx' def get_build_script(self, subs): return (self.BUILD_SCRIPT%subs).replace('rm ', 'sudo rm ') @@ -583,13 +613,25 @@ class build_osx(VMInstaller): def run(self): installer = installer_name('dmg') python = '/Library/Frameworks/Python.framework/Versions/Current/bin/python' - self.start_vm('osx', ('sudo %s setup.py develop'%python, python, + if os.path.exists('/dev/kvm'): + check_call('sudo rmmod -w kvm-intel kvm', shell=True) + check_call('sudo /etc/init.d/vmware restart', shell=True) + self.start_vm('osx_build', ('sudo %s setup.py develop'%python, python, 'installer/osx/freeze.py')) - check_call(('scp', 'osx:build/calibre/dist/*.dmg', 'dist')) + check_call(('scp', 'osx_build:build/calibre/dist/*.dmg', 'dist')) if not os.path.exists(installer): raise Exception('Failed to build installer '+installer) if not self.dont_shutdown: - Popen(('ssh', 'osx', 'sudo', '/sbin/shutdown', '-h', 'now')) + Popen(('ssh', 'osx_build', 'sudo', '/sbin/shutdown', '-h', 'now')) + time.sleep(20) + while True: + try: + check_call('sudo /etc/init.d/vmware stop', shell=True) + break + except: + pass + check_call('sudo modprobe kvm-intel', shell=True) + return os.path.basename(installer) @@ -661,8 +703,9 @@ class upload_installers(OptionlessCommand): def run(self): print 'Uploading installers...' - for i in ('dmg', 'exe', 'tar.bz2'): - self.upload_installer(installer_name(i)) + installers = list(map(installer_name, ('dmg', 'exe', 'tar.bz2'))) + installers.append(installers[-1].replace('x86_64', 'i686')) + map(self.upload_installer, installers) check_call('''ssh divok echo %s \\> %s/latest_version'''\ %(__version__, DOWNLOADS), shell=True) @@ -715,6 +758,10 @@ class stage3(OptionlessCommand): OptionlessCommand.run(self) self.misc() +class build_linux(OptionlessCommand): + description = 'Build linux installers' + sub_commands = [ ('build_linux64', None), ('build_linux32', None) ] + class stage2(OptionlessCommand): description = 'Stage 2 of the build process' sub_commands = [ From 745723b60cba21bd24d3c127d3b0f5ae1de6ee36 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 24 Aug 2009 08:57:37 -0600 Subject: [PATCH 12/34] Fix #3270 (Chapter detection keywords should not be translated) --- src/calibre/gui2/convert/__init__.py | 2 +- .../gui2/convert/structure_detection.py | 3 +- .../gui2/convert/structure_detection.ui | 20 ------- src/calibre/translations/calibre.pot | 54 ++++++------------- 4 files changed, 20 insertions(+), 59 deletions(-) diff --git a/src/calibre/gui2/convert/__init__.py b/src/calibre/gui2/convert/__init__.py index 70223acb70..bbab3a1edd 100644 --- a/src/calibre/gui2/convert/__init__.py +++ b/src/calibre/gui2/convert/__init__.py @@ -34,7 +34,7 @@ class Widget(QWidget): def initialize_options(self, get_option, get_help, db=None, book_id=None): ''' :param get_option: A callable that takes one argument: the option name - and returns the correspoing OptionRecommendation. + and returns the corresponding OptionRecommendation. :param get_help: A callable that takes the option name and return a help string. ''' diff --git a/src/calibre/gui2/convert/structure_detection.py b/src/calibre/gui2/convert/structure_detection.py index 506ee37c45..00c5e30d6b 100644 --- a/src/calibre/gui2/convert/structure_detection.py +++ b/src/calibre/gui2/convert/structure_detection.py @@ -28,11 +28,12 @@ class StructureDetectionWidget(Widget, Ui_Form): 'remove_footer', 'footer_regex'] ) self.db, self.book_id = db, book_id + for x in ('pagebreak', 'rule', 'both', 'none'): + self.opt_chapter_mark.addItem(x) self.initialize_options(get_option, get_help, db, book_id) self.opt_chapter.set_msg(_('Detect chapters at (XPath expression):')) self.opt_page_breaks_before.set_msg(_('Insert page breaks before ' '(XPath expression):')) - def pre_commit_check(self): for x in ('header_regex', 'footer_regex'): x = getattr(self, 'opt_'+x) diff --git a/src/calibre/gui2/convert/structure_detection.ui b/src/calibre/gui2/convert/structure_detection.ui index eebc0f0d53..6952abce96 100644 --- a/src/calibre/gui2/convert/structure_detection.ui +++ b/src/calibre/gui2/convert/structure_detection.ui @@ -29,26 +29,6 @@ - - - pagebreak - - - - - rule - - - - - both - - - - - none - - diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 92b93cb92b..082d179847 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.8\n" -"POT-Creation-Date: 2009-08-24 08:38+MDT\n" -"PO-Revision-Date: 2009-08-24 08:38+MDT\n" +"POT-Creation-Date: 2009-08-24 08:57+MDT\n" +"PO-Revision-Date: 2009-08-24 08:57+MDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -2006,7 +2006,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:38 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:39 #: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:28 -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:71 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:67 #: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:61 #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:28 #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:35 @@ -2523,91 +2523,71 @@ msgstr "" msgid "Fine tune the detection of chapter headings and other document structure." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:32 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:34 msgid "Detect chapters at (XPath expression):" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:33 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:35 msgid "Insert page breaks before (XPath expression):" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:43 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:44 #: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:72 msgid "Invalid regular expression" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:44 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:45 #: /home/kovid/work/calibre/src/calibre/gui2/widgets.py:73 msgid "Invalid regular expression: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:49 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:50 #: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:38 msgid "Invalid XPath" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:50 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection.py:51 #: /home/kovid/work/calibre/src/calibre/gui2/convert/toc.py:39 msgid "The XPath expression %s is invalid." msgstr "" #: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:72 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:68 msgid "Chapter &mark:" msgstr "" #: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:73 -msgid "pagebreak" -msgstr "" - -#: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:74 -msgid "rule" -msgstr "" - -#: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:75 -msgid "both" -msgstr "" - -#: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:76 -msgid "none" -msgstr "" - -#: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:77 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:69 msgid "Remove first &image" msgstr "" #: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:78 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:70 msgid "Insert &metadata as page at start of book" msgstr "" #: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:79 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:71 msgid "&Footer regular expression:" msgstr "" #: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:72 msgid "&Preprocess input file to possibly improve structure detection" msgstr "" #: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:81 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:73 msgid "&Header regular expression:" msgstr "" #: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:82 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:74 msgid "Remove F&ooter" msgstr "" #: -#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:83 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:75 msgid "Remove H&eader" msgstr "" From 8293226c5f1e10318d08ca891da4f8560a0f851a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 24 Aug 2009 10:56:04 -0600 Subject: [PATCH 13/34] Fix bug in OS X and Windows where instead of remebering previously selected directory, the parent directory would be remembered instead --- src/calibre/gui2/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index eb93602fd1..8564fda328 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -450,12 +450,13 @@ class FileDialog(QObject): if os.path.exists(f): self.selected_files.append(f) if self.selected_files: - self.selected_files = [qstring_to_unicode(q) for q in self.selected_files] - dynamic[self.dialog_name] = os.path.dirname(self.selected_files[0]) + self.selected_files = [unicode(q) for q in self.selected_files] + saved_loc = self.selected_files[0] + if os.path.isfile(saved_loc): + saved_loc = os.path.dirname(saved_loc) + dynamic[self.dialog_name] = saved_loc self.accepted = bool(self.selected_files) - - def get_files(self): if islinux and self.fd.result() != self.fd.Accepted: return tuple() From 3a0311d973152d615658034a6596b7e251b611f5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 10:50:28 -0600 Subject: [PATCH 14/34] On a new install choose an empty directory as library location by default. Also only transfer known sub-directories when moving the library. Fixes #3282 (Installing a new install of Calibre on a WinXP machine the library location is insane.) --- src/calibre/gui2/main.py | 5 ++++- src/calibre/library/database2.py | 13 ++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 98ae6a3796..1f035d4bae 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -424,9 +424,12 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): error_dialog(self, _('Bad database location'), _('Bad database location')+':'+self.library_path, det_msg=traceback.format_exc()).exec_() + x = os.path.expanduser('~'+os.sep+'library') + if not os.path.exists(x): + os.makedirs(x) dir = unicode(QFileDialog.getExistingDirectory(self, _('Choose a location for your ebook library.'), - os.path.expanduser('~'))) + x)) if not dir: QCoreApplication.exit(1) raise SystemExit(1) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index c605be0879..c48b238c8d 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1447,7 +1447,18 @@ class LibraryDatabase2(LibraryDatabase): def move_library_to(self, newloc, progress=lambda x: x): if not os.path.exists(newloc): os.makedirs(newloc) - items = os.listdir(self.library_path) + items = set(os.listdir(self.library_path)) + paths = set([]) + for x in self.data.universal_set(): + path = self.path(x, index_is_id=True) + path = path.split(os.sep)[0] + paths.add(path) + paths.add('metadata.db') + if not self.is_case_sensitive: + items = set([x.lower() for x in items]) + paths = set([x.lower() for x in paths]) + items = items.intersection(paths) + old_dirs = set([]) for i, x in enumerate(items): src = os.path.join(self.library_path, x) From 5e65dd3499fc14d59511ad945e8e662b28fbc50a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 11:09:19 -0600 Subject: [PATCH 15/34] TXT Output: remove excessive newlines --- src/calibre/ebooks/txt/txtml.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/txt/txtml.py b/src/calibre/ebooks/txt/txtml.py index 24a9fb0878..206dff50ed 100644 --- a/src/calibre/ebooks/txt/txtml.py +++ b/src/calibre/ebooks/txt/txtml.py @@ -32,7 +32,7 @@ BLOCK_STYLES = [ ] class TXTMLizer(object): - + def __init__(self, log): self.log = log @@ -90,8 +90,8 @@ class TXTMLizer(object): text = re.sub('[ ]+', ' ', text) # Remove excessive newlines. - #text = re.sub('\n[ ]+\n', '\n\n', text) - #text = re.sub('\n{3,}', '\n\n', text) + text = re.sub('\n[ ]+\n', '\n\n', text) + text = re.sub('\n{3,}', '\n\n', text) # Replace spaces at the beginning and end of lines text = re.sub('(?imu)^[ ]+', '', text) From a04024d455c8ba35ae8a10c65b8cd359beeb477c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 11:10:44 -0600 Subject: [PATCH 16/34] IGN:New windows build system --- installer/windows/freeze.py | 38 ++++++++-------------- setup.py | 17 +++++----- src/calibre/library/server.py | 12 +++---- upload.py | 59 ++++++++++++++++++++++------------- 4 files changed, 66 insertions(+), 60 deletions(-) diff --git a/installer/windows/freeze.py b/installer/windows/freeze.py index 4dadc8875c..bf64637dab 100644 --- a/installer/windows/freeze.py +++ b/installer/windows/freeze.py @@ -7,15 +7,12 @@ __docformat__ = 'restructuredtext en' Freeze app into executable using py2exe. ''' QT_DIR = 'C:\\Qt\\4.5.2' -LIBUSB_DIR = 'C:\\libusb' +LIBUSB_DIR = r'C:\cygwin\home\kovid\win32\libusb' LIBUNRAR = 'C:\\Program Files\\UnrarDLL\\unrar.dll' -PDFTOHTML = 'C:\\cygwin\\home\\kovid\\poppler-0.10.6\\rel\\pdftohtml.exe' -POPPLER = 'C:\\cygwin\\home\\kovid\\poppler' -IMAGEMAGICK_DIR = 'C:\\ImageMagick' -PDFTK = 'C:\\pdftk.exe' -PODOFO = 'C:\\podofo' -FONTCONFIG_DIR = 'C:\\fontconfig' -VC90 = r'C:\VC90.CRT' +BINARIES = r'C:\cygwin\home\kovid\win32\bin' +IMAGEMAGICK_DIR = r'C:\cygwin\home\kovid\win32\imagemagick' +FONTCONFIG_DIR = r'C:\cygwin\home\kovid\win32\etc' +VC90 = r'C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT' # ModuleFinder can't handle runtime changes to __path__, but win32com uses them import sys @@ -98,25 +95,17 @@ class BuildEXE(py2exe.build_exe.py2exe): shutil.copyfile(f, os.path.join(tdir, os.path.basename(f))) print '\tAdding unrar' shutil.copyfile(LIBUNRAR, os.path.join(PY2EXE_DIR, os.path.basename(LIBUNRAR))) - print '\tAdding poppler' - for x in ('bin\\pdftohtml.exe', 'bin\\poppler-qt4.dll', - 'bin\\freetype.dll', 'bin\\jpeg62.dll'): - shutil.copyfile(os.path.join(POPPLER, x), - os.path.join(PY2EXE_DIR, os.path.basename(x))) - print '\tAdding podofo' - for f in glob.glob(os.path.join(PODOFO, '*.dll')): - shutil.copyfile(f, os.path.join(PY2EXE_DIR, os.path.basename(f))) - + print '\tAdding Binaries' + for x in glob.glob(os.path.join(BINARIES, '*.dll')) + \ + [os.path.join(BINARIES, 'pdftohtml.exe')] + \ + glob.glob(os.path.join(BINARIES, '*.manifest')): + shutil.copyfile(x, os.path.join(PY2EXE_DIR, os.path.basename(x))) print '\tAdding ImageMagick' for f in os.listdir(IMAGEMAGICK_DIR): shutil.copyfile(os.path.join(IMAGEMAGICK_DIR, f), os.path.join(PY2EXE_DIR, f)) print '\tCopying fontconfig' - for f in glob.glob(os.path.join(FONTCONFIG_DIR, '*')): - tgt = os.path.join(PY2EXE_DIR, os.path.basename(f)) - if os.path.isdir(f): - shutil.copytree(f, tgt) - else: - shutil.copyfile(f, tgt) + tgt = os.path.join(PY2EXE_DIR, 'etc') + shutil.copytree(FONTCONFIG_DIR, tgt) print print 'Doing DLL redirection' # See http://msdn.microsoft.com/en-us/library/ms682600(VS.85).aspx @@ -169,8 +158,7 @@ def main(args=sys.argv): 'email.iterators', 'email.generator', 'win32process', 'win32api', 'msvcrt', - 'win32event', 'calibre.ebooks.lrf.any.*', - 'calibre.ebooks.lrf.feeds.*', + 'win32event', 'BeautifulSoup', 'pyreadline', 'pydoc', 'IPython.Extensions.*', 'calibre.web.feeds.recipes.*', diff --git a/setup.py b/setup.py index ed372920de..a7d5b009ab 100644 --- a/setup.py +++ b/setup.py @@ -94,8 +94,8 @@ if __name__ == '__main__': sources=['src/calibre/utils/windows/winutil.c'], libraries=['shell32', 'setupapi'], include_dirs=os.environ.get('INCLUDE', - 'C:/WinDDK/6001.18001/inc/api/;' - 'C:/WinDDK/6001.18001/inc/crt/').split(';'), + 'C:/WinDDK/7600.16385.0/inc/api/;' + 'C:/WinDDK/7600.16385.0/inc/crt/').split(';'), extra_compile_args=['/X'] )) @@ -103,8 +103,8 @@ if __name__ == '__main__': poppler_lib = '/usr/lib' poppler_libs = [] if iswindows: - poppler_inc = r'C:\cygwin\home\kovid\poppler\include\poppler\qt4' - poppler_lib = r'C:\cygwin\home\kovid\poppler\lib' + poppler_inc = r'C:\cygwin\home\kovid\win32\include\poppler\qt4' + poppler_lib = r'C:\cygwin\home\kovid\win32\lib' poppler_libs = ['QtCore4', 'QtGui4'] if isosx: poppler_inc = '/Volumes/sw/build/poppler-0.10.7/qt4/src' @@ -124,9 +124,10 @@ if __name__ == '__main__': print 'POPPLER_LIB_DIR environment variables.' podofo_inc = '/usr/include/podofo' if islinux else \ - 'C:\\podofo\\include\\podofo' if iswindows else \ + r'C:\cygwin\home\kovid\win32\include\podofo' if iswindows else \ '/usr/local/include/podofo' - podofo_lib = '/usr/lib' if islinux else r'C:\podofo' if iswindows else \ + podofo_lib = '/usr/lib' if islinux else \ + r'C:\cygwin\home\kovid\win32\lib' if iswindows else \ '/usr/local/lib' podofo_inc = os.environ.get('PODOFO_INC_DIR', podofo_inc) if os.path.exists(os.path.join(podofo_inc, 'podofo.h')): @@ -141,10 +142,10 @@ if __name__ == '__main__': print 'PODOFO_LIB_DIR environment variables.' fc_inc = '/usr/include/fontconfig' if islinux else \ - r'C:\cygwin\home\kovid\fontconfig\include\fontconfig' if iswindows else \ + r'C:\cygwin\home\kovid\win32\include\fontconfig' if iswindows else \ '/Users/kovid/fontconfig/include/fontconfig' fc_lib = '/usr/lib' if islinux else \ - r'C:\cygwin\home\kovid\fontconfig\lib' if iswindows else \ + r'C:\cygwin\home\kovid\win32\lib' if iswindows else \ '/Users/kovid/fontconfig/lib' diff --git a/src/calibre/library/server.py b/src/calibre/library/server.py index 58cb457971..4ab254555e 100644 --- a/src/calibre/library/server.py +++ b/src/calibre/library/server.py @@ -110,7 +110,7 @@ class LibraryServer(object): ${authors} urn:calibre:${record[FM['id']]} ${timestamp} - + ''')) @@ -120,7 +120,7 @@ class LibraryServer(object): calibre Library $id ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} - + calibre http://calibre.kovidgoyal.net @@ -140,7 +140,7 @@ class LibraryServer(object): calibre Library $id ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} - + calibre http://calibre.kovidgoyal.net @@ -152,19 +152,19 @@ class LibraryServer(object): By Author urn:uuid:fc000fa0-8c23-11de-a31d-0002a5d5c51b ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} - + By Title urn:uuid:1df4fe40-8c24-11de-b4c6-0002a5d5c51b ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} - + By Newest urn:uuid:3c6d4940-8c24-11de-a4d7-0002a5d5c51b ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} - + ''')) diff --git a/upload.py b/upload.py index e82946af37..95d8013985 100644 --- a/upload.py +++ b/upload.py @@ -528,6 +528,27 @@ class VMInstaller(OptionlessCommand): def get_build_script(self, subs): return self.BUILD_SCRIPT%subs + def vmware_started(self): + return 'started' in subprocess.Popen('/etc/init.d/vmware status', shell=True, stdout=subprocess.PIPE).stdout.read() + + def start_vmware(self): + if not self.vmware_started(): + if os.path.exists('/dev/kvm'): + check_call('sudo rmmod -w kvm-intel kvm', shell=True) + subprocess.Popen('sudo /etc/init.d/vmware start', shell=True) + + def stop_vmware(self): + while True: + try: + check_call('sudo /etc/init.d/vmware stop', shell=True) + break + except: + pass + while 'vmblock' in open('/proc/modules').read(): + check_call('sudo rmmod -f vmblock') + check_call('sudo modprobe kvm-intel', shell=True) + + def run_vm(self): vmware = ('vmware', '-q', '-x', '-n', self.VM) self.__p = Popen(vmware) @@ -547,9 +568,18 @@ class VMInstaller(OptionlessCommand): check_call(('scp', t.name, ssh_host+':build-calibre')) check_call('ssh -t %s bash build-calibre'%ssh_host, shell=True) -class build_linux32(VMInstaller): +class KVMInstaller(VMInstaller): + + def run_vm(self): + self.stop_vmware() + self.__p = Popen(self.VM) + + + +class build_linux32(KVMInstaller): description = 'Build linux 32bit installer' + VM = '/vmware/bin/linux_build' def run_vm(self): self.__p = Popen('/vmware/bin/linux_build') @@ -569,25 +599,23 @@ class build_linux32(VMInstaller): return _build_linux() -class build_windows(VMInstaller): +class build_windows(KVMInstaller): description = 'Build windows installer' - VM = '/mnt/backup/calibre_windows_xp_home/calibre_windows_xp_home.vmx' - if not os.path.exists(VM): - VM = '/home/kovid/calibre_windows_xp_home/calibre_windows_xp_home.vmx' + VM = '/vmware/bin/win_build' def run(self): installer = installer_name('exe') - self.start_vm('windows', ('python setup.py develop', + self.start_vm('win_build', ('python setup.py develop', 'python', r'installer\\windows\\freeze.py')) if os.path.exists('build/py2exe'): shutil.rmtree('build/py2exe') - check_call(('scp', '-rp', 'windows:build/%s/build/py2exe'%__appname__, + check_call(('scp', '-rp', 'win_build:build/%s/build/py2exe'%__appname__, 'build')) if not os.path.exists('build/py2exe'): raise Exception('Failed to run py2exe') if not self.dont_shutdown: - Popen(('ssh', 'windows', 'shutdown', '-s', '-t', '0')) + Popen(('ssh', 'win_build', 'shutdown', '-s', '-t', '0')) self.run_windows_install_jammer(installer) return os.path.basename(installer) @@ -613,9 +641,7 @@ class build_osx(VMInstaller): def run(self): installer = installer_name('dmg') python = '/Library/Frameworks/Python.framework/Versions/Current/bin/python' - if os.path.exists('/dev/kvm'): - check_call('sudo rmmod -w kvm-intel kvm', shell=True) - check_call('sudo /etc/init.d/vmware restart', shell=True) + self.start_vmware() self.start_vm('osx_build', ('sudo %s setup.py develop'%python, python, 'installer/osx/freeze.py')) check_call(('scp', 'osx_build:build/calibre/dist/*.dmg', 'dist')) @@ -624,18 +650,9 @@ class build_osx(VMInstaller): if not self.dont_shutdown: Popen(('ssh', 'osx_build', 'sudo', '/sbin/shutdown', '-h', 'now')) time.sleep(20) - while True: - try: - check_call('sudo /etc/init.d/vmware stop', shell=True) - break - except: - pass - check_call('sudo modprobe kvm-intel', shell=True) - + self.stop_vmware() return os.path.basename(installer) - - class upload_installers(OptionlessCommand): description = 'Upload any installers present in dist/' def curl_list_dir(self, url=MOBILEREAD, listonly=1): From cb232d395e4ee4ddab8a134f0ea542df75122337 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 11:11:56 -0600 Subject: [PATCH 17/34] Handle single line paragraphs in PDB files --- src/calibre/ebooks/pdb/ereader/reader.py | 6 +++--- src/calibre/ebooks/pdb/ereader/reader132.py | 4 ++-- src/calibre/ebooks/pdb/ereader/reader202.py | 4 ++-- src/calibre/ebooks/pdb/formatreader.py | 2 +- src/calibre/ebooks/pdb/input.py | 11 +++++++++-- src/calibre/ebooks/pdb/palmdoc/reader.py | 7 ++++--- src/calibre/ebooks/pdb/ztxt/reader.py | 7 ++++--- src/calibre/ebooks/txt/input.py | 7 +------ src/calibre/ebooks/txt/processor.py | 6 +++++- 9 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/calibre/ebooks/pdb/ereader/reader.py b/src/calibre/ebooks/pdb/ereader/reader.py index 7a3298122f..77ca8d6933 100644 --- a/src/calibre/ebooks/pdb/ereader/reader.py +++ b/src/calibre/ebooks/pdb/ereader/reader.py @@ -15,13 +15,13 @@ from calibre.ebooks.pdb.ereader.reader202 import Reader202 class Reader(FormatReader): - def __init__(self, header, stream, log, encoding=None): + def __init__(self, header, stream, log, options): record0_size = len(header.section_data(0)) if record0_size == 132: - self.reader = Reader132(header, stream, log, encoding) + self.reader = Reader132(header, stream, log, options) elif record0_size == 202: - self.reader = Reader202(header, stream, log, encoding) + self.reader = Reader202(header, stream, log, options) else: raise EreaderError('Size mismatch. eReader header record size %s KB is not supported.' % record0_size) diff --git a/src/calibre/ebooks/pdb/ereader/reader132.py b/src/calibre/ebooks/pdb/ereader/reader132.py index a1d1f4294d..d44eb2c561 100644 --- a/src/calibre/ebooks/pdb/ereader/reader132.py +++ b/src/calibre/ebooks/pdb/ereader/reader132.py @@ -47,9 +47,9 @@ class HeaderRecord(object): class Reader132(FormatReader): - def __init__(self, header, stream, log, encoding=None): + def __init__(self, header, stream, log, options): self.log = log - self.encoding = encoding + self.encoding = options.input_encoding self.log.debug('132 byte header version found.') diff --git a/src/calibre/ebooks/pdb/ereader/reader202.py b/src/calibre/ebooks/pdb/ereader/reader202.py index 5057df363e..18281a208e 100644 --- a/src/calibre/ebooks/pdb/ereader/reader202.py +++ b/src/calibre/ebooks/pdb/ereader/reader202.py @@ -33,9 +33,9 @@ class HeaderRecord(object): class Reader202(FormatReader): - def __init__(self, header, stream, log, encoding=None): + def __init__(self, header, stream, log, options): self.log = log - self.encoding = encoding + self.encoding = options.input_encoding self.log.debug('202 byte header version found.') diff --git a/src/calibre/ebooks/pdb/formatreader.py b/src/calibre/ebooks/pdb/formatreader.py index bde6c9ae35..2251eaae04 100644 --- a/src/calibre/ebooks/pdb/formatreader.py +++ b/src/calibre/ebooks/pdb/formatreader.py @@ -11,7 +11,7 @@ __docformat__ = 'restructuredtext en' class FormatReader(object): - def __init__(self, header, stream, log, encoding=None): + def __init__(self, header, stream, log, options): raise NotImplementedError() def extract_content(self, output_dir): diff --git a/src/calibre/ebooks/pdb/input.py b/src/calibre/ebooks/pdb/input.py index 62ae24c7f0..3ad1a6121c 100644 --- a/src/calibre/ebooks/pdb/input.py +++ b/src/calibre/ebooks/pdb/input.py @@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en' import os -from calibre.customize.conversion import InputFormatPlugin +from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation from calibre.ebooks.pdb.header import PdbHeaderReader from calibre.ebooks.pdb import PDBError, IDENTITY_TO_NAME, get_reader @@ -17,6 +17,13 @@ class PDBInput(InputFormatPlugin): description = 'Convert PDB to HTML' file_types = set(['pdb']) + options = set([ + OptionRecommendation(name='single_line_paras', recommended_value=False, + help=_('Normally calibre treats blank lines as paragraph markers. ' + 'With this option it will assume that every line represents ' + 'a paragraph instead.')), + ]) + def convert(self, stream, options, file_ext, log, accelerators): header = PdbHeaderReader(stream) @@ -27,7 +34,7 @@ class PDBInput(InputFormatPlugin): log.debug('Detected ebook format as: %s with identity: %s' % (IDENTITY_TO_NAME[header.ident], header.ident)) - reader = Reader(header, stream, log, options.input_encoding) + reader = Reader(header, stream, log, options) opf = reader.extract_content(os.getcwd()) return opf diff --git a/src/calibre/ebooks/pdb/palmdoc/reader.py b/src/calibre/ebooks/pdb/palmdoc/reader.py index 7e8f3b241c..e1935db566 100644 --- a/src/calibre/ebooks/pdb/palmdoc/reader.py +++ b/src/calibre/ebooks/pdb/palmdoc/reader.py @@ -31,10 +31,11 @@ class HeaderRecord(object): class Reader(FormatReader): - def __init__(self, header, stream, log, encoding=None): + def __init__(self, header, stream, log, options): self.stream = stream self.log = log - self.encoding = encoding + self.encoding = options.input_encoding + self.single_line_paras = options.single_line_paras self.sections = [] for i in range(header.num_sections): @@ -61,7 +62,7 @@ class Reader(FormatReader): txt += self.decompress_text(i) self.log.info('Converting text to OEB...') - html = txt_to_markdown(txt) + html = txt_to_markdown(txt, single_line_paras=self.single_line_paras) with open(os.path.join(output_dir, 'index.html'), 'wb') as index: index.write(html.encode('utf-8')) diff --git a/src/calibre/ebooks/pdb/ztxt/reader.py b/src/calibre/ebooks/pdb/ztxt/reader.py index 0c334556e8..86c5abfe82 100644 --- a/src/calibre/ebooks/pdb/ztxt/reader.py +++ b/src/calibre/ebooks/pdb/ztxt/reader.py @@ -34,10 +34,11 @@ class HeaderRecord(object): class Reader(FormatReader): - def __init__(self, header, stream, log, encoding=None): + def __init__(self, header, stream, log, options): self.stream = stream self.log = log - self.encoding = encoding + self.encoding = options.input_encoding + self.single_line_paras = options.single_line_paras self.sections = [] for i in range(header.num_sections): @@ -76,7 +77,7 @@ class Reader(FormatReader): txt += self.decompress_text(i) self.log.info('Converting text to OEB...') - html = txt_to_markdown(txt) + html = txt_to_markdown(txt, single_line_paras=self.single_line_paras) with open(os.path.join(output_dir, 'index.html'), 'wb') as index: index.write(html.encode('utf-8')) diff --git a/src/calibre/ebooks/txt/input.py b/src/calibre/ebooks/txt/input.py index 493fdf3967..75dd516360 100644 --- a/src/calibre/ebooks/txt/input.py +++ b/src/calibre/ebooks/txt/input.py @@ -31,14 +31,9 @@ class TXTInput(InputFormatPlugin): log.debug('Reading text from file...') txt = stream.read().decode(ienc, 'replace') - if options.single_line_paras: - txt = txt.replace('\r\n', '\n') - txt = txt.replace('\r', '\n') - txt = txt.replace('\n', '\n\n') - log.debug('Running text though markdown conversion...') try: - html = txt_to_markdown(txt) + html = txt_to_markdown(txt, single_line_paras=options.single_line_paras) except RuntimeError: raise ValueError('This txt file has malformed markup, it cannot be' 'converted by calibre. See http://daringfireball.net/projects/markdown/syntax') diff --git a/src/calibre/ebooks/txt/processor.py b/src/calibre/ebooks/txt/processor.py index ddb9b6a121..3005d633b8 100644 --- a/src/calibre/ebooks/txt/processor.py +++ b/src/calibre/ebooks/txt/processor.py @@ -13,7 +13,11 @@ __license__ = 'GPL v3' __copyright__ = '2009, John Schember ' __docformat__ = 'restructuredtext en' -def txt_to_markdown(txt, title=''): +def txt_to_markdown(txt, title='', single_line_paras=False): + if single_line_paras: + txt = txt.replace('\r\n', '\n') + txt = txt.replace('\r', '\n') + txt = txt.replace('\n', '\n\n') md = markdown.Markdown( extensions=['footnotes', 'tables', 'toc'], safe_mode=False,) From ab77e05d3023be816e71c57a2d17060005bc970a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 14:07:49 -0600 Subject: [PATCH 18/34] IGN:Misc. fixes --- installer/windows/build_installer.py | 2 +- installer/windows/calibre/calibre.mpi | 19 +- installer/windows/freeze.py | 3 +- src/calibre/debug.py | 3 +- src/calibre/gui2/convert/pdb_input.py | 19 ++ src/calibre/gui2/convert/pdb_input.ui | 41 ++++ src/calibre/gui2/main.py | 13 +- src/calibre/gui2/wizard/__init__.py | 14 +- src/calibre/manual/faq.rst | 6 + src/calibre/translations/calibre.pot | 314 ++++++++++++++------------ upload.py | 2 +- 11 files changed, 268 insertions(+), 168 deletions(-) create mode 100644 src/calibre/gui2/convert/pdb_input.py create mode 100644 src/calibre/gui2/convert/pdb_input.ui diff --git a/installer/windows/build_installer.py b/installer/windows/build_installer.py index 01720bb2c0..24a8768ded 100644 --- a/installer/windows/build_installer.py +++ b/installer/windows/build_installer.py @@ -36,7 +36,7 @@ def run_install_jammer(installer_name='<%AppName%>-<%Version%><%Ext%>', build_fo compression = 'zlib' if build_for_release: cmdline += ['--build-for-release'] - #compression = 'lzma (solid)' + compression = 'lzma (solid)' cmdline += ['-DCompressionMethod', compression] cmdline += ['--build', mpi] #print 'Running installjammer with cmdline:' diff --git a/installer/windows/calibre/calibre.mpi b/installer/windows/calibre/calibre.mpi index a371bb9587..42f30224b0 100644 --- a/installer/windows/calibre/calibre.mpi +++ b/installer/windows/calibre/calibre.mpi @@ -232,12 +232,10 @@ test } FileGroup ::BEF8D398-58BA-1F66-39D6-D4A63D5BEEF9 -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows TarArchive ZipArchive FreeBSD-5-x86 FreeBSD-6-x86 FreeBSD-7-x86 Linux-x86_64 Solaris-x86} -name {Program Files} -parent FileGroups File ::8E5D85A4-7608-47A1-CF7C-309060D5FF40 -filemethod {Always overwrite files} -type dir -directory <%InstallDir%> -name /home/kovid/work/calibre/build/py2exe -parent BEF8D398-58BA-1F66-39D6-D4A63D5BEEF9 -File ::FC870EE7-667B-481F-113B-B4504DFCCFA5 -type dir -name bin -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::377C588B-B324-CA09-ED49-4DB5F82A15ED -type dir -name etc -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::55DE4B9F-0881-FF51-E2BA-EC72B5D3425C -type dir -name fonts -parent 377C588B-B324-CA09-ED49-4DB5F82A15ED File ::A27B68D9-43A6-B994-3091-E829AFBA340D -type dir -name conf.d -parent 55DE4B9F-0881-FF51-E2BA-EC72B5D3425C File ::974ADD48-88E5-BC7A-1963-928A245F133A -type dir -name conf.avail -parent 55DE4B9F-0881-FF51-E2BA-EC72B5D3425C -File ::5E5273D8-3423-8DC8-83C4-BE000069A803 -name fonts.dtd -parent 55DE4B9F-0881-FF51-E2BA-EC72B5D3425C File ::32D7DBE0-E0B1-5BDD-66C5-2A13D8BC8F90 -name fonts.conf -parent 55DE4B9F-0881-FF51-E2BA-EC72B5D3425C File ::B95D03D4-EA59-F00E-59E1-BA05758879DA -type dir -name imageformats -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A624029D-AE0F-49A5-4DAC-7720CDCAB271 -name qmng4.dll -parent B95D03D4-EA59-F00E-59E1-BA05758879DA @@ -337,7 +335,6 @@ File ::2F90282D-B59F-B6BA-090B-45858AF7F3B2 -name IM_MOD_RL_clipboard_.dll -pare File ::B512D139-B295-D7C3-F0B4-43775849CF58 -name numpy.core._sort.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A2C063AC-2F12-9260-501A-0E8BD0B8A932 -name calibre.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::439B6D05-7DE6-061D-4BCC-3F04F4FA2FA2 -name IM_MOD_RL_png_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::BA464D11-BBCE-DEDA-C354-0C7BE60FAA05 -name IM_MOD_RL_braille_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::8F9FF823-AF6D-A288-8AE6-7D74F55DCE29 -name CORE_RL_bzlib_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::57A3F5D5-BFC8-CB38-5A57-548EE0DB033B -name QtNetwork4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4DB7E8DE-905A-822A-AF14-17BD5ACEF915 -name IM_MOD_RL_wmf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -361,7 +358,6 @@ File ::A6419A84-6C22-784E-6D84-D09972770770 -name unicodedata.pyd -parent 8E5D85 File ::E658FBE0-5860-D041-12D3-76ADD18F804B -name servicemanager.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C98A6FC4-E341-7FD4-005C-DA2B384E11D8 -name win32api.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::ADA36EEA-7DE1-447C-B1AB-A4908E65E2CD -name IM_MOD_RL_ipl_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::53C2EC15-850F-8F49-6425-C228FB6E6D0E -name libfontconfig-1.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::EDE6F457-C83F-C5FA-9AF4-38FDFF17D929 -name PIL._imagingtk.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::09D0906E-3611-3DB7-32CF-A140585694A7 -name win32pdh.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4C84F0DC-7157-0C90-2062-180139B03E25 -name IM_MOD_RL_rgb_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -384,17 +380,14 @@ File ::404A98F1-84FD-B6D0-B130-354EECD9253C -name IM_MOD_RL_emf_.dll -parent 8E5 File ::17034C34-403E-B405-99C1-F80B7F00E27C -name log.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::34E63A2C-65C5-0A84-ACF1-BD6A844D4579 -name pythoncom26.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::2F20484B-53B8-B08E-B691-C5B2D49A9CB4 -name QtWebKit4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::8AF134C8-9189-3F9A-A081-9143FFD44C45 -name freetype6.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::E8A4442D-D0D3-31CD-997A-3CEB641CF5B7 -name IM_MOD_RL_mtv_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::0CA87D0B-5A04-1439-AEE8-C97072D47BA7 -name CORE_RL_tiff_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::AC24F520-88D4-D1CF-5797-27C715CE8ACA -name pyexpat.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::16848F38-71CD-55B8-4D96-1537F6773744 -name IM_MOD_RL_dps_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::33A46CC5-BAC4-5863-C83D-303DCCA0CAA1 -name tk85.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::81116DD3-1715-AA87-472F-544FC616EDAF -name IM_MOD_RL_dcm_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::335A4CFB-5C2D-44E4-C438-7018E8244C3D -name ebook-viewer.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::62A16C3B-ED9C-5187-2807-58857DF3A990 -name calibre-debug.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::55ECA7B7-279A-F51D-81C2-C8DC44CF0E22 -name select.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::A6AF5ECC-A981-4CBD-DBEE-303A9340C603 -name IM_MOD_RL_xps_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::5BCBF71F-18E7-5C52-E3F5-7D7F3028AD46 -name locale.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::5C9FA94C-B8B0-A94B-548D-1D24FDEA5770 -name CORE_RL_wand_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::E39E60BE-DE77-AB8C-42C6-5A7D7DC073E3 -name IM_MOD_RL_ttf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -443,12 +436,10 @@ File ::396B4F78-FB45-C0B2-ACB3-97769CF5CD5D -name msvcr90.dll -parent 8E5D85A4-7 File ::1DE767EE-4891-4E54-422D-67A4DFF8C3B5 -name lrfviewer.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::AFFEC28A-615C-E3E6-0026-CCE2594A6D25 -name calibre-server.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::2C64F86B-9366-B52D-F7B2-5BBD51F6982A -name IM_MOD_RL_pwp_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::F4B2EF9C-EB18-B865-6E99-75CFB9B60D87 -name IM_MOD_RL_dds_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::38770D87-6CA9-9E3E-FBA1-A8CCFCD88FB5 -name IM_MOD_RL_fpx_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::BE2D7BC3-D294-AF3F-65E7-3B372DEFDE36 -name PIL._imaging.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::200B9AEC-809F-75B7-DC12-A51BFC2A6F93 -name PyQt4.QtSvg.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::52132A31-D3AE-C617-7568-BF2AF46B5D74 -name IM_MOD_RL_pcl_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::F94472C3-C8D0-950F-5ED9-1611D1CE30E5 -name IM_MOD_RL_inline_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::055ADB4B-20C5-E071-442F-4DA0A8D6F3C5 -name english.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::B10B6B91-0C03-642D-90D8-37B607B164AD -name IM_MOD_RL_wpg_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::BFBB144B-1794-8304-9772-F103A42F2CA4 -name IM_MOD_RL_pdb_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -503,7 +494,6 @@ File ::9BA85EE5-1754-67AF-736D-481CDCC72DD2 -name _imagingft.pyd -parent 8E5D85A File ::6254DD0C-8F2C-D4AE-2107-2597D542C181 -name IM_MOD_RL_matte_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::F159D566-88D6-C347-3E3C-55C2DDFC5FD0 -name IM_MOD_RL_mono_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::B873CAA2-011F-94C3-7977-FF344E53C44F -name CORE_RL_jbig_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::7004FCB8-C6F4-C7AF-08E4-B6151B2F7050 -name tcl85.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::6921F62A-4015-4C9F-98A6-BCBBC43B698E -name msvcm90.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::7276E0CA-C205-4B18-19A3-157F1B8523FB -name IM_MOD_RL_xtrn_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::7B9624A9-88B4-C61E-6771-9A34FB6CA3B5 -name PyQt4.QtGui.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -567,6 +557,15 @@ File ::9E4E5E8F-30C0-E631-9516-2AE01A5CA0E9 -name ebook-device.exe.local -parent File ::7BE6B538-70D5-A7EB-5F91-E14CE57B394B -name calibre-complete.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C4E40030-3EE0-8B05-E6B9-89E81433EE1F -name phonon4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::9E84342F-36ED-7ED3-8F90-1EC55267BCFC -name poppler-qt4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::86BA442C-90C9-A4E6-1D3E-D144E5F326C1 -name msvcp71.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::11FBAD0B-A2DB-C28A-85B8-D6A22706864F -name mfc71.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::4B9FB3E6-B807-65CC-826D-A398E964D00C -name IM_MOD_RL_hdf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::3E201C0C-C7CC-5785-74F6-A6CC7F50A15A -name msvcr71.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::2EE42149-1C12-CCA9-9089-AE1809098D0A -name jpeg62.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::B1FD37B4-E91B-DC1C-1C69-FB2E10EB93AE -name libtiff3.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::15E09D95-97D6-92A9-CC4D-120885E4DDAD -name freetype.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::D954BC75-8166-EC1B-D91B-C9779248AA14 -name fontconfig.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::1F3C052A-A5E0-5C65-8D42-EBF44FBE138D -name podofo.dll.manifest -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 Component ::F6829AB7-9F66-4CEE-CA0E-21F54C6D3609 -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows FreeBSD-5-x86 FreeBSD-6-x86 FreeBSD-7-x86 Linux-x86_64 Solaris-x86} -name Main -parent Components SetupType ::D9ADE41C-B744-690C-2CED-CF826BF03D2E -setup Install -active Yes -platforms {AIX-ppc FreeBSD-4-x86 FreeBSD-x86 HPUX-hppa Linux-x86 Solaris-sparc Windows FreeBSD-5-x86 FreeBSD-6-x86 FreeBSD-7-x86 Linux-x86_64 Solaris-x86} -name Typical -parent SetupTypes diff --git a/installer/windows/freeze.py b/installer/windows/freeze.py index bf64637dab..8c5feda212 100644 --- a/installer/windows/freeze.py +++ b/installer/windows/freeze.py @@ -171,7 +171,8 @@ def main(args=sys.argv): 'excludes' : ["Tkconstants", "Tkinter", "tcl", "_imagingtk", "ImageTk", "FixTk" ], - 'dll_excludes' : ['mswsock.dll'], + 'dll_excludes' : ['mswsock.dll', 'tcl85.dll', + 'MSVCP90.dll', 'tk85.dll'], }, }, diff --git a/src/calibre/debug.py b/src/calibre/debug.py index b7fb55f4aa..0d38cb4a69 100644 --- a/src/calibre/debug.py +++ b/src/calibre/debug.py @@ -135,7 +135,8 @@ def debug_device_driver(): print 'failed' continue success = True - print 'Main memory:', repr(dev._main_prefix) + if hasattr(dev, '_main_prefix'): + print 'Main memory:', repr(dev._main_prefix) print 'Total space:', dev.total_space() break if not success and errors: diff --git a/src/calibre/gui2/convert/pdb_input.py b/src/calibre/gui2/convert/pdb_input.py new file mode 100644 index 0000000000..cc7582c7f6 --- /dev/null +++ b/src/calibre/gui2/convert/pdb_input.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +__license__ = 'GPL 3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +from calibre.gui2.convert.pdb_input_ui import Ui_Form +from calibre.gui2.convert import Widget + +class PluginWidget(Widget, Ui_Form): + + TITLE = _('PDB Input') + HELP = _('Options specific to')+' PDB '+_('input') + + def __init__(self, parent, get_option, get_help, db=None, book_id=None): + Widget.__init__(self, parent, 'txt_input', + ['single_line_paras']) + self.db, self.book_id = db, book_id + self.initialize_options(get_option, get_help, db, book_id) diff --git a/src/calibre/gui2/convert/pdb_input.ui b/src/calibre/gui2/convert/pdb_input.ui new file mode 100644 index 0000000000..191e749833 --- /dev/null +++ b/src/calibre/gui2/convert/pdb_input.ui @@ -0,0 +1,41 @@ + + + Form + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Qt::Vertical + + + + 20 + 213 + + + + + + + + Treat each &line as a paragraph + + + + + + + + diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 1f035d4bae..0a1f8a2ae4 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -14,8 +14,9 @@ from PyQt4.Qt import Qt, SIGNAL, QObject, QCoreApplication, QUrl, QTimer, \ QMessageBox, QStackedLayout from PyQt4.QtSvg import QSvgRenderer -from calibre import __version__, __appname__, \ - iswindows, isosx, prints, patheq +from calibre import prints, patheq +from calibre.constants import __version__, __appname__, \ + iswindows, isosx, filesystem_encoding from calibre.utils.filenames import ascii_filename from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.config import prefs, dynamic @@ -424,7 +425,13 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): error_dialog(self, _('Bad database location'), _('Bad database location')+':'+self.library_path, det_msg=traceback.format_exc()).exec_() - x = os.path.expanduser('~'+os.sep+'library') + fname = _('Calibre Library') + if isinstance(fname, unicode): + try: + fname = fname.encode(filesystem_encoding) + except: + fname = 'Calibre Library' + x = os.path.expanduser('~'+os.sep+fname) if not os.path.exists(x): os.makedirs(x) dir = unicode(QFileDialog.getExistingDirectory(self, diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index 68e866e7e1..df5d38a927 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -17,6 +17,7 @@ from calibre import __appname__, patheq from calibre.library.database2 import LibraryDatabase2 from calibre.library.move import MoveLibrary from calibre.resources import server_resources +from calibre.constants import filesystem_encoding from calibre.gui2.wizard.send_email import smtp_prefs from calibre.gui2.wizard.device_ui import Ui_WizardPage as DeviceUI from calibre.gui2.wizard.library_ui import Ui_WizardPage as LibraryUI @@ -473,7 +474,18 @@ class LibraryPage(QWizardPage, LibraryUI): def initializePage(self): lp = prefs['library_path'] if not lp: - lp = os.path.expanduser('~') + fname = _('Calibre Library') + if isinstance(fname, unicode): + try: + fname = fname.encode(filesystem_encoding) + except: + fname = 'Calibre Library' + lp = os.path.expanduser('~'+os.sep+fname) + if not os.path.exists(lp): + try: + os.makedirs(lp) + except: + lp = os.path.expanduser('~') self.location.setText(lp) def isComplete(self): diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index 500eda5e2f..458247896e 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -140,6 +140,12 @@ Why doesn't |app| have a column for foo? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |app| is designed to have columns for the most frequently and widely used fields. If it does not have a coulmn for your favorite field, you can always add a tag to the book for that piece of information. |app| also supports a general purpose "comments" fields for longer items. +How do I move my |app| library from one computer to another? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Simply copy the |app| library folder from the old to the new computer. You can find out what the library folder is by clicking Preferences. The very first item is the path tot he library folder. Now on the new computer, start |app| for the first time. It will run the Welcome Wizard asking you for the location of the |app| library. Point it to the previously copied folder. + +Note that if you are transferring between different types of computers (for example Windows to OS X) then after doing the above you should also go to Preferences->Advanced and click the Check database integrity button. It will warn you about missing files, if any, which you should then transfer by hand. + Content From The Web --------------------- diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 082d179847..27084860a1 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.8\n" -"POT-Creation-Date: 2009-08-24 08:57+MDT\n" -"PO-Revision-Date: 2009-08-24 08:57+MDT\n" +"POT-Creation-Date: 2009-08-25 14:07+MDT\n" +"PO-Revision-Date: 2009-08-25 14:07+MDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -72,7 +72,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/jacket.py:86 #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:105 #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:106 -#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:26 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:33 #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/palmdoc/writer.py:29 #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ztxt/writer.py:27 #: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/crop.py:81 @@ -126,7 +126,7 @@ msgstr "" #: /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:1514 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1525 #: /home/kovid/work/calibre/src/calibre/library/server.py:373 #: /home/kovid/work/calibre/src/calibre/library/server.py:446 #: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45 @@ -1590,6 +1590,11 @@ msgstr "" msgid "Sidebar" msgstr "" +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:22 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:21 +msgid "Normally calibre treats blank lines as paragraph markers. With this option it will assume that every line represents a paragraph instead." +msgstr "" + #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/output.py:23 msgid "Format to use inside the pdb container. Choices are:" msgstr "" @@ -1804,10 +1809,6 @@ msgstr "" msgid "This RTF file has a feature calibre does not support. Convert it to HTML first and then try it." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/txt/input.py:21 -msgid "Normally calibre treats blank lines as paragraph markers. With this option it will assume that every line represents a paragraph instead." -msgstr "" - #: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:24 msgid "Type of newline to use. Options are %s. Default is 'system'. Use 'old_mac' for compatibility with Mac OS 9 and earlier. For Mac OS X use 'unix'. 'system' will default to the newline type used by this OS." msgstr "" @@ -1906,7 +1907,7 @@ msgid "Default action to perform when send to device button is clicked" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:124 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:397 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:398 msgid "Copied" msgstr "" @@ -1977,6 +1978,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15 #: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20 #: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:13 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:17 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:13 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:18 @@ -1988,6 +1990,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16 #: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:13 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:13 #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input.py:13 msgid "input" @@ -2002,6 +2005,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:165 #: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:44 #: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:110 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:28 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:35 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:38 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:39 @@ -2453,6 +2457,15 @@ msgstr "" msgid "&Bottom:" msgstr "" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input.py:12 +msgid "PDB Input" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_input_ui.py:29 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:29 +msgid "Treat each &line as a paragraph" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:16 msgid "PDB Output" msgstr "" @@ -2637,10 +2650,6 @@ msgstr "" msgid "TXT Input" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:29 -msgid "Treat each &line as a paragraph" -msgstr "" - #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:16 msgid "TXT Output" msgstr "" @@ -3103,12 +3112,12 @@ msgid "Access log:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:635 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:564 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:574 msgid "Failed to start content server" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:659 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:469 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:470 msgid "Select location for books" msgstr "" @@ -3142,8 +3151,8 @@ msgid "Checking database integrity" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:783 -#: /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/gui2/main.py:142 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1005 #: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:52 msgid "Error" msgstr "" @@ -4440,144 +4449,149 @@ msgstr "" msgid "Configure" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:58 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:59 msgid "Save single format to disk..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:125 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:126 msgid "Search (For Advanced Search click the button to the left)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:142 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:143 msgid "Error communicating with device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:156 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:157 msgid "&Restore" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:158 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:159 msgid "&Donate to support calibre" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:163 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:164 msgid "&Restart" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:202 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:203 msgid "

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

" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:225 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:226 msgid "Edit metadata individually" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:227 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:228 msgid "Edit metadata in bulk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:229 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:230 msgid "Download metadata and covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:230 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:231 msgid "Download only metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:231 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:232 msgid "Download only covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:234 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:235 msgid "Add books from a single directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:235 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:236 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:238 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:239 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:241 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:242 msgid "Add Empty book. (Book entry with no formats)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:278 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:279 #: /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:279 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:280 msgid "Save to disk in a single directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:280 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1474 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:281 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1484 msgid "Save only %s format to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:288 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:289 #: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:359 msgid "View" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:289 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:290 msgid "View specific format" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:315 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:316 msgid "Convert individually" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:316 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:317 msgid "Bulk convert" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:331 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:332 msgid "Run welcome wizard" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:365 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:366 msgid "Similar books..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:424 #: /home/kovid/work/calibre/src/calibre/gui2/main.py:425 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:426 msgid "Bad database location" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/main.py:428 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1602 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:477 +msgid "Calibre Library" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:438 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1612 msgid "Choose a location for your ebook library." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:607 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:617 msgid "Browse by covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:714 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:724 msgid "Device: " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:716 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:726 msgid " detected." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:738 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:748 msgid "Connected " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:750 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:760 msgid "Device database corrupted" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:751 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:761 msgid "" "\n" "

The database of books on the reader is corrupted. Try the following:\n" @@ -4588,297 +4602,297 @@ msgid "" " " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:827 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:870 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:837 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:880 msgid "Uploading books to device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:835 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:845 msgid "Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:836 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:846 msgid "EPUB Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:837 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:847 msgid "LRF Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:838 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:848 msgid "HTML Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:839 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:849 msgid "LIT Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:840 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:850 msgid "MOBI Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:841 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:851 msgid "Text books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:842 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:852 msgid "PDF Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:843 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:853 msgid "Comics" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:844 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:854 msgid "Archives" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:879 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:889 msgid "Failed to read metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:880 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:890 msgid "Failed to read metadata from the following" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:899 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:909 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:926 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:936 msgid "Deleting books from device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:957 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967 msgid "Cannot download metadata" msgstr "" -#: /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:1198 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:968 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1016 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1046 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1071 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1208 msgid "No books selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:977 msgid "covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:967 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:977 msgid "metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:969 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:979 msgid "Downloading %s for %d book(s)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:990 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1000 msgid "Failed to download some metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:991 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1001 msgid "Failed to download metadata for the following:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:994 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1004 msgid "Failed to download metadata:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1005 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1035 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1015 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1045 msgid "Cannot edit metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1060 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1070 msgid "Cannot save to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1063 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1073 msgid "Choose destination directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1090 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1100 msgid "Error while saving" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1091 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1101 msgid "There was an error while saving." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1098 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1099 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1108 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1109 msgid "Could not save some books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1100 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1110 msgid "Click the show details button to see which ones." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1119 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1129 msgid "Fetching news from " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1132 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1142 msgid " fetched." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1197 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1207 msgid "Cannot convert" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1367 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1386 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1377 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1396 msgid "No book selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1367 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1419 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1377 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1429 msgid "Cannot view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1373 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1383 msgid "Choose the format to view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1385 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1395 msgid "Cannot open folder" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1402 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1412 msgid "Multiple Books Selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1403 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1413 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:1420 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1430 msgid "%s has no available formats." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1458 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1468 msgid "Cannot configure" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1459 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1469 msgid "Cannot configure while there are running jobs." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1503 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1513 msgid "No detailed info available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1504 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1514 msgid "No detailed information is available for books on the device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1552 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1562 msgid "Error talking to device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1553 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1563 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:1570 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1585 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1580 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1595 msgid "Conversion Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1571 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1581 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:1586 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1596 msgid "Failed" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1611 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1621 msgid "Invalid library location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1612 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1622 msgid "Could not access %s. Using %s as the library." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1660 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1670 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:1684 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1694 msgid "There are active jobs. 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:1697 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:1691 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1701 msgid "WARNING: Active jobs" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1742 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1752 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:1761 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1771 msgid "Latest version: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1769 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1779 msgid "Update available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1770 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1780 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:1788 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1798 msgid "Use the library located at the specified path." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1790 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1800 msgid "Start minimized to system tray." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1792 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1802 msgid "Log debugging information to console" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1840 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1850 msgid "If you are sure it is not running" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1842 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1852 msgid "Cannot Start " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1843 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1853 msgid "%s is already running." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1846 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1856 msgid "may be running in the system tray, in the" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1848 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1858 msgid "upper right region of the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1850 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1860 msgid "lower right region of the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1853 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1863 msgid "try rebooting your computer." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1855 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1875 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1865 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1885 msgid "try deleting the file" msgstr "" @@ -5487,47 +5501,47 @@ msgstr "" msgid "Title Case" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:36 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:37 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:149 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:38 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:150 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:151 msgid "Default" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:288 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:289 msgid "If you use the WordPlayer e-book app on your Android phone, you can access your calibre book collection directly on the device. To do this you have to turn on the content server." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:292 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:293 msgid "Remember to leave calibre running as the server only runs as long as calibre is running." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:294 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:295 msgid "You have to add the URL http://myhostname:8080 as your calibre library in WordPlayer. Here myhostname should be the fully qualified hostname or the IP address of the computer calibre is running on." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:371 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:372 msgid "Moving library..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:387 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:388 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:389 msgid "Failed to move library" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:441 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:442 msgid "Invalid database" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:442 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:443 msgid "

An invalid library already exists at %s, delete it before trying to move the existing library.
Error: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:453 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:454 msgid "Could not move library" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:515 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:527 msgid "welcome wizard" msgstr "" @@ -5940,27 +5954,27 @@ msgid "" "For help on an individual command: %%prog command --help\n" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1540 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1551 msgid "

Migrating old database to ebook library in %s

" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1569 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1580 msgid "Copying %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1586 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1597 msgid "Compacting database" msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1674 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1685 msgid "Checking SQL integrity..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1702 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1713 msgid "Checking for missing files." msgstr "" -#: /home/kovid/work/calibre/src/calibre/library/database2.py:1726 +#: /home/kovid/work/calibre/src/calibre/library/database2.py:1737 msgid "Checked id" msgstr "" diff --git a/upload.py b/upload.py index 95d8013985..ffd702ca5d 100644 --- a/upload.py +++ b/upload.py @@ -614,9 +614,9 @@ class build_windows(KVMInstaller): 'build')) if not os.path.exists('build/py2exe'): raise Exception('Failed to run py2exe') + self.run_windows_install_jammer(installer) if not self.dont_shutdown: Popen(('ssh', 'win_build', 'shutdown', '-s', '-t', '0')) - self.run_windows_install_jammer(installer) return os.path.basename(installer) @classmethod From 3e2ca84f09f28b8059b7b4117f51daad8499e2ae Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 14:22:34 -0600 Subject: [PATCH 19/34] Fix #3276 (Tag search GUI broken) --- src/calibre/gui2/main.py | 1 + src/calibre/gui2/tag_view.py | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 0a1f8a2ae4..19e77d211c 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -1503,6 +1503,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.search.clear_to_help() self.status_bar.reset_info() self.library_view.sortByColumn(3, Qt.DescendingOrder) + self.library_view.model().count_changed() ############################################################################ diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py index 2e8bf3c910..9adbb5aad6 100644 --- a/src/calibre/gui2/tag_view.py +++ b/src/calibre/gui2/tag_view.py @@ -93,7 +93,7 @@ class TagsModel(QStandardItemModel): QIcon(':/images/minus.svg')] QStandardItemModel.__init__(self) self.db = db - self.ignore_next_search = False + self.ignore_next_search = 0 self._data = {} self.bold_font = QFont() self.bold_font.setBold(True) @@ -129,19 +129,20 @@ class TagsModel(QStandardItemModel): self.refresh() def reinit(self, *args, **kwargs): - if not self.ignore_next_search: + if self.ignore_next_search == 0: for category in self._data.values(): for tag in category: tag.state = 0 self.reset() - self.ignore_next_search = False + else: + self.ignore_next_search -= 1 def toggle(self, index): if index.parent().isValid(): category = self.row_map[index.parent().row()] tag = self._data[category][index.row()] self.invisibleRootItem().child(index.parent().row()).child(index.row()).toggle() - self.ignore_next_search = True + self.ignore_next_search = 2 self.emit(SIGNAL('dataChanged(QModelIndex,QModelIndex)'), index, index) return True return False From 37a8e070153dcfebf5650587fb2bcc0583afc489 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 15:43:19 -0600 Subject: [PATCH 20/34] Make error messages about failed conversion jobs non-modal. Fixes #3273 (Calibre Shuts Down). --- src/calibre/gui2/main.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 19e77d211c..154b6e859a 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -1578,12 +1578,14 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): def job_exception(self, job): try: if 'calibre.ebooks.DRMError' in job.details: - error_dialog(self, _('Conversion Error'), + d = error_dialog(self, _('Conversion Error'), _('

Could not convert: %s

It is a ' 'DRMed book. You must first remove the ' 'DRM using 3rd party tools.')%\ (job.description.split(':')[-1], - 'http://wiki.mobileread.com/wiki/DRM')).exec_() + 'http://wiki.mobileread.com/wiki/DRM')) + d.setModal(False) + d.show() return except: pass @@ -1593,9 +1595,11 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): prints(job.details, file=sys.stderr) except: pass - error_dialog(self, _('Conversion Error'), + d = error_dialog(self, _('Conversion Error'), _('Failed')+': '+unicode(job.description), - det_msg=job.details).exec_() + det_msg=job.details) + d.setModal(False) + d.show() def initialize_database(self): From 56fa91619413d5d222b623a14203c7571f514059 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 16:52:11 -0600 Subject: [PATCH 21/34] Fix Slate recipe --- src/calibre/web/feeds/recipes/recipe_slate.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/calibre/web/feeds/recipes/recipe_slate.py b/src/calibre/web/feeds/recipes/recipe_slate.py index 93c37affd4..09c6c2fa5a 100644 --- a/src/calibre/web/feeds/recipes/recipe_slate.py +++ b/src/calibre/web/feeds/recipes/recipe_slate.py @@ -16,7 +16,7 @@ class PeriodicalNameHere(BasicNewsRecipe): title = 'Slate' description = 'A general-interest publication offering analysis and commentary about politics, news and culture.' __author__ = 'GRiker' - max_articles_per_feed = 40 + max_articles_per_feed = 20 oldest_article = 7.0 recursions = 0 delay = 0 @@ -106,11 +106,15 @@ class PeriodicalNameHere(BasicNewsRecipe): older_section_dates = soup.findAll(True, attrs={'class':'maindateline'}) for older_section in older_section_dates : self.section_dates.append(self.tag_to_string(older_section,use_alt=False)) - - headline_stories = soup_top_stories.find('ul') + + if soup_top_stories: + headline_stories = soup_top_stories.find('ul') + else: + headline_stories = None section_lists = soup.findAll('ul') # Prepend the headlines to the first section - section_lists[0].insert(0,headline_stories) + if headline_stories: + section_lists[0].insert(0,headline_stories) sections = [] for section in section_lists : @@ -290,7 +294,8 @@ class PeriodicalNameHere(BasicNewsRecipe): excluded = re.compile('|'.join(self.excludedContentKeywords)) found_excluded = excluded.search(str(soup)) if found_excluded : - return None + print "no allowed content found, removing article" + raise StringError # Articles from www.thebigmoney.com use different tagging for byline, dateline and body head = soup.find('head') @@ -423,4 +428,3 @@ class PeriodicalNameHere(BasicNewsRecipe): if article.description is None : article.description = extract_description(article.href) - \ No newline at end of file From aeb5cb189ef2a9a7c044e70db202c7d3b3e5e58e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 17:04:33 -0600 Subject: [PATCH 22/34] Fix #3280 (Frequent crashes) --- src/calibre/gui2/add.py | 58 ++++++++++++++++++++++++++++++-------- src/calibre/gui2/main.py | 8 ++++++ src/calibre/manual/faq.rst | 6 ++-- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py index 56ed9b661a..93bebf593f 100644 --- a/src/calibre/gui2/add.py +++ b/src/calibre/gui2/add.py @@ -5,7 +5,8 @@ import os, shutil, time from Queue import Queue, Empty from threading import Thread -from PyQt4.Qt import QThread, SIGNAL, QObject, QTimer, Qt +from PyQt4.Qt import QThread, SIGNAL, QObject, QTimer, Qt, \ + QProgressDialog from calibre.gui2.dialogs.progress import ProgressDialog from calibre.gui2 import question_dialog, error_dialog @@ -13,6 +14,25 @@ from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata import MetaInformation from calibre.constants import preferred_encoding +class DuplicatesAdder(QThread): + + def __init__(self, parent, db, duplicates, db_adder): + QThread.__init__(self, parent) + self.db, self.db_adder = db, db_adder + self.duplicates = duplicates + + def run(self): + count = 1 + for mi, cover, formats in self.duplicates: + id = self.db.create_book_entry(mi, cover=cover, + add_duplicates=True) + self.db_adder.add_formats(id, formats) + self.db_adder.number_of_books_added += 1 + self.emit(SIGNAL('added(PyQt_PyObject)'), count) + count += 1 + self.emit(SIGNAL('adding_done()')) + + class RecursiveFind(QThread): def __init__(self, parent, db, root, single): @@ -196,15 +216,19 @@ class Adder(QObject): self.callback(self.paths, self.names, self.infos) self.callback_called = True + def duplicates_processed(self): + self.db_adder.end = True + if not self.callback_called: + self.callback(self.paths, self.names, self.infos) + self.callback_called = True + if hasattr(self, '__p_d'): + self.__p_d.hide() + def update(self): if self.entry_count <= 0: self.timer.stop() - self.process_duplicates() self.pd.hide() - self.db_adder.end = True - if not self.callback_called: - self.callback(self.paths, self.names, self.infos) - self.callback_called = True + self.process_duplicates() return try: @@ -240,18 +264,28 @@ class Adder(QObject): def process_duplicates(self): duplicates = self.db_adder.duplicates if not duplicates: - return + return self.duplicates_processed() self.pd.hide() files = [x[0].title for x in duplicates] if question_dialog(self._parent, _('Duplicates found!'), _('Books with the same title as the following already ' 'exist in the database. Add them anyway?'), '\n'.join(files)): - for mi, cover, formats in duplicates: - id = self.db.create_book_entry(mi, cover=cover, - add_duplicates=True) - self.db_adder.add_formats(id, formats) - self.db_adder.number_of_books_added += 1 + pd = QProgressDialog(_('Adding duplicates...'), '', 0, len(duplicates), + self._parent) + pd.setCancelButton(None) + pd.setValue(0) + pd.show() + self.__p_d = pd + self.__d_a = DuplicatesAdder(self._parent, self.db, duplicates, + self.db_adder) + self.connect(self.__d_a, SIGNAL('added(PyQt_PyObject)'), + pd.setValue) + self.connect(self.__d_a, SIGNAL('adding_done()'), + self.duplicates_processed) + self.__d_a.start() + else: + return self.duplicates_processed() def cleanup(self): if hasattr(self, 'pd'): diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 154b6e859a..8d2abd77d7 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -1576,6 +1576,12 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.device_error_dialog.show() def job_exception(self, job): + if not hasattr(self, '_modeless_dialogs'): + self._modeless_dialogs = [] + if self.isVisible(): + for x in list(self._modeless_dialogs): + if not x.isVisible(): + self._modeless_dialogs.remove(x) try: if 'calibre.ebooks.DRMError' in job.details: d = error_dialog(self, _('Conversion Error'), @@ -1586,6 +1592,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): 'http://wiki.mobileread.com/wiki/DRM')) d.setModal(False) d.show() + self._modeless_dialogs.append(d) return except: pass @@ -1600,6 +1607,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): det_msg=job.details) d.setModal(False) d.show() + self._modeless_dialogs.append(d) def initialize_database(self): diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index 458247896e..36a262ab5c 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -54,11 +54,11 @@ In order to convert a collection of HTML files in a specific oder, you have to c Then just add this HTML file to the GUI and use the convert button to create your ebook. -How do I convert my file containing non-English characters? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +How do I convert my file containing non-English characters, or smart quotes? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are two aspects to this problem: 1. Knowing the encoding of the source file: |app| tries to guess what character encoding your source files use, but often, this is impossible, so you need to tell it what encoding to use. This can be done in the GUI via the :guilabel:`Input character encoding` field in the :guilabel:`Look & Feel` section. The command-line tools all have an :option:`--input-encoding` option. - 2. When adding HTML files to |app|, you may need to tell |app| what encoding the files are in. To do this go to Preferences->Plugins->File Type plugins and customize the HTML2Zip plugin, telling it what encoding your HTML files are in. |app| will then automatically convert the HTML files into the UTF-8 encoding when adding them. + 2. When adding HTML files to |app|, you may need to tell |app| what encoding the files are in. To do this go to Preferences->Plugins->File Type plugins and customize the HTML2Zip plugin, telling it what encoding your HTML files are in. Now when you add HTML files to |app| they will be correctly processed. HTML files from different sources often have different encodings, so you may have to change this setting repeatedly. A common encoding for many files from the web is ``cp1252`` and I would suggest you try that first. 3. Embedding fonts: If you are generating an LRF file to read on your SONY Reader, you are limited by the fact that the Reader only supports a few non-English characters in the fonts it comes pre-loaded with. You can work around this problem by embedding a unicode-aware font that supports the character set your file uses into the LRF file. You should embed atleast a serif and a sans-serif font. Be aware that embedding fonts significantly slows down page-turn speed on the reader. From 5396c109050cf6a135c81e5d723eb12bd96b2c79 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 17:53:59 -0600 Subject: [PATCH 23/34] Use default day of 1 when no day is available in the downloaded publish date from Google Books --- src/calibre/ebooks/metadata/google_books.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/google_books.py b/src/calibre/ebooks/metadata/google_books.py index 82f11c2010..374c4a8a5f 100644 --- a/src/calibre/ebooks/metadata/google_books.py +++ b/src/calibre/ebooks/metadata/google_books.py @@ -6,6 +6,7 @@ __docformat__ = 'restructuredtext en' import sys, textwrap from urllib import urlencode from functools import partial +from datetime import datetime from lxml import etree from dateutil import parser @@ -151,7 +152,9 @@ class ResultList(list): try: d = date(entry) if d: - d = parser.parse(d[0].text) + default = datetime.utcnow() + default = datetime(default.year, default.month, 1) + d = parser.parse(d[0].text, default=default) else: d = None except: From b1ee1b622f21f79442430c3282e6767a2e41a5dc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 17:54:21 -0600 Subject: [PATCH 24/34] Fix #3267 (Can not convert ebook format from ODT to LRF format.) --- src/calibre/ebooks/oeb/stylizer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index 0c387e3e84..b5d351f886 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -92,7 +92,10 @@ class CSSSelector(etree.XPath): def __init__(self, css, namespaces=XPNSMAP): css = self.MIN_SPACE_RE.sub(r'\1', css) - path = css_to_xpath(css) + try: + path = css_to_xpath(css) + except UnicodeEncodeError: # Bug in css_to_xpath + path = '/' path = self.LOCAL_NAME_RE.sub(r"local-name() = '", path) etree.XPath.__init__(self, path, namespaces=namespaces) self.css = css From 5f87805c63b3ca365656af596ffaed60d65a54e1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 17:56:31 -0600 Subject: [PATCH 25/34] IGN:Fix #3290 (Fetching pagina/12 recipe does not work) --- .../web/feeds/recipes/recipe_pagina12.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/calibre/web/feeds/recipes/recipe_pagina12.py b/src/calibre/web/feeds/recipes/recipe_pagina12.py index 039e8a8e15..e0836a14c6 100644 --- a/src/calibre/web/feeds/recipes/recipe_pagina12.py +++ b/src/calibre/web/feeds/recipes/recipe_pagina12.py @@ -10,11 +10,11 @@ from calibre import strftime from calibre.web.feeds.news import BasicNewsRecipe class Pagina12(BasicNewsRecipe): - title = 'Pagina/12' + title = 'Pagina - 12' __author__ = 'Darko Miletic' description = 'Noticias de Argentina y el resto del mundo' publisher = 'La Pagina S.A.' - category = 'news, politics, Argentina' + category = 'news, politics, Argentina' oldest_article = 2 max_articles_per_feed = 100 no_stylesheets = True @@ -22,16 +22,16 @@ class Pagina12(BasicNewsRecipe): cover_url = strftime('http://www.pagina12.com.ar/fotos/%Y%m%d/diario/tapagn.jpg') remove_javascript = True use_embedded_content = False - language = _('Spanish') - - + language = _('Spanish') + + html2lrf_options = [ '--comment', description , '--category', category , '--publisher', publisher ] - - html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"' + + html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"' remove_tags = [ @@ -39,7 +39,7 @@ class Pagina12(BasicNewsRecipe): ,dict(name='div', attrs={'id':'logo' }) ] - + feeds = [(u'Pagina/12', u'http://www.pagina12.com.ar/diario/rss/principal.xml')] def print_version(self, url): @@ -47,7 +47,7 @@ class Pagina12(BasicNewsRecipe): def preprocess_html(self, soup): mtag = '' - soup.head.insert(0,mtag) + soup.head.insert(0,mtag) for item in soup.findAll(style=True): del item['style'] return soup From 3e5a21ef421b4d9e13ae5b571454e874ff3df988 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 18:07:27 -0600 Subject: [PATCH 26/34] New recipe for Livemint by Darko Miletic --- src/calibre/gui2/images/news/livemint.png | Bin 0 -> 853 bytes src/calibre/web/feeds/recipes/__init__.py | 2 +- .../web/feeds/recipes/recipe_livemint.py | 43 ++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/calibre/gui2/images/news/livemint.png create mode 100644 src/calibre/web/feeds/recipes/recipe_livemint.py diff --git a/src/calibre/gui2/images/news/livemint.png b/src/calibre/gui2/images/news/livemint.png new file mode 100644 index 0000000000000000000000000000000000000000..5fb3cf7e89cf05bf079351c69c7fe0a9a5e22acf GIT binary patch literal 853 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87?|ojT^vI!PUlWOpB)k|bJYI(@#@O=GiQ1p zQ}H$M;{15s?d_qZCRdhf=*8^T2@zk%Dy}=DcSrb zIw9t4g7=Tz%n8~>729Rf@2e;T$RJN1UXMSxKHx1)9K4`f0~-L@4rj9v%6%H z^7Fa{@f@X+1&k#eXH*&we{N)MZ#kOkyE#@UDe>nUUbW}b%9$AY=I%cgE*{2d#r8h) z$h?&&yQ~5`N_VVyz{|U7s`Z(9JAV8W+xGSTX7xQ4CEPFnoGIDkc_+ZYw0mxJ;;#?o zCeQlb*)8*b+SQcxCC_HY8ebd1_g2rpi{+^93b|yp7nm$nOI#yLQW8s2t&)pUffR$0 zfq|v2frYM-X^5e@m8rRviHWX(nU#ToL~7zD6b-rgDVb@N2n{A+4aQccMi32&2k$xp PH86O(`njxgN@xNAauRZD literal 0 HcmV?d00001 diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index a214ca7fa6..7f9723063c 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -55,7 +55,7 @@ recipe_modules = ['recipe_' + r for r in ( 'eltiempo_hn', 'slate', 'tnxm', 'bbcvietnamese', 'vnexpress', 'volksrant', 'theeconomictimes_india', 'ourdailybread', 'monitor', 'republika', 'beta', 'beta_en', 'glasjavnosti', - 'esquire', + 'esquire', 'livemint', )] diff --git a/src/calibre/web/feeds/recipes/recipe_livemint.py b/src/calibre/web/feeds/recipes/recipe_livemint.py new file mode 100644 index 0000000000..5813233b86 --- /dev/null +++ b/src/calibre/web/feeds/recipes/recipe_livemint.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +__license__ = 'GPL v3' +__copyright__ = '2009, Darko Miletic ' +''' +www.livemint.com +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class LiveMint(BasicNewsRecipe): + title = u'Livemint' + __author__ = 'Darko Miletic' + description = 'The Wall Street Journal' + publisher = 'The Wall Street Journal' + category = 'news, games, adventure, technology' + language = _('English') + oldest_article = 15 + max_articles_per_feed = 100 + no_stylesheets = True + encoding = 'utf-8' + use_embedded_content = False + extra_css = ' #dvArtheadline{font-size: x-large} #dvArtAbstract{font-size: large} ' + + keep_only_tags = [dict(name='div', attrs={'class':'innercontent'})] + + remove_tags = [dict(name=['object','link','embed','form','iframe'])] + + feeds = [(u'Articles', u'http://www.livemint.com/SectionRssfeed.aspx?Mid=1')] + + def print_version(self, url): + link = url + try: + msoup = self.index_to_soup(link) + except: + return 'http://invalid_url_generated_by_calibre.com' + mlink = msoup.find(attrs={'id':'ctl00_bodyplaceholdercontent_cntlArtTool_printUrl'}) + if mlink: + link = 'http://www.livemint.com/Articles/' + mlink['href'].rpartition('/Articles/')[2] + return link + + def preprocess_html(self, soup): + return self.adeify_images(soup) From 4dde757294e290c5a2ddb4afdf97fa583866c4e4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 18:23:25 -0600 Subject: [PATCH 27/34] IGN:Handle failure to find print version of articles more gracefully --- src/calibre/web/feeds/news.py | 3 +++ src/calibre/web/feeds/recipes/recipe_livemint.py | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/calibre/web/feeds/news.py b/src/calibre/web/feeds/news.py index 91e00cc213..849a5be1ab 100644 --- a/src/calibre/web/feeds/news.py +++ b/src/calibre/web/feeds/news.py @@ -741,6 +741,9 @@ class BasicNewsRecipe(Recipe): url = self.print_version(article.url) except NotImplementedError: url = article.url + except: + self.log.exception('Failed to find print version for: '+article.url) + url = None if not url: continue func, arg = (self.fetch_embedded_article, article) if self.use_embedded_content else \ diff --git a/src/calibre/web/feeds/recipes/recipe_livemint.py b/src/calibre/web/feeds/recipes/recipe_livemint.py index 5813233b86..2461dde404 100644 --- a/src/calibre/web/feeds/recipes/recipe_livemint.py +++ b/src/calibre/web/feeds/recipes/recipe_livemint.py @@ -30,10 +30,7 @@ class LiveMint(BasicNewsRecipe): def print_version(self, url): link = url - try: - msoup = self.index_to_soup(link) - except: - return 'http://invalid_url_generated_by_calibre.com' + msoup = self.index_to_soup(link) mlink = msoup.find(attrs={'id':'ctl00_bodyplaceholdercontent_cntlArtTool_printUrl'}) if mlink: link = 'http://www.livemint.com/Articles/' + mlink['href'].rpartition('/Articles/')[2] From 4bcede833d3eb288d5ae2118f34105b814b5fa04 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Aug 2009 18:26:49 -0600 Subject: [PATCH 28/34] New recipe for The Edge Singapore by Darko Miletic --- src/calibre/web/feeds/recipes/__init__.py | 2 +- .../feeds/recipes/recipe_thedgesingapore.py | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/calibre/web/feeds/recipes/recipe_thedgesingapore.py diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index 7f9723063c..2892e88379 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -55,7 +55,7 @@ recipe_modules = ['recipe_' + r for r in ( 'eltiempo_hn', 'slate', 'tnxm', 'bbcvietnamese', 'vnexpress', 'volksrant', 'theeconomictimes_india', 'ourdailybread', 'monitor', 'republika', 'beta', 'beta_en', 'glasjavnosti', - 'esquire', 'livemint', + 'esquire', 'livemint', 'thedgesingapore', )] diff --git a/src/calibre/web/feeds/recipes/recipe_thedgesingapore.py b/src/calibre/web/feeds/recipes/recipe_thedgesingapore.py new file mode 100644 index 0000000000..248255bee5 --- /dev/null +++ b/src/calibre/web/feeds/recipes/recipe_thedgesingapore.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +__license__ = 'GPL v3' +__copyright__ = '2009, Darko Miletic ' +''' +www.livemint.com +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class Edgesingapore(BasicNewsRecipe): + title = 'The Edge Singapore' + __author__ = 'Darko Miletic' + description = 'Financial news from Singapore' + publisher = 'The Edge Singapore' + category = 'news, finances, singapore' + language = _('English') + lang = 'en' + oldest_article = 15 + max_articles_per_feed = 100 + no_stylesheets = True + encoding = 'utf-8' + use_embedded_content = False + extra_css = ' .contentheading{font-size: x-large} .small{font-size: small} .createdate{font-size: small; font-weight: bold} ' + + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'author' : publisher + , 'language' : lang + , 'pretty_print' : True + , 'linearize_tables' : True + } + + + remove_tags = [ + dict(name=['object','link','embed','form','iframe']) + ,dict(name='div',attrs={'id':'toolbar-article'}) + ,dict(name='div',attrs={'class':'backtotop'}) + ,dict(name='img',attrs={'alt':'Print'}) + ] + + remove_tags_after = dict(name='div',attrs={'class':'backtotop'}) + + feeds = [(u'Articles', u'http://feeds.feedburner.com/edgesg')] + + def print_version(self, url): + return url + '?tmpl=component&print=1' + + def preprocess_html(self, soup): + attribs = [ 'style','font','valign' + ,'colspan','width','height' + ,'rowspan','summary','align' + ,'cellspacing','cellpadding' + ,'frames','rules','border' + ] + for item in soup.body.findAll(name=['table','td','tr','th','caption','thead','tfoot','tbody','colgroup','col']): + item.name = 'div' + for attrib in attribs: + if item.has_key(attrib): + del item[attrib] + return self.adeify_images(soup) From fd2d6bdd3d6f2b904a92237a36532a51c6a2cedc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 26 Aug 2009 08:28:11 -0600 Subject: [PATCH 29/34] New recipe Darknet by Oliver Beusner --- src/calibre/gui2/images/news/darknet.png | Bin 0 -> 1874 bytes src/calibre/web/feeds/recipes/__init__.py | 2 +- .../web/feeds/recipes/recipe_darknet.py | 43 ++++++++++++++++++ .../web/feeds/recipes/recipe_elektrolese.py | 3 +- src/calibre/web/feeds/recipes/recipe_hna.py | 9 ++++ .../web/feeds/recipes/recipe_linuxdevices.py | 37 ++++++--------- 6 files changed, 69 insertions(+), 25 deletions(-) create mode 100644 src/calibre/gui2/images/news/darknet.png create mode 100644 src/calibre/web/feeds/recipes/recipe_darknet.py diff --git a/src/calibre/gui2/images/news/darknet.png b/src/calibre/gui2/images/news/darknet.png new file mode 100644 index 0000000000000000000000000000000000000000..a64867c3e7cba90c695c3bf5d8d010c9f7b46a92 GIT binary patch literal 1874 zcmV-Y2d(&tP)nKgCRn=Yf{(SFyUwsGg+kZZO zbq7*`nm1!W)&HNz0KWYWLqH@!?cd8G?7{jUe*O2yuNn;G42;B6Fo{UQL?88Nyv*y# z4u+ZGX(FENu9UWWCeqWycfbDY<5x5AIZ*S3NJ2Gu{5+m- z-Zih4f~b85IaIX>RJApDus_v+LLwEsj)-Urfa>La`#hdk4FZFH04cCRP)A}YsEU}E zH4%&PH4ueJ;t4flDIR#Yecz6c=OZ;Q>0`bc@j37~;|^u+2PV<1@b)jZ?v+SAI02!6 zxP**)8UJS*mWb3~%$eiIBk$h*%(y>vPzKZa#M^go8Lx~|tVM!Y9Y|CW6iE9vDTulW z`)W7M$R(fsfM#J!i_d`#nd`%dSum#H7YybJn+v7htf{_4K)^h%IcfQU{A?rwB(QJs z`0ZoH_00>)mxAU(eEz_ggnbU;{tivI*p+ZQtlkHZ2#^IH(Og92XCoi}dCT#5WZZS{ zmV+LF(`u}1HW;$zai%a<$W_SCSe;PqVBBD6t%8+IaD|Obp+KG6`Gr*irx;dSnZPQ>Hr#LBvvi?OU$_Lz{OApBqNZ z991#ydSp_DS>(9^JvLEDk%T1?VW>jXyaW_cAWoc1;oVW zrcVdR!pj{wWfY*qGeyAr0tfgo^;eL%hhtvHL;>b8> z?DmX@HN%Gkz8i^ji&C&^27o~=9X$$(8@dIIFQE!caa-V>(o500g4ul*oYJ$MQwdt{jdha+*xiR9D}(vsa$|zV)}BT?40;= zjm-`NoUTSj35GL5Sltu#OyFpSESTh2W!noJOSWQQ>D>VC0RtF;Sq8hIq>(WT3&XC2 zT^ZIHN+z^}^KU1l33J1u@eB@_kc_C?ZV31if$nj+cYgZQ3*P2&w);6VTOf?_{uYMXCcgFj_6adERt1{m9(tsvP8HBGP5q!CZTuMF%!zMqH$+uj=Y*q1XUS*QHQF-;Yx(#e5` zPwgp5j@OA$Py{Vr0ThZEE)fDBM6ouyHSr=fMvZw-xoT{xUhYfpNz~jV*}OSC#d`f( z#b<4Fn*D^;iDt@~oC-lSATQ#vw!Uw}xl4E9K&TKYuWEXg?w8niPlwW)PZ%1Uamd8x@Rf)x1-_YV#oEhjxp303pmfB;2s6gn z0P8Agg9G~Aq6RKQ5v_Gs`zFcZ19h0?@|`i*B(;e)&3W+9flT)JFM6eoh*=A=HmXyXi&)qs_K$!NKmZEjdgJN_@5yBH;g zR(a6?001R)MObuXVRU6WV{&C-bY%cCFfchSFgPtTHdHV;Ix;glF)%GKHaajc7p;Dc z0000bbVXQnWMOn=I&E)cX=Zr Date: Wed, 26 Aug 2009 09:58:48 -0600 Subject: [PATCH 30/34] Implement #3246 (additional file naming options for "Saving books" tab) --- src/calibre/gui2/dialogs/config/__init__.py | 3 ++- src/calibre/gui2/dialogs/config/add_save.py | 6 ++++-- src/calibre/gui2/dialogs/config/add_save.ui | 18 ++++++++++++++++-- src/calibre/library/cli.py | 6 ++++++ src/calibre/library/save_to_disk.py | 19 ++++++++++++++++--- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py index 32013b34fa..6cc77725e8 100644 --- a/src/calibre/gui2/dialogs/config/__init__.py +++ b/src/calibre/gui2/dialogs/config/__init__.py @@ -758,7 +758,8 @@ class CheckIntegrity(QProgressDialog): def __init__(self, db, parent=None): QProgressDialog.__init__(self, parent) - self.setCancelButtonText('') + self.db = db + self.setCancelButton(None) self.setMinimum(0) self.setMaximum(100) self.setWindowTitle(_('Checking database integrity')) diff --git a/src/calibre/gui2/dialogs/config/add_save.py b/src/calibre/gui2/dialogs/config/add_save.py index 6d91745044..71e7c83a62 100644 --- a/src/calibre/gui2/dialogs/config/add_save.py +++ b/src/calibre/gui2/dialogs/config/add_save.py @@ -26,7 +26,8 @@ class AddSave(QTabWidget, Ui_TabWidget): self.removeTab(2) c = config() opts = c.parse() - for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf'): + for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf', + 'replace_whitespace', 'to_lowercase'): g = getattr(self, 'opt_'+x) g.setChecked(getattr(opts, x)) help = '\n'.join(textwrap.wrap(c.get_option(x).help, 75)) @@ -74,7 +75,8 @@ class AddSave(QTabWidget, Ui_TabWidget): if not self.validate(): return False c = config() - for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf'): + for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf', + 'replace_whitespace', 'to_lowercase'): c.set(x, getattr(self, 'opt_'+x).isChecked()) for x in ('formats', 'template', 'timefmt'): c.set(x, unicode(getattr(self, 'opt_'+x).text()).strip()) diff --git a/src/calibre/gui2/dialogs/config/add_save.ui b/src/calibre/gui2/dialogs/config/add_save.ui index 6faec64626..513be73e54 100644 --- a/src/calibre/gui2/dialogs/config/add_save.ui +++ b/src/calibre/gui2/dialogs/config/add_save.ui @@ -77,14 +77,14 @@ - + Save &cover separately - + Update &metadata in saved copies @@ -163,6 +163,20 @@ + + + + Replace space with &underscores + + + + + + + Change paths to &lowercase + + + diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index 81d293a1cb..b5e15b4681 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -530,6 +530,12 @@ an opf file). You can get id numbers from the list command. parser.add_option(switch, default=opt.default, help=opt.help, dest=pref) + for pref in ('replace_whitespace', 'to_lowercase'): + opt = c.get_option(pref) + switch = '--'+pref.replace('_', '-') + parser.add_option(switch, default=False, action='store_true', + help=opt.help) + opts, args = parser.parse_args(sys.argv[1:]+args) if (len(args) < 2 and not opts.all): parser.print_help() diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index adaa9c8689..c404bd9223 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -6,7 +6,7 @@ __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import os, traceback, cStringIO +import os, traceback, cStringIO, re from calibre.utils.config import Config, StringConfig from calibre.utils.filenames import shorten_components_to, supports_long_names, \ @@ -71,6 +71,10 @@ def config(defaults=None): x('timefmt', default='%b, %Y', help=_('The format in which to display dates. %d - day, %b - month, ' '%Y - year. Default is: %b, %Y')) + x('to_lowercase', default=False, + help=_('Convert paths to lowercase.')) + x('replace_whitespace', default=False, + help=_('Replace whitespace with underscores.')) return c def preprocess_template(template): @@ -81,7 +85,9 @@ def preprocess_template(template): template = template.decode(preferred_encoding, 'replace') return template -def get_components(template, mi, id, timefmt='%b %Y', length=250, sanitize_func=ascii_filename): +def get_components(template, mi, id, timefmt='%b %Y', length=250, + sanitize_func=ascii_filename, replace_whitespace=False, + to_lowercase=False): format_args = dict(**FORMAT_ARGS) if mi.title: format_args['title'] = mi.title @@ -113,6 +119,11 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, sanitize_func= components = [str(id)] components = [x.encode(filesystem_encoding, 'replace') if isinstance(x, unicode) else x for x in components] + if to_lowercase: + components = [x.lower() for x in components] + if replace_whitespace: + components = [re.sub(r'\s', '_', x) for x in components] + return shorten_components_to(length, components) @@ -134,7 +145,9 @@ def save_book_to_disk(id, db, root, opts, length): return True, id, mi.title components = get_components(opts.template, mi, id, opts.timefmt, length, - ascii_filename if opts.asciiize else sanitize_file_name) + ascii_filename if opts.asciiize else sanitize_file_name, + to_lowercase=opts.to_lowercase, + replace_whitespace=opts.replace_whitespace) base_path = os.path.join(root, *components) base_name = os.path.basename(base_path) dirpath = os.path.dirname(base_path) From f289c6b44b6a68cb010d3a195be41553db9edc21 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 26 Aug 2009 13:31:39 -0600 Subject: [PATCH 31/34] Fix #3294 (Calibre 0.6.8 E-book library management has stopped working) --- src/calibre/utils/poppler/__init__.py | 2 +- src/calibre/utils/poppler/poppler.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/calibre/utils/poppler/__init__.py b/src/calibre/utils/poppler/__init__.py index 5c44a99d8b..47d357b933 100644 --- a/src/calibre/utils/poppler/__init__.py +++ b/src/calibre/utils/poppler/__init__.py @@ -22,6 +22,7 @@ def get_metadata(stream, cover=True): raw = stream.read() doc = poppler.PDFDoc() doc.load(raw) + del raw title = doc.title if not title or not title.strip(): title = _('Unknown') @@ -55,7 +56,6 @@ def get_metadata(stream, cover=True): if cdata is not None: mi.cover_data = ('jpg', cdata) del doc - del raw return mi diff --git a/src/calibre/utils/poppler/poppler.cpp b/src/calibre/utils/poppler/poppler.cpp index db14bf9a55..b64536c85d 100644 --- a/src/calibre/utils/poppler/poppler.cpp +++ b/src/calibre/utils/poppler/poppler.cpp @@ -176,15 +176,16 @@ poppler_PDFDoc_render_page(poppler_PDFDoc *self, PyObject *args, PyObject *kwarg int num; if (!PyArg_ParseTuple(args, "i|ff", &num, &xdpi, &ydpi)) return ans; - if ( num < 0 || num >= self->doc->numPages()) { - PyErr_SetString(PyExc_ValueError, "Invalid page number"); - return ans; - } if ( self->doc->isLocked()) { PyErr_SetString(PyExc_ValueError, "This document is copyrighted."); return ans; } + if ( num < 0 || num >= self->doc->numPages()) { + PyErr_SetString(PyExc_ValueError, "Invalid page number"); + return ans; + } + page = self->doc->page(num); img = page->renderToImage(xdpi, ydpi); if (img.isNull()) { From 4f2644f3efbad2872df66c609c0f085245e61559 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 26 Aug 2009 15:01:47 -0600 Subject: [PATCH 32/34] Document the calibredb command in the User Manual --- src/calibre/library/cli.py | 77 +++++++++++++++++++++++++----------- src/calibre/manual/custom.py | 49 +++++++++++++++++++++-- 2 files changed, 101 insertions(+), 25 deletions(-) diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index b5e15b4681..0a392c1b8c 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -183,9 +183,7 @@ def do_list(db, fields, sort_by, ascending, search_text, line_width, separator, return template.generate(id="urn:calibre:main", data=data, subtitle=subtitle, sep=os.sep, quote=quote, updated=db.last_modified()).render('xml') - - -def command_list(args, dbpath): +def list_option_parser(): parser = get_parser(_( '''\ %prog list [options] @@ -208,6 +206,11 @@ List the books available in the calibre database. of = ['text', 'xml', 'stanza'] parser.add_option('--output-format', choices=of, default='text', help=_('The format in which to output the data. Available choices: %s. Defaults is text.')%of) + return parser + + +def command_list(args, dbpath): + parser = list_option_parser() opts, args = parser.parse_args(sys.argv[:1] + args) fields = [str(f.strip().lower()) for f in opts.fields.split(',')] if 'all' in fields: @@ -316,9 +319,7 @@ def do_add(db, paths, one_book_per_directory, recurse, add_duplicates): finally: sys.stdout = orig - - -def command_add(args, dbpath): +def add_option_parser(): parser = get_parser(_( '''\ %prog add [options] file1 file2 file3 ... @@ -333,6 +334,11 @@ the directory related options below. help=_('Process directories recursively')) parser.add_option('-d', '--duplicates', action='store_true', default=False, help=_('Add books to database even if they already exist. Comparison is done based on book titles.')) + return parser + + +def command_add(args, dbpath): + parser = add_option_parser() opts, args = parser.parse_args(sys.argv[:1] + args) if len(args) < 2: parser.print_help() @@ -353,9 +359,8 @@ def do_remove(db, ids): if send_message is not None: send_message('refreshdb:', 'calibre GUI') - -def command_remove(args, dbpath): - parser = get_parser(_( +def remove_option_parser(): + return get_parser(_( '''\ %prog remove ids @@ -363,6 +368,9 @@ Remove the books identified by ids from the database. ids should be a comma sepa list of id numbers (you can get id numbers by using the list command). For example, \ 23,34,57-85 ''')) + +def command_remove(args, dbpath): + parser = remove_option_parser() opts, args = parser.parse_args(sys.argv[:1] + args) if len(args) < 2: parser.print_help() @@ -385,15 +393,18 @@ list of id numbers (you can get id numbers by using the list command). For examp def do_add_format(db, id, fmt, path): db.add_format_with_hooks(id, fmt.upper(), path, index_is_id=True) - -def command_add_format(args, dbpath): - parser = get_parser(_( +def add_format_option_parser(): + return get_parser(_( '''\ %prog add_format [options] id ebook_file Add the ebook in ebook_file to the available formats for the logical book identified \ by id. You can get id by using the list command. If the format already exists, it is replaced. ''')) + + +def command_add_format(args, dbpath): + parser = add_format_option_parser() opts, args = parser.parse_args(sys.argv[:1] + args) if len(args) < 3: parser.print_help() @@ -410,8 +421,8 @@ by id. You can get id by using the list command. If the format already exists, i def do_remove_format(db, id, fmt): db.remove_format(id, fmt, index_is_id=True) -def command_remove_format(args, dbpath): - parser = get_parser(_( +def remove_format_option_parser(): + return get_parser(_( ''' %prog remove_format [options] id fmt @@ -420,6 +431,10 @@ You can get id by using the list command. fmt should be a file extension \ like LRF or TXT or EPUB. If the logical book does not have fmt available, \ do nothing. ''')) + + +def command_remove_format(args, dbpath): + parser = remove_format_option_parser() opts, args = parser.parse_args(sys.argv[:1] + args) if len(args) < 3: parser.print_help() @@ -441,7 +456,7 @@ def do_show_metadata(db, id, as_opf): else: print unicode(mi).encode(preferred_encoding) -def command_show_metadata(args, dbpath): +def show_metadata_option_parser(): parser = get_parser(_( ''' %prog show_metadata [options] id @@ -451,6 +466,10 @@ id is an id number from the list command. ''')) parser.add_option('--as-opf', default=False, action='store_true', help=_('Print metadata in OPF form (XML)')) + return parser + +def command_show_metadata(args, dbpath): + parser = show_metadata_option_parser() opts, args = parser.parse_args(sys.argv[1:]+args) if len(args) < 2: parser.print_help() @@ -468,8 +487,8 @@ def do_set_metadata(db, id, stream): if send_message is not None: send_message('refreshdb:', 'calibre GUI') -def command_set_metadata(args, dbpath): - parser = get_parser(_( +def set_metadata_option_parser(): + return get_parser(_( ''' %prog set_metadata [options] id /path/to/metadata.opf @@ -478,6 +497,9 @@ from the OPF file metadata.opf. id is an id number from the list command. You can get a quick feel for the OPF format by using the --as-opf switch to the show_metadata command. ''')) + +def command_set_metadata(args, dbpath): + parser = set_metadata_option_parser() opts, args = parser.parse_args(sys.argv[1:]+args) if len(args) < 3: parser.print_help() @@ -501,7 +523,7 @@ def do_export(db, ids, dir, opts): prints('\t'+'\n\t'.join(tb.splitlines())) prints(' ') -def command_export(args, dbpath): +def export_option_parser(): parser = get_parser(_('''\ %prog export [options] ids @@ -536,6 +558,10 @@ an opf file). You can get id numbers from the list command. parser.add_option(switch, default=False, action='store_true', help=opt.help) + return parser + +def command_export(args, dbpath): + parser = export_option_parser() opts, args = parser.parse_args(sys.argv[1:]+args) if (len(args) < 2 and not opts.all): parser.print_help() @@ -547,9 +573,11 @@ an opf file). You can get id numbers from the list command. do_export(get_db(dbpath, opts), ids, dir, opts) return 0 -def main(args=sys.argv): - commands = ('list', 'add', 'remove', 'add_format', 'remove_format', +COMMANDS = ('list', 'add', 'remove', 'add_format', 'remove_format', 'show_metadata', 'set_metadata', 'export') + + +def option_parser(): parser = OptionParser(_( '''\ %%prog command [options] [arguments] @@ -561,11 +589,16 @@ command is one of: For help on an individual command: %%prog command --help ''' - )%'\n '.join(commands)) + )%'\n '.join(COMMANDS)) + return parser + + +def main(args=sys.argv): + parser = option_parser() if len(args) < 2: parser.print_help() return 1 - if args[1] not in commands: + if args[1] not in COMMANDS: if args[1] == '--version': parser.print_version() return 0 diff --git a/src/calibre/manual/custom.py b/src/calibre/manual/custom.py index d5bb7efcec..958c2ec6a4 100644 --- a/src/calibre/manual/custom.py +++ b/src/calibre/manual/custom.py @@ -69,6 +69,46 @@ CLI_PREAMBLE='''\ {usage} ''' +def generate_calibredb_help(preamble, info): + from calibre.library.cli import COMMANDS, get_parser + import calibre.library.cli as cli + preamble = preamble[:preamble.find('\n\n\n', preamble.find('code-block'))] + preamble += textwrap.dedent(''' + + :command:`calibredb` is the command line interface to the |app| database. It has + several sub-commands, documented below: + + ''') + + global_parser = get_parser('') + groups = [] + for grp in global_parser.option_groups: + groups.append((grp.title.capitalize(), grp.description, grp.option_list)) + + global_options = '\n'.join(render_options('calibredb', groups, False, False)) + + + lines, toc = [], [] + for cmd in COMMANDS: + parser = getattr(cli, cmd+'_option_parser')() + toc.append(' * :ref:`calibredb-%s`'%cmd) + lines += ['.. _calibredb-'+cmd+':', ''] + lines += [cmd, '~'*20, ''] + usage = parser.usage.strip() + usage = [i for i in usage.replace('%prog', 'calibredb').splitlines()] + cmdline = ' '+usage[0] + usage = usage[1:] + usage = [i.replace(cmd, ':command:`%s`'%cmd) for i in usage] + lines += ['.. code-block:: none', '', cmdline, ''] + lines += usage + groups = [(None, None, parser.option_list)] + lines += [''] + lines += render_options('calibredb '+cmd, groups, False) + lines += [''] + + toc = '\n'.join(toc) + raw = preamble + '\n\n'+toc + '\n\n' + global_options+'\n\n'+'\n'.join(lines) + update_cli_doc(os.path.join('cli', 'calibredb.rst'), raw, info) def generate_ebook_convert_help(preamble, info): from calibre.ebooks.conversion.cli import create_option_parser @@ -125,11 +165,12 @@ def update_cli_doc(path, raw, info): info('creating '+os.path.splitext(os.path.basename(path))[0]) open(path, 'wb').write(raw) -def render_options(cmd, groups, options_header=True): - lines = [] +def render_options(cmd, groups, options_header=True, add_program=True): + lines = [''] if options_header: lines = ['[options]', '-'*15, ''] - lines += ['.. program:: '+cmd, ''] + if add_program: + lines += ['.. program:: '+cmd, ''] for title, desc, options in groups: if title: lines.extend([title, '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~']) @@ -180,6 +221,8 @@ def cli_docs(app): preamble = CLI_PREAMBLE.format(cmd=cmd, cmdline=cmdline, usage=usage) if cmd == 'ebook-convert': generate_ebook_convert_help(preamble, info) + elif cmd == 'calibredb': + generate_calibredb_help(preamble, info) else: groups = [(None, None, parser.option_list)] for grp in parser.option_groups: From 96851834cd5c9c596a00f078fdf97a9f26847351 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 26 Aug 2009 15:02:37 -0600 Subject: [PATCH 33/34] IGN:Misc fixes --- installer/linux/freeze.py | 2 +- installer/osx/freeze.py | 2 +- installer/windows/freeze.py | 2 +- src/calibre/gui2/dialogs/add_save.py | 66 ------------------- src/calibre/gui2/wizard/__init__.py | 3 +- src/calibre/library/database2.py | 44 ++++++++----- src/calibre/library/sqlite.py | 6 +- src/calibre/utils/fonts/__init__.py | 8 ++- src/calibre/utils/windows/winutil.c | 1 + .../web/feeds/recipes/recipe_linuxdevices.py | 9 ++- 10 files changed, 51 insertions(+), 92 deletions(-) delete mode 100644 src/calibre/gui2/dialogs/add_save.py diff --git a/installer/linux/freeze.py b/installer/linux/freeze.py index c0f4edfd01..6e5bb0592b 100644 --- a/installer/linux/freeze.py +++ b/installer/linux/freeze.py @@ -93,7 +93,7 @@ def freeze(): includes = [x[0] for x in executables.values()] includes += ['calibre.ebooks.lrf.fonts.prs500.'+x for x in FONT_MAP.values()] - includes += ['email.iterators', 'email.generator'] + includes += ['email.iterators', 'email.generator', 'sqlite3.dump'] excludes = ['matplotlib', "Tkconstants", "Tkinter", "tcl", "_imagingtk", diff --git a/installer/osx/freeze.py b/installer/osx/freeze.py index b9dc2ebe39..7791668a09 100644 --- a/installer/osx/freeze.py +++ b/installer/osx/freeze.py @@ -353,7 +353,7 @@ def main(): 'keyword', 'codeop', 'pydoc', 'readline', 'BeautifulSoup', 'calibre.ebooks.lrf.fonts.prs500.*', 'dateutil', 'email.iterators', - 'email.generator', + 'email.generator', 'sqlite3.dump', 'calibre.ebooks.metadata.amazon', ], 'packages' : ['PIL', 'Authorization', 'lxml', 'dns'], diff --git a/installer/windows/freeze.py b/installer/windows/freeze.py index 8c5feda212..0b4f18ff4a 100644 --- a/installer/windows/freeze.py +++ b/installer/windows/freeze.py @@ -158,7 +158,7 @@ def main(args=sys.argv): 'email.iterators', 'email.generator', 'win32process', 'win32api', 'msvcrt', - 'win32event', + 'win32event', 'sqlite3.dump', 'BeautifulSoup', 'pyreadline', 'pydoc', 'IPython.Extensions.*', 'calibre.web.feeds.recipes.*', diff --git a/src/calibre/gui2/dialogs/add_save.py b/src/calibre/gui2/dialogs/add_save.py deleted file mode 100644 index 7bd6273b4a..0000000000 --- a/src/calibre/gui2/dialogs/add_save.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/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' - -import textwrap - -from PyQt4.Qt import QTabWidget - -from calibre.gui2.dialogs.add_save_ui import Ui_TabWidget -from calibre.library.save_to_disk import config, FORMAT_ARG_DESCS - - -class AddSave(QTabWidget, Ui_TabWidget): - - def __init__(self, parent=None): - QTabWidget.__init__(self, parent) - self.setupUi(self) - c = config() - opts = c.parse() - for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf'): - g = getattr(self, 'opt_'+x) - g.setChecked(getattr(opts, x)) - help = '\n'.join(textwrap.wrap(c.get_option(x).help, 75)) - g.setToolTip(help) - g.setWhatsThis(help) - - for x in ('formats', 'timefmt'): - g = getattr(self, 'opt_'+x) - g.setText(getattr(opts, x)) - help = '\n'.join(textwrap.wrap(c.get_option(x).help, 75)) - g.setToolTip(help) - g.setWhatsThis(help) - - help = '\n'.join(textwrap.wrap(c.get_option('template').help, 75)) - self.opt_template.initialize('save_to_disk_template_history', - opts.template, help=help) - - variables = sorted(FORMAT_ARG_DESCS.keys()) - rows = [] - for var in variables: - rows.append(u'%s%s'% - (var, FORMAT_ARG_DESCS[var])) - table = u'%s
'%(u'\n'.join(rows)) - self.template_variables.setText(table) - - def save_settings(self): - c = config() - for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf'): - c.set(x, getattr(self, 'opt_'+x).isChecked()) - for x in ('formats', 'template', 'timefmt'): - c.set(x, unicode(getattr(self, 'opt_'+x).text()).strip()) - - - -if __name__ == '__main__': - from PyQt4.Qt import QApplication - app=QApplication([]) - a = AddSave() - a.show() - app.exec_() - a.save_settings() - diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index df5d38a927..7045f6334d 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -424,7 +424,8 @@ def move_library(oldloc, newloc, parent, callback_on_complete): callback) else: rq = Queue() - m = MoveLibrary(oldloc, newloc, db.data.count(), rq) + m = MoveLibrary(oldloc, newloc, + len(db.get_top_level_move_items()[0]), rq) global _mm _mm = MoveMonitor(m, rq, callback, parent) return diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index c48b238c8d..54607d1d11 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1444,9 +1444,7 @@ class LibraryDatabase2(LibraryDatabase): if notify: self.notify('add', [id]) - def move_library_to(self, newloc, progress=lambda x: x): - if not os.path.exists(newloc): - os.makedirs(newloc) + def get_top_level_move_items(self): items = set(os.listdir(self.library_path)) paths = set([]) for x in self.data.universal_set(): @@ -1454,15 +1452,25 @@ class LibraryDatabase2(LibraryDatabase): path = path.split(os.sep)[0] paths.add(path) paths.add('metadata.db') + path_map = {} + for x in paths: + path_map[x] = x if not self.is_case_sensitive: - items = set([x.lower() for x in items]) + for x in items: + path_map[x.lower()] = x + items = set(path_map) paths = set([x.lower() for x in paths]) items = items.intersection(paths) + return items, path_map + def move_library_to(self, newloc, progress=lambda x: x): + if not os.path.exists(newloc): + os.makedirs(newloc) old_dirs = set([]) - for i, x in enumerate(items): + items, path_map = self.get_top_level_move_items() + for x in items: src = os.path.join(self.library_path, x) - dest = os.path.join(newloc, x) + dest = os.path.join(newloc, path_map[x]) if os.path.isdir(src): if os.path.exists(dest): shutil.rmtree(dest) @@ -1472,6 +1480,7 @@ class LibraryDatabase2(LibraryDatabase): if os.path.exists(dest): os.remove(dest) shutil.copyfile(src, dest) + x = path_map[x] if not isinstance(x, unicode): x = x.decode(filesystem_encoding, 'replace') progress(x) @@ -1686,13 +1695,12 @@ books_series_link feeds user_version = self.user_version sql = self.conn.dump() self.conn.close() - dest = self.dbpath+'.old' + dest = self.dbpath+'.tmp' if os.path.exists(dest): os.remove(dest) - shutil.copyfile(self.dbpath, dest) + conn = None try: - os.remove(self.dbpath) - ndb = DBThread(self.dbpath, None) + ndb = DBThread(dest, None) ndb.connect() conn = ndb.conn conn.executescript(sql) @@ -1701,15 +1709,21 @@ books_series_link feeds conn.commit() conn.close() except: - if os.path.exists(self.dbpath): - os.remove(self.dbpath) - shutil.copyfile(dest, self.dbpath) - os.remove(dest) + if conn is not None: + try: + conn.close() + except: + pass + if os.path.exists(dest): + os.remove(dest) raise else: - os.remove(dest) + os.remove(self.dbpath) + shutil.copyfile(dest, self.dbpath) self.connect() self.refresh() + if os.path.exists(dest): + os.remove(dest) callback(0.1, _('Checking for missing files.')) bad = {} us = self.data.universal_set() diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py index a1caf506d9..3c23dd67cc 100644 --- a/src/calibre/library/sqlite.py +++ b/src/calibre/library/sqlite.py @@ -157,6 +157,8 @@ class DatabaseException(Exception): def proxy(fn): ''' Decorator to call methods on the database connection in the proxy thread ''' def run(self, *args, **kwargs): + if self.closed: + raise DatabaseException('Connection closed', '') with global_lock: if self.proxy.unhandled_error[0] is not None: raise DatabaseException(*self.proxy.unhandled_error) @@ -174,10 +176,12 @@ class ConnectionProxy(object): def __init__(self, proxy): self.proxy = proxy + self.closed = False def close(self): - if self.proxy.unhandled_error is None: + if self.proxy.unhandled_error[0] is None: self.proxy.requests.put((self.proxy.CLOSE, [], {})) + self.closed = True @proxy def get(self, query, all=True): pass diff --git a/src/calibre/utils/fonts/__init__.py b/src/calibre/utils/fonts/__init__.py index bc6b117147..f4b4e0fc99 100644 --- a/src/calibre/utils/fonts/__init__.py +++ b/src/calibre/utils/fonts/__init__.py @@ -9,7 +9,7 @@ __docformat__ = 'restructuredtext en' import os, sys from threading import Thread -from calibre.constants import plugins +from calibre.constants import plugins, iswindows _fc, _fc_err = plugins['fontconfig'] @@ -31,6 +31,12 @@ class FontConfig(Thread): if isinstance(config_dir, unicode): config_dir = config_dir.encode(sys.getfilesystemencoding()) config = os.path.join(config_dir, 'fonts.conf') + if iswindows and getattr(sys, 'frozen', False): + config_dir = os.path.join(os.path.dirname(sys.executable), + 'etc', 'fonts') + if isinstance(config_dir, unicode): + config_dir = config_dir.encode(sys.getfilesystemencoding()) + config = os.path.join(config_dir, 'fonts.conf') try: _fc.initialize(config) except: diff --git a/src/calibre/utils/windows/winutil.c b/src/calibre/utils/windows/winutil.c index 88091ffc52..be504b7fcf 100644 --- a/src/calibre/utils/windows/winutil.c +++ b/src/calibre/utils/windows/winutil.c @@ -929,6 +929,7 @@ initwinutil(void) { PyModule_AddIntConstant(m, "CSIDL_COOKIES", CSIDL_COOKIES); PyModule_AddIntConstant(m, "CSIDL_FLAG_CREATE", CSIDL_FLAG_CREATE); PyModule_AddIntConstant(m, "CSIDL_FLAG_DONT_VERIFY", CSIDL_FLAG_DONT_VERIFY); + PyModule_AddIntConstant(m, "CSIDL_FONTS", CSIDL_FONTS); PyModule_AddIntConstant(m, "CSIDL_HISTORY", CSIDL_HISTORY); PyModule_AddIntConstant(m, "CSIDL_INTERNET_CACHE", CSIDL_INTERNET_CACHE); PyModule_AddIntConstant(m, "CSIDL_LOCAL_APPDATA", CSIDL_LOCAL_APPDATA); diff --git a/src/calibre/web/feeds/recipes/recipe_linuxdevices.py b/src/calibre/web/feeds/recipes/recipe_linuxdevices.py index ab79b4b911..4c32bad80c 100644 --- a/src/calibre/web/feeds/recipes/recipe_linuxdevices.py +++ b/src/calibre/web/feeds/recipes/recipe_linuxdevices.py @@ -6,10 +6,9 @@ Fetch Linuxdevices. ''' import re from calibre.web.feeds.news import BasicNewsRecipe -from calibre.ebooks.BeautifulSoup import BeautifulSoup -class Sueddeutsche(BasicNewsRecipe): +class LinuxDevices(BasicNewsRecipe): title = u'Linuxdevices' description = 'News about Linux driven Hardware' @@ -20,7 +19,7 @@ class Sueddeutsche(BasicNewsRecipe): no_stylesheets = True language = _('English') remove_javascript = True - conversion_options {' linearize_tables' : True} + conversion_options = { 'linearize_tables' : True} encoding = 'latin1' @@ -83,9 +82,9 @@ class Sueddeutsche(BasicNewsRecipe): for item in soup.findAll('b', text=match): item.extract() for item in soup.findAll(re.compile('^ul')): - item.extract() + item.extract() for item in soup.findAll('br', limit=10): - item.extract() + item.extract() return soup From 4d95f184553a37de6a14a479fbf1e8838f4dd880 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 26 Aug 2009 15:28:41 -0600 Subject: [PATCH 34/34] IGN:... --- src/calibre/debug.py | 4 ++++ src/calibre/manual/custom.py | 1 + 2 files changed, 5 insertions(+) diff --git a/src/calibre/debug.py b/src/calibre/debug.py index 0d38cb4a69..0b17920cd8 100644 --- a/src/calibre/debug.py +++ b/src/calibre/debug.py @@ -145,6 +145,10 @@ def debug_device_driver(): print dev print msg print + if isosx and os.path.exists('/tmp/ioreg.txt'): + print + print + print "Don't forget to send the file /tmp/ioreg.txt as well" def add_simple_plugin(path_to_plugin): diff --git a/src/calibre/manual/custom.py b/src/calibre/manual/custom.py index 958c2ec6a4..6e519c9b2b 100644 --- a/src/calibre/manual/custom.py +++ b/src/calibre/manual/custom.py @@ -194,6 +194,7 @@ def cli_docs(app): for script in entry_points['console_scripts']: module = script[script.index('=')+1:script.index(':')].strip() cmd = script[:script.index('=')].strip() + if cmd in ('calibre-complete', 'calibre-parallel'): continue module = __import__(module, fromlist=[module.split('.')[-1]]) if hasattr(module, 'option_parser'): documented_cmds.append((cmd, getattr(module, 'option_parser')()))