From 0dc8d053ff8f43c23d1b6adc0b6da96a87ca28eb Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 31 May 2009 13:49:07 -0700 Subject: [PATCH 01/20] ... --- installer/windows/calibre/calibre.mpi | 454 +++++++++++++++++++++----- 1 file changed, 366 insertions(+), 88 deletions(-) diff --git a/installer/windows/calibre/calibre.mpi b/installer/windows/calibre/calibre.mpi index a519695367..ad7a8f5ded 100644 --- a/installer/windows/calibre/calibre.mpi +++ b/installer/windows/calibre/calibre.mpi @@ -50,6 +50,12 @@ DefaultDirectoryLocation DefaultLanguage English +DefaultToSystemLanguage +Yes + +EnableResponseFiles +Yes + Ext {} @@ -138,7 +144,7 @@ ProjectID DA98A0C6-9102-73EC-2516-B147E972D3F7 ProjectVersion -1.2.7.0 +1.2.13.1 SaveOnlyToplevelDirs No @@ -206,85 +212,130 @@ test {Testing Switch Yes No {} {run uninstaller without uninstalling any files}} } -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} -name {Program Files} -parent FileGroups +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 +File ::C53E8AB9-30FC-730C-3DA3-851C9B4838A1 -name qmng4.exp -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::36ADF34E-46AD-663F-6C3A-D45E971CB722 -name qmng4.lib -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::A1EEB0BC-ADA2-86C8-631B-E88FE03328EA -name qico4.dll -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::516069B4-FC33-F267-8C4B-95475515A853 -name qico4.exp -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::129AE39B-995D-9BE2-3FB4-69F129C4E86E -name qico4.lib -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::113DBCCE-B6CA-2742-35DB-6FB53EE75919 -name qico4.dll.manifest -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::CC7FFFF8-5DA6-3CCB-540C-A24B528B3DD6 -name qjpeg4.dll -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::9C5B362E-D06B-D92F-6B39-F9F2B5BE9E17 -name qjpeg4.exp -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::0FF52CC9-3920-A82E-0657-5B2A31CD1457 -name qjpeg4.lib -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::9DD8CFAE-2E69-CACA-B451-16683C0F168D -name qjpeg4.dll.manifest -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::5E16CADD-7269-4247-B35C-046D5B67E298 -name qtiff4.dll.manifest -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::633981BF-9A0C-589D-25D3-50866757C3B8 -name qmng4.dll.manifest -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::DB93E311-ECDF-21E0-8C5D-0B2EDAE6C424 -name qgif4.dll.manifest -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::48E4C188-4ABF-4CCD-C410-7936B4898DDF -name qsvg4.dll.manifest -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::BFF82F4E-0F3C-8F6E-381C-CCF91E220226 -name qgif4.dll -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::3FAEE4BA-C005-E833-8BE4-EC8EF7BDAF1B -name qgif4.exp -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::4AB682B9-C811-C68A-0100-5B32E0127093 -name qgif4.lib -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::6EBEF5E4-1FA0-B14A-736F-DD1068874D19 -name qtiff4.dll -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::8B2F7092-5B97-9DA8-90CD-46D191B49C28 -name qtiff4.exp -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::9D014D0C-E6F4-A713-7CE9-CD71AFCEBC61 -name qtiff4.lib -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::5EA8BF5D-76A7-023E-CF87-ED92DBCA527D -name qsvg4.dll -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::A5298D0E-A211-EB2E-6892-7045D04B264E -name qsvg4.exp -parent B95D03D4-EA59-F00E-59E1-BA05758879DA +File ::8A138EC0-728A-A421-A723-DE84F8DDE3EA -name qsvg4.lib -parent B95D03D4-EA59-F00E-59E1-BA05758879DA File ::5EF561A9-E70B-8F01-A852-C36D28D1FA14 -type dir -name codecs -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::D60D391E-2AA1-900B-DB5A-348EFC529375 -name qkrcodecs4.dll -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::4B320138-FB4B-DBD2-81BC-9D1413CF7ED6 -name qkrcodecs4.exp -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::38BE74BB-3CFA-7131-0467-BB1C4AE76512 -name qkrcodecs4.lib -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::49F00491-8056-0B75-7FC5-87761A3C6161 -name qcncodecs4.dll -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::CE567CBA-06A4-6D8E-E389-560CAC84E168 -name qcncodecs4.exp -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::2546B812-DBD7-3EDF-5CB2-B5F6B62639AB -name qcncodecs4.lib -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::12148DF6-6953-C6D3-6CDA-0ACED6F7D7FA -name qjpcodecs4.dll.manifest -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::E4C54E9A-D1E4-DCC9-C43E-FC3A5FD7F8C7 -name qcncodecs4.dll.manifest -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::1A86AC76-87FD-5EA9-0F23-2F21CA22F0CE -name qjpcodecs4.dll -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::FEB0CF93-169B-D996-2363-3AE057322EA6 -name qjpcodecs4.exp -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::0C8E6656-F734-B2B5-F0F7-6F5BDB5C6885 -name qjpcodecs4.lib -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::F95B9748-FC4E-4AF3-C037-8493AD7BE0DA -name qtwcodecs4.dll.manifest -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::2C3B2B03-3911-E7A8-035A-33E25A510F27 -name qtwcodecs4.dll -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::BD1A8C7A-D485-9272-4B9A-05EE511A59CF -name qtwcodecs4.exp -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::7EC5EFFB-7AA7-AEB1-46AD-4234DEE6A377 -name qtwcodecs4.lib -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 +File ::CEE6F2FE-EEBA-8973-AAA5-DCAAAD279B72 -name qkrcodecs4.dll.manifest -parent 5EF561A9-E70B-8F01-A852-C36D28D1FA14 File ::48EA1D8C-F4C8-3D34-229D-B501057802F3 -type dir -name driver -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::596DAFDA-23D2-26B3-1535-3D4BF36C9AD9 -name libusb0.dll -parent 48EA1D8C-F4C8-3D34-229D-B501057802F3 +File ::E6B997AB-A35F-1142-14AB-6B9513D98C40 -name libusb0.sys -parent 48EA1D8C-F4C8-3D34-229D-B501057802F3 +File ::20557983-9D6C-4AB5-D2DF-BE418BEE6BA3 -name libusb0_x64.dll -parent 48EA1D8C-F4C8-3D34-229D-B501057802F3 +File ::CFCED8FB-FE60-07EC-690D-4C47C2C786F6 -name libusb0_x64.sys -parent 48EA1D8C-F4C8-3D34-229D-B501057802F3 +File ::6D2B03D1-8449-045C-298A-9E65C168F64A -name prs500_x64.cat -parent 48EA1D8C-F4C8-3D34-229D-B501057802F3 +File ::8147A9D4-D17C-55EB-CAA5-CC0C04EDC0D2 -name prs500.cat -parent 48EA1D8C-F4C8-3D34-229D-B501057802F3 +File ::1085BEED-C76A-5FF4-209A-E03CFB697462 -name prs500.inf -parent 48EA1D8C-F4C8-3D34-229D-B501057802F3 File ::0AC00D67-8452-CABB-6843-FE6A464E9AE9 -type dir -name plugins -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::540FEFD3-9B1B-00E6-B8A5-EA8EB959428E -name podofo.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::87BCFAF5-FAEB-219C-BA28-1DFD1B2A7743 -name podofo.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::0C77BC18-CE53-35EF-A667-C25B81C43E64 -name pictureflow.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::9F15B633-412B-51ED-2B7D-4EB0A0847740 -name winutil.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::9E3D908E-B119-30AE-391D-D16CA6BEE7AC -name msdes.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::F1D1D581-9194-D12F-6139-F920EEC1B14E -name winutil.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::A94E4D31-5F8C-A363-AE61-A8F2E3A7B756 -name lzx.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::34C430AE-BC1B-8352-1713-50C89C176C77 -name lzx.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::2C88788E-B9FB-729D-442B-600ED97096A0 -name cPalmdoc.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::8A15A76F-105D-3B6C-6E54-A01F8EA16CE3 -name cPalmdoc.pyd.manifest -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 +File ::26503DDE-8C5F-102F-B689-C6A17B2D6C93 -name msdes.pyd -parent 0AC00D67-8452-CABB-6843-FE6A464E9AE9 File ::01034EB7-C79C-42B9-6FF0-E06C72EF2623 -type dir -name iconengines -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::8ADB07A0-6B9E-8F53-34DF-2035C7C343F1 -name qsvgicon4.dll -parent 01034EB7-C79C-42B9-6FF0-E06C72EF2623 +File ::41F512E3-9F39-68C6-BB7F-58F572755D35 -name qsvgicon4.exp -parent 01034EB7-C79C-42B9-6FF0-E06C72EF2623 +File ::7EE2621C-0EAE-B516-505A-6CE11A8F8951 -name qsvgicon4.lib -parent 01034EB7-C79C-42B9-6FF0-E06C72EF2623 +File ::99A56CA8-60A5-CC90-1F6F-0A393722F9D2 -name qsvgicon4.dll.manifest -parent 01034EB7-C79C-42B9-6FF0-E06C72EF2623 File ::7FC7557D-E1AF-082B-7286-24939CD5EE76 -name IM_MOD_RL_sfw_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::EF383C5E-5939-F73E-5F9C-26009B469ADA -name feeds2mobi.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::71A18B69-E38B-AB9F-3B81-BECFD4454D38 -name PyQt4.QtNetwork.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::E1BF1A4F-2942-73DB-1770-1ECB02CA9799 -name comic2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::EEC00227-DED5-B9BF-A36D-24239AEDE932 -name rtf-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::F6C99732-1835-1C2A-02F9-F2BB631BEC81 -name dde.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::3334C5D8-8513-326D-A96C-C86D1C325EBB -name pdf2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::20079501-EBD5-FEFD-8E49-2CF6A63E83E0 -name IM_MOD_RL_rle_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::D98A0557-D988-24A1-9F32-67F3E9A5A123 -name opf-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::470243F6-C8E4-DB45-678F-6A314747097E -name sqlite3.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::4AA221F6-EBE3-997E-AECF-DD8E03265385 -name html2epub.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::0213D597-D9C7-F155-EE44-1BD9E19520E3 -name IM_MOD_RL_tiff_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::F782E3D0-C2CA-481C-70C4-2257FEF52EAF -name CORE_RL_libxml_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::414CB1DC-A13E-CE54-60A9-157381D4DDC4 -name oeb2lit.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::9306B7C1-11DE-7B54-1AFB-67AFF82B8013 -name _sqlite3.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4D6B4FC9-F900-E0AD-5258-8918CBFEB9AD -name lrs2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::05329209-3CCE-90C0-FFEA-BECEBA6A6AB4 -name lit2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A2AF7001-960E-F5EA-AA09-025E35FD09BC -name IM_MOD_RL_sun_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C472ABCF-2160-C218-41CA-0DDE625AAEC6 -name IM_MOD_RL_msl_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::DC7D8C3A-81C2-7FC5-4AC0-8CDC4069FC97 -name IM_MOD_RL_jp2_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::555AF3FA-9A08-CCFF-4028-3F8891A6D212 -name CORE_RL_ttf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::92F06FE6-C2C5-FF23-0A9B-884AB21D8221 -name PIL._imagingft.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::DA2ABF54-3BC2-87E4-BA86-24C8B2915AC0 -name txt2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::C3B86C9F-1A59-9573-DCA2-A2747E7C3B4F -name odt2oeb.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::ED8542BE-DDE4-72B2-B05A-A09D00818994 -name web2disk.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A2154B84-F146-FD50-1DA9-1DB374A5439E -name IM_MOD_RL_exr_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A442B5C3-724F-6542-816D-30C3D3EDD1E3 -name CORE_RL_Magick++_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A18318B3-88EF-11EB-4E14-B02CBD4F0E5E -name calibre-parallel.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::E26C9A86-F12B-7F1E-F2E8-8A42C0436321 -name IM_MOD_RL_dib_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::2E94EBE2-F588-C484-009C-48C0DA7D1932 -name IM_MOD_RL_preview_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::9D75046B-57DC-872C-39F1-4C6E44337227 -name html2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::7294280B-8324-B1A0-A054-92F330874F48 -name numpy.fft.fftpack_lite.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::5322B2EC-82CF-9446-964E-38CB7C688C1B -name oeb2mobi.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::74DC3F8D-5C56-8FB8-F59A-0C4C5ECB70A0 -name CORE_RL_magick_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::1638722F-A861-F762-1514-5649B2AD08FF -name IM_MOD_RL_svg_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D345F98D-EDB4-53D0-95A6-82968E47E080 -name IM_MOD_RL_mpeg_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::91CA5392-5F4E-12F7-C670-939B1500616B -name ebook-viewer.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4706580D-D101-13EA-DED0-2593D7FBADE8 -name LICENSE -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::63F996B0-07D9-EA5B-2176-F02D9851EAE4 -name feeds2disk.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::89CAC9B2-DA65-DBF2-6295-757553882213 -name numpy.core.umath.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::2F90282D-B59F-B6BA-090B-45858AF7F3B2 -name IM_MOD_RL_clipboard_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::B512D139-B295-D7C3-F0B4-43775849CF58 -name numpy.core._sort.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::A999B024-1024-E709-07C1-22BA67A850BB -name feeds2mobi.exe -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 ::ABAEA510-B003-29CB-6ADE-F6E1826DD501 -name web2lrf.exe -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 File ::559057ED-0FEA-62A1-68C2-023116B5636C -name win32ui.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::83F3AC3F-A485-B791-D4F0-6E67135FF19D -name IM_MOD_RL_txt_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::FABA7768-743B-08F7-B871-ED5E9082DF38 -name win32gui.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::A8D10C63-CDFB-0809-CA84-4CB7A0A451FC -name fb2-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C49805D2-C0B8-01C4-DF6F-674D9C0BFD15 -name IM_MOD_RL_viff_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::1B9F2F00-20A5-B207-5A80-8F75470286AD -name txt2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::826F1915-9F97-59DD-6637-3EEC0744A79C -name IM_MOD_RL_ps2_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::519A6618-8A1F-93A5-93B4-6EEF5A4A3DE9 -name comic2pdf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A5F23791-BCDC-A997-4941-5D1F2F227E6D -name type.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::0A1C107A-C0AA-3ED6-4F37-A6894386DCBE -name IM_MOD_RL_ps3_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::EEBA64E7-6509-EBAF-3E23-1A203216F39A -name epub2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::2655F4FC-F682-46D8-B75C-6AF322323EF5 -name IM_MOD_RL_dot_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::176456BB-237C-9EBE-60E1-D8F78AAFFEC8 -name IM_MOD_RL_xwd_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::9AE8498B-C89C-8B12-B8A1-35E1B6650469 -name lxml.objectify.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::EA37C1C2-57BB-4E7A-C004-0010D79142C2 -name IM_MOD_RL_fits_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::05F5C10D-6988-F1F4-A486-86C96DB20302 -name pywintypes26.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::0137A2B1-EB94-EB26-7295-0C7CD941A1DF -name IM_MOD_RL_histogram_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::7F199A1F-4FA4-2ABA-DED3-36ECF3C089CA -name epub2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::CF6398D8-2140-53CF-1DA6-421A82E92621 -name any2epub.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::8DFA6C69-360D-FA63-7FF9-860E3DB00B19 -name any2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::5BB7579D-9183-412C-81F8-B411B07C57B3 -name IM_MOD_RL_pnm_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::97B8BB83-7772-D87B-C8D1-5215E324AF2C -name library.ico -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::DF1361A2-2580-EFBF-65D2-156AD9919DE1 -name library.zip -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -293,7 +344,6 @@ File ::E658FBE0-5860-D041-12D3-76ADD18F804B -name servicemanager.pyd -parent 8E5 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 ::2BCD9281-2CBC-CF0D-0E12-2CE11F6ED758 -name comic2epub.exe.local -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 @@ -302,71 +352,49 @@ File ::69072379-7D16-B9F7-9F39-3E6403C48267 -name IM_MOD_RL_xbm_.dll -parent 8E5 File ::FBD11D98-D1E7-5DD9-BF02-01CE92518859 -name IM_MOD_RL_otb_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::8D0CFD32-2B7F-2BB3-8FA0-760A8DB24B52 -name win32service.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C7F9AB12-AAF7-2954-3DB6-F2C84F41655B -name win32clipboard.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::76676624-68A9-D9D9-6EC7-40CF201520A4 -name pdfreflow.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::62CD997A-A5C7-D71B-A8F7-54567B36A071 -name msvcp90.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::7D76BBE6-FD20-1290-4DBA-93D14FC45B81 -name sip.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::17D27485-128E-E247-14CE-9C3B6988E182 -name pdfreflow.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::BF2007D6-5AFE-6D04-4DB0-36A3644D988D -name pdf-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D4354621-69ED-DFCB-068A-0812DB1C09C3 -name IM_MOD_RL_avi_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::109FBE61-82CD-D5AB-AA9D-F9D52947DD22 -name rtf-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::9BA20E46-014F-DA6A-DEF3-D78E2AEFDD47 -name odt-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::EAFAC6D5-A7E8-1843-6D98-6663D899BB11 -name PyQt4.QtCore.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::155505A4-F0D8-05B2-10AD-149E178976A4 -name calibredb.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::39D5114E-1E70-5402-7E19-D86490678506 -name CORE_RL_lcms_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::75C3F298-B07C-DA98-38B2-40FFD39C32ED -name oeb2lit.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::388E0308-35A8-69B9-6837-383FD72E99E9 -name IM_MOD_RL_xpm_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::3DB88954-1B0D-FDBC-CE29-EFCC01D4121E -name epub-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::43C0DE14-A935-2139-6690-256C49C461C4 -name IM_MOD_RL_xcf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::E185A35A-93DB-61BB-E7EE-2C2222FD4939 -name win32security.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::498CCC26-383A-87CA-30C0-626D52555B37 -name librarything.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::404A98F1-84FD-B6D0-B130-354EECD9253C -name IM_MOD_RL_emf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 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 ::CE737360-1B73-DEC3-E511-3FAEC61F5292 -name epub-meta.exe -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 ::56B7883F-B4FE-BE25-BCBA-4AF17CC84C93 -name fb22lrf.exe.local -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 ::39E11D64-CC0C-E565-B3CC-882A5AA9F4AF -name html2oeb.exe -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 ::A6EF7DB0-FC94-8794-1F15-394432CD283D -name imp-meta.exe -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 ::2B8B1DCD-AA68-7612-80A5-C20CAAF06019 -name any2lit.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 ::2EDE0641-B5DF-220F-9FF3-486E5A081EFC -name rb-meta.exe.local -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 -File ::8F1AF028-E819-4ED6-8B69-704183C3BD1D -name pdf-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D8F566FB-93DA-3128-5DBD-DF1068B3E3ED -name IM_MOD_RL_dpx_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::FFE5F178-A1A4-3691-9C88-E5109D144437 -name IM_MOD_RL_jpeg_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::0C9C97F6-5622-D4B5-E7CD-B4E5E9A8634C -name odt-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::C05AD359-A7A5-9760-A4C8-310074353C89 -name feeds2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::03665A74-B895-EB3D-EBA0-2D2B6D26DDDA -name PIL._imagingmath.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::81AED538-B97F-6272-5C6E-9B27D7285B35 -name IM_MOD_RL_fax_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::BDCCAEC0-4847-B8D8-50B1-1B434B73A01F -name IM_MOD_RL_avs_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::727B9BD6-B55E-386E-D3B9-D99D0D9ADBB1 -name QtGui4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::1C7421A2-1BA7-7807-EB41-67578E0302E8 -name IM_MOD_RL_mvg_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C3466B70-23C3-31C9-3B4F-1B3B56E4D013 -name markdown-calibre.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::A190F216-F7F7-A425-5F9D-F6B5C35D3A8F -name lrf-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::6ED1C675-C4D5-6BFF-7C8A-9AB4BF39D00C -name _hashlib.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::21F7F333-3063-71E3-85F5-5C88584B15CC -name IM_MOD_RL_tga_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::738CADE4-6C0A-5155-A1BE-8F789C1D92E7 -name feeds2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::26741B21-C241-E100-8BB1-8B679BC3E662 -name configure.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::7D491E89-C6D3-1E6E-F4BD-8E55260FE33E -name libexpat.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A4910EB3-0F1C-F6F0-CD2D-16A64BBAA92B -name calibre-fontconfig.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::8711327A-716D-B162-6AC6-2FB4AD071266 -name fb22lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::476CB977-5155-D56F-26CA-EB243AEBBA99 -name unrar.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::2DA1CC8D-AF5C-3B03-2060-301DFE0356CC -name mobi2oeb.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::2E2A9EDA-5386-444E-8479-557386794552 -name IM_MOD_RL_uil_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::4530C4C8-BCFA-E461-5F72-0EF5B553C7F5 -name pdf2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::29582E09-00E0-B2F9-475C-8C6D2E4BF7E8 -name any2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D3301E15-1B1A-E2AB-1B04-30A601B3FB44 -name IM_MOD_RL_cut_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::181B28B9-CF13-0C28-8380-B39DF6E7397D -name markdown-calibre.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::BC1D2D23-48ED-ECFF-2180-37C83554FDED -name Xext.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -379,7 +407,6 @@ File ::DE476170-B65E-B429-A23C-F822E4190FFC -name IM_MOD_RL_thumbnail_.dll -pare File ::31E46936-560D-1E88-8FC1-F8E590D2FD02 -name IM_MOD_RL_mpc_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::0C04692E-5DCF-864F-6640-2FF5BF12BA91 -name IM_MOD_RL_cmyk_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A620FEB9-39FE-B102-6963-FEDA25EBF2F1 -name IM_MOD_RL_pcd_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::0A4D27B3-157D-357A-6A86-32D8EB5B30D7 -name lit2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::80D1F9CA-D7DA-578E-CE25-4E0EE988D280 -name IM_MOD_RL_sct_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C85307C1-5F11-01EF-2193-95F37CB49822 -name IM_MOD_RL_pict_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::3ECF2FC0-91AA-9573-42B3-4BD784FA5BC9 -name IM_MOD_RL_gradient_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -389,46 +416,29 @@ File ::CBF83E89-39E0-D7C3-7902-A4A0ADCDEF48 -name IM_MOD_RL_jbig_.dll -parent 8E File ::FFF32C7F-BB57-4BB3-A52D-4E4F3496B967 -name calibre-debug.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::80A3C65A-553D-EA27-FAED-4F831578F4F8 -name magic.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::E2DF0DC3-3372-3CDF-5177-5B3F3BF84E66 -name IM_MOD_RL_mat_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::955B176E-5F6A-FFFA-9387-893E38C23E33 -name prs500.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4D938678-59AF-F5F6-697B-E3A5BE76B43B -name QtXml4.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::FCAEFF6A-1E96-FA23-C8AC-0F5F3297B14A -name rtf2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::0A5A70A8-39EC-B733-E807-9C358E5EA7A3 -name IM_MOD_RL_meta_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::E6419523-253A-3052-B9B4-0EA792EF4A64 -name pdftohtml.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::EF062C24-09D8-1DC8-891A-F9563BBA57C2 -name IM_MOD_RL_gray_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::E1D4796B-733B-F45A-2ECC-D498A1AC4EAD -name opf-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::0E21E0B1-C2D4-3F6D-E788-9EEB821128C3 -name web2disk.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::12DE2886-5926-F8AD-77C4-EAAC5DD9413C -name rtf2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::E96D95C6-2D53-A67B-C704-06BD213BBC86 -name mobi-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::A4D76085-EFC7-A237-7BB7-AA8A33BFB849 -name html2epub.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::27127583-9DC6-4397-3E86-052A515ED051 -name lrfviewer.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::7229472A-2A5A-2685-0223-2DF2CED0C9D4 -name comic2epub.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::396B4F78-FB45-C0B2-ACB3-97769CF5CD5D -name msvcr90.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 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 ::187D965E-40CE-18AB-5684-18C31A7FD8D4 -name any2epub.exe.local -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 ::9D0CC46C-E254-7F11-4B64-A6E8E16CF6FB -name mobi2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::72769321-EF4D-C796-5E76-3D5807772233 -name any2mobi.exe -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 ::A31CA43B-4456-BB26-A8EE-73C4C4B1F6FC -name pdftrim.exe -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 ::3A424677-A66A-CAA0-4FD2-4FE8086DBBA6 -name comic2mobi.exe.local -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 ::794E99A2-79AB-BABB-97A1-9E3482002EA8 -name imp-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::055ADB4B-20C5-E071-442F-4DA0A8D6F3C5 -name english.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::DE4F9AD0-3D79-865A-2DD9-4A4CB6886AFC -name lit-meta.exe.local -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 -File ::EAED9280-84D7-9768-9F89-CEC61CE549DF -name mobi-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::2FE2FF56-5CF5-15B7-2BD8-32100DF421DC -name _ssl.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::AE47BDA8-A1E5-2E84-28D7-DF8A84B18202 -name Microsoft.VC90.CRT.manifest -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A6B1C213-DC68-B7C3-8EDE-806286829899 -name w9xpopen.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D3E03CFA-4AF0-93FB-E04B-B282926099E0 -name IM_MOD_RL_label_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::6F40E97B-430C-08FE-30CA-9E6622EE29EB -name feeds2epub.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::345C74B8-B45D-A370-27F3-78CEA9EAB1E1 -name prs500.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::662783C0-3826-9869-8EB8-326B363D3686 -name IM_MOD_RL_clip_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::442D92A7-97B1-74BC-F150-A9992A925356 -name numpy.core.multiarray.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::54991918-D11F-EEAD-F7E3-0EE28F22249E -name IM_MOD_RL_pix_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -440,41 +450,27 @@ File ::5CB76241-5682-AE44-82D3-A6C8C66B88D6 -name IM_MOD_RL_bmp_.dll -parent 8E5 File ::A843E4DA-8671-C4F7-BA61-998AA1D278C8 -name numpy.linalg.lapack_lite.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::908EA762-5568-17BE-D77D-5DE5551895D0 -name IM_MOD_RL_raw_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::CC186E15-8751-A4AA-B2A7-D2E522F1F9DF -name lrf2lrs.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::36135E27-30B6-A0E9-5423-FDDFBCBD4FA2 -name feeds2disk.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A99CACD7-FE57-8A5E-BAA1-2D8B41925593 -name IM_MOD_RL_cip_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::782BE25A-B08E-D914-73F5-D92430823BE1 -name mobi2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C4649D7A-9312-8984-E7CD-A0AB794C5A8E -name IM_MOD_RL_pdf_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::B50467F0-07D0-B634-EB43-C4B721798A84 -name analyze.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::5531BA1B-8FDA-01B2-7DEE-6E9A116F7AB3 -name lrf-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::47658BFB-7389-6866-359E-7517C18E768D -name IM_MOD_RL_mpr_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::673BD772-ACE7-1695-EAAC-EDD1A3EA0425 -name pdftrim.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::3F6735E8-D4E6-A6F9-C9F8-4219E6BBC827 -name CORE_RL_jpeg_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::918BE500-1E97-90C0-3FB3-4056FE8D0E15 -name IM_MOD_RL_wbmp_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D59F7D54-24A7-774D-79EB-423A64E8CB21 -name IM_MOD_RL_stegano_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::BB8BCD59-9EBA-3D9B-D802-79D9C384AADB -name fb2-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::17F9A868-E52D-F961-9DB7-8AC69BA702EA -name CORE_RL_jp2_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::2ABAD420-B987-612E-C654-10BDB18DE638 -name html2oeb.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::81715796-F363-675F-998E-EEEF890009A2 -name calibre-fontconfig.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::5CA62422-C207-8C9C-79EB-45260E3DB37B -name odt2oeb.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::878003DC-9B1D-7C58-29F8-14D4565ABA64 -name IM_MOD_RL_yuv_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::602B3244-CF6C-F934-E86C-8161800DB150 -name coder.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C23261F0-19EA-2216-A8D6-45FCC4ECBECE -name win32file.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::100103F9-C269-9B03-A133-7D046DCC5B30 -name IM_MOD_RL_null_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::D0461A63-6890-CC43-23D1-48E938BF1E6D -name oeb2mobi.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::F3996144-7BA7-6038-FBB2-C210721BD20E -name lit-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::9BEE3580-3674-F4AE-C1F3-B8623E0E4FC8 -name IM_MOD_RL_pattern_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::AC4AE65E-78A4-28C0-1C1B-B99239D0A0EC -name rb-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::C025F962-60EE-E4EF-6428-93755DD24F7D -name web2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::6A41C4F0-802D-9999-2F7D-AF86466BC420 -name feeds2epub.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::58F70BF7-491E-38D1-B836-1BBF340AA602 -name IM_MOD_RL_plasma_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4B6C22CD-D139-FCAB-45FB-E9B7DADFFFED -name win32process.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::4F391A40-8D34-DFEA-2CEB-97A45FF5D234 -name lit2oeb.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::9698339D-6A1E-7CBC-A772-C9C4B10418BC -name librarything.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::A3F1DC1C-BEF6-CB6B-F7AC-39F34F4DFABD -name IM_MOD_RL_pcx_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::BE44B72D-2ED1-4983-F652-DE8814401946 -name CORE_RL_xlib_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::EC5B5C55-8347-0A8C-E9B5-28E45680E2F2 -name IM_MOD_RL_caption_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::519BA66E-0CD3-00EA-0932-8D225C4C7EC8 -name calibredb.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::EF7BD102-32B6-EEAB-1C3F-AC4059EFEB1E -name comic2lrf.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::B7E13F99-C8D3-F2FB-1E5F-E8530A77BB71 -name IM_MOD_RL_url_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D0762C72-29E8-85CC-8550-6AC9E9AE39E9 -name _win32sysloader.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4921649D-06BD-A568-3879-BD2D94423FCB -name pdftohtml.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -499,10 +495,8 @@ File ::80EC4265-6F3B-7F74-F995-4FA85E87A877 -name IM_MOD_RL_vicar_.dll -parent 8 File ::4CDC2DC5-5A3D-B773-A338-3E12E8C5BB9D -name IM_MOD_RL_psd_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4AF4C7B2-8926-4581-2896-C6436460C81F -name IM_MOD_RL_uyvy_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::BF71D048-1137-4453-960C-9267CB790EAD -name IM_MOD_RL_art_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::1BB40D21-9061-9B38-E653-26D808F7DEEA -name html2lrf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D9B6371C-332C-45FB-DAEE-1A247130F704 -name calibre-customize.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::605E727F-DE13-27FE-75C0-34567C468B18 -name calibre-parallel.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::61F250E4-BAA0-5AF3-F597-E53ADEC19877 -name comic2pdf.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::37306B68-BABB-418C-A2CA-BAF4E439D3F1 -name viewer.ico -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::6092C5A2-8740-2769-DB77-E0B664CD19EC -name PyQt4.QtWebKit.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::73C82473-A35A-23B8-067C-AA3120D1CEE2 -name win32pipe.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -521,14 +515,9 @@ File ::29022F2B-4E69-8624-2B2C-98A40E12DC0A -name calibre-server.exe -parent 8E5 File ::7592A236-4835-6A9D-56B1-78985267D9AD -name win32console.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::05F4A6BD-A7C3-5108-4708-1524EB0628D9 -name calibre.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::DEB8E703-365E-A7BB-2315-6306B2E5C978 -name win32evtlog.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::6C90CF50-4894-7672-BB1B-F7EE5EB631E3 -name lit2oeb.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::AB44B44C-E258-A5AB-9511-8D0FBB456EE8 -name IM_MOD_RL_gif_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::5D5F2AAD-6668-5E14-B84C-5D80C4CCC968 -name calibre-customize.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::5A0DA3BB-2659-F5AA-A305-C4810FA28D89 -name mobi2oeb.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::9A0C05D0-26E3-72C5-1F04-76F76ABB180F -name numpy.core.scalarmath.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::42616D6D-2797-559B-7E96-2685599993DF -name any2lit.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::CB47F917-A45E-B7DE-645C-CA33F005D1BD -name any2mobi.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::16AF75CF-CA5E-F533-6C28-7CF167B1215C -name comic2mobi.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::0888A744-B049-01E8-6AC8-ECC3EE2CEFE6 -name IM_MOD_RL_sgi_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::4AEEBBED-E749-15A9-E1F7-9F6BE2A2C3D0 -name _socket.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::35B19292-0C50-4AEE-0A79-B2F3BC34B529 -name w9xpopen.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -544,8 +533,27 @@ File ::6F5D62F3-5E63-0753-364C-01CAAF1002E0 -name IM_MOD_RL_magick_.dll -parent File ::9FDAC308-5D4F-A865-A09A-9FBF48162A47 -name IM_MOD_RL_djvu_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::5D748040-5973-EFF1-41FC-B424636C642E -name fetch-ebook-metadata.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::8B8655B8-3823-AA02-1CDA-02F5AD4677C0 -name fetch-ebook-metadata.exe -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} -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} -name Typical -parent SetupTypes +File ::8FC3D58A-F3FA-A2D1-711F-F4C3128620CE -name podofo.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::88034147-A376-B759-D48C-5F17A47E8CC3 -name ebook-meta.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::6E6F2A97-6614-F2A6-1751-95C099B909FD -name pdfmanipulate.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::AC456A9A-6653-5852-D1F7-B04E2C1AA481 -name isbndb.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::94580010-4CE4-8EC0-3834-9A2BCCB28C70 -name isbndb.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::BA087530-7CF4-5460-C9AA-DE4A796C9AEB -name pdfmanipulate.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::6AF80BFC-A813-074D-897A-856744A91949 -name ebook-convert.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::F8C59A30-9E90-0861-5604-95E7C69C3C80 -name ebook-convert.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::9389D511-7BF3-4D72-C78E-4F98DCE8F723 -name calibre-smtp.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::36E9023D-CCBC-9C59-CDA3-71A4D3203B25 -name ebook-meta.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::B757AEB8-74A7-1EA8-AC7C-C2B5F690B539 -name ebook-device.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::CD137106-C058-6035-57F3-420F9540386E -name _multiprocessing.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::7930C2FB-1C6F-3CFB-D8C6-BC677D96045F -name zlib1.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::7FDFCBEF-0687-FDA5-F5B7-632966E87BD3 -name calibre-complete.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::0450D3E0-07EB-F81F-DA39-038494E4C8FE -name win32com.shell.shell.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::8D7A36A6-4517-E995-E989-2E522E7A1438 -name calibre-smtp.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::9E4E5E8F-30C0-E631-9516-2AE01A5CA0E9 -name ebook-device.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::7BE6B538-70D5-A7EB-5F91-E14CE57B394B -name calibre-complete.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 +File ::F54BC3BB-5F21-3D81-043E-603D53754CFC -name pdftohtml.exe.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 InstallComponent 3EA07B17-04D8-6508-B535-96CC7173B49A -setup Install -type pane -conditions D7F585DB-0DEC-A94E-DAB0-94D558D82764 -title {Welcome Screen} -component Welcome -command insert -active Yes -parent StandardInstall Condition D7F585DB-0DEC-A94E-DAB0-94D558D82764 -active Yes -parent 3EA07B17-04D8-6508-B535-96CC7173B49A -title {Execute Script Condition} -component ExecuteScriptCondition -TreeObject::id D7F585DB-0DEC-A94E-DAB0-94D558D82764 @@ -1871,6 +1879,168 @@ No FreeBSD-4-x86,RootInstallDir /usr/local/<%ShortAppName%> +FreeBSD-5-x86,Active +No + +FreeBSD-5-x86,BuildSeparateArchives +No + +FreeBSD-5-x86,DefaultDirectoryPermission +0755 + +FreeBSD-5-x86,DefaultFilePermission +0755 + +FreeBSD-5-x86,Executable +<%AppName%>-<%Version%>-<%Platform%>-Install<%Ext%> + +FreeBSD-5-x86,FallBackToConsole +Yes + +FreeBSD-5-x86,InstallDir +<%Home%>/<%ShortAppName%> + +FreeBSD-5-x86,InstallMode +Standard + +FreeBSD-5-x86,InstallType +Typical + +FreeBSD-5-x86,ProgramExecutable +{} + +FreeBSD-5-x86,ProgramFolderAllUsers +No + +FreeBSD-5-x86,ProgramFolderName +<%AppName%> + +FreeBSD-5-x86,ProgramLicense +<%InstallDir%>/LICENSE.txt + +FreeBSD-5-x86,ProgramName +{} + +FreeBSD-5-x86,ProgramReadme +<%InstallDir%>/README.txt + +FreeBSD-5-x86,PromptForRoot +Yes + +FreeBSD-5-x86,RequireRoot +No + +FreeBSD-5-x86,RootInstallDir +/usr/local/<%ShortAppName%> + +FreeBSD-6-x86,Active +No + +FreeBSD-6-x86,BuildSeparateArchives +No + +FreeBSD-6-x86,DefaultDirectoryPermission +0755 + +FreeBSD-6-x86,DefaultFilePermission +0755 + +FreeBSD-6-x86,Executable +<%AppName%>-<%Version%>-<%Platform%>-Install<%Ext%> + +FreeBSD-6-x86,FallBackToConsole +Yes + +FreeBSD-6-x86,InstallDir +<%Home%>/<%ShortAppName%> + +FreeBSD-6-x86,InstallMode +Standard + +FreeBSD-6-x86,InstallType +Typical + +FreeBSD-6-x86,ProgramExecutable +{} + +FreeBSD-6-x86,ProgramFolderAllUsers +No + +FreeBSD-6-x86,ProgramFolderName +<%AppName%> + +FreeBSD-6-x86,ProgramLicense +<%InstallDir%>/LICENSE.txt + +FreeBSD-6-x86,ProgramName +{} + +FreeBSD-6-x86,ProgramReadme +<%InstallDir%>/README.txt + +FreeBSD-6-x86,PromptForRoot +Yes + +FreeBSD-6-x86,RequireRoot +No + +FreeBSD-6-x86,RootInstallDir +/usr/local/<%ShortAppName%> + +FreeBSD-7-x86,Active +No + +FreeBSD-7-x86,BuildSeparateArchives +No + +FreeBSD-7-x86,DefaultDirectoryPermission +0755 + +FreeBSD-7-x86,DefaultFilePermission +0755 + +FreeBSD-7-x86,Executable +<%AppName%>-<%Version%>-<%Platform%>-Install<%Ext%> + +FreeBSD-7-x86,FallBackToConsole +Yes + +FreeBSD-7-x86,InstallDir +<%Home%>/<%ShortAppName%> + +FreeBSD-7-x86,InstallMode +Standard + +FreeBSD-7-x86,InstallType +Typical + +FreeBSD-7-x86,ProgramExecutable +{} + +FreeBSD-7-x86,ProgramFolderAllUsers +No + +FreeBSD-7-x86,ProgramFolderName +<%AppName%> + +FreeBSD-7-x86,ProgramLicense +<%InstallDir%>/LICENSE.txt + +FreeBSD-7-x86,ProgramName +{} + +FreeBSD-7-x86,ProgramReadme +<%InstallDir%>/README.txt + +FreeBSD-7-x86,PromptForRoot +Yes + +FreeBSD-7-x86,RequireRoot +No + +FreeBSD-7-x86,RootInstallDir +/usr/local/<%ShortAppName%> + FreeBSD-x86,Active No @@ -2033,6 +2203,60 @@ Yes Linux-x86,RootInstallDir /opt/<%ShortAppName%> +Linux-x86_64,Active +No + +Linux-x86_64,BuildSeparateArchives +No + +Linux-x86_64,DefaultDirectoryPermission +0755 + +Linux-x86_64,DefaultFilePermission +0755 + +Linux-x86_64,Executable +<%AppName%>-<%Version%>-<%Platform%>-Install<%Ext%> + +Linux-x86_64,FallBackToConsole +Yes + +Linux-x86_64,InstallDir +<%Home%>/<%ShortAppName%> + +Linux-x86_64,InstallMode +Standard + +Linux-x86_64,InstallType +Typical + +Linux-x86_64,ProgramExecutable +{} + +Linux-x86_64,ProgramFolderAllUsers +No + +Linux-x86_64,ProgramFolderName +<%AppName%> + +Linux-x86_64,ProgramLicense +<%InstallDir%>/LICENSE.txt + +Linux-x86_64,ProgramName +{} + +Linux-x86_64,ProgramReadme +<%InstallDir%>/README.txt + +Linux-x86_64,PromptForRoot +Yes + +Linux-x86_64,RequireRoot +No + +Linux-x86_64,RootInstallDir +/usr/local/<%ShortAppName%> + Solaris-sparc,Active No @@ -2087,6 +2311,60 @@ No Solaris-sparc,RootInstallDir /usr/local/<%ShortAppName%> +Solaris-x86,Active +No + +Solaris-x86,BuildSeparateArchives +No + +Solaris-x86,DefaultDirectoryPermission +0755 + +Solaris-x86,DefaultFilePermission +0755 + +Solaris-x86,Executable +<%AppName%>-<%Version%>-<%Platform%>-Install<%Ext%> + +Solaris-x86,FallBackToConsole +Yes + +Solaris-x86,InstallDir +<%Home%>/<%ShortAppName%> + +Solaris-x86,InstallMode +Standard + +Solaris-x86,InstallType +Typical + +Solaris-x86,ProgramExecutable +{} + +Solaris-x86,ProgramFolderAllUsers +No + +Solaris-x86,ProgramFolderName +<%AppName%> + +Solaris-x86,ProgramLicense +<%InstallDir%>/LICENSE.txt + +Solaris-x86,ProgramName +{} + +Solaris-x86,ProgramReadme +<%InstallDir%>/README.txt + +Solaris-x86,PromptForRoot +Yes + +Solaris-x86,RequireRoot +No + +Solaris-x86,RootInstallDir +/usr/local/<%ShortAppName%> + TarArchive,Active No From 7475c676e410e2a900f9025b0000724182a2eb11 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 31 May 2009 15:17:36 -0700 Subject: [PATCH 02/20] Misc. fixes --- src/calibre/ebooks/conversion/cli.py | 17 +++++++++-------- src/calibre/ebooks/mobi/writer.py | 8 +++++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/calibre/ebooks/conversion/cli.py b/src/calibre/ebooks/conversion/cli.py index 73e1a1e523..dbf86c4d94 100644 --- a/src/calibre/ebooks/conversion/cli.py +++ b/src/calibre/ebooks/conversion/cli.py @@ -7,6 +7,15 @@ __docformat__ = 'restructuredtext en' Command line interface to conversion sub-system ''' +import sys, os +from optparse import OptionGroup, Option + +from calibre.utils.config import OptionParser +from calibre.utils.logging import Log +from calibre.constants import preferred_encoding +from calibre.customize.conversion import OptionRecommendation + + USAGE = '%prog ' + _('''\ input_file output_file [options] @@ -33,14 +42,6 @@ option. For full documentation of the conversion system see ''') + 'http://calibre.kovidgoyal.net/user_manual/conversion.html' -import sys, os -from optparse import OptionGroup, Option - -from calibre.utils.config import OptionParser -from calibre.utils.logging import Log -from calibre.constants import preferred_encoding -from calibre.customize.conversion import OptionRecommendation - def print_help(parser, log): help = parser.format_help().encode(preferred_encoding, 'replace') log(help) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 288fa01c73..7d63744e57 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -357,7 +357,10 @@ class MobiWriter(object): self._map_image_names() self._generate_text() if INDEXING and not self.opts.no_mobi_index: - self._generate_index() + try: + self._generate_index() + except: + self._oeb.log.exception('Failed to generate index') self._generate_images() def _map_image_names(self): @@ -507,6 +510,9 @@ class MobiWriter(object): ctoc = self._generate_ctoc() indxt, indxt_count, indices, last_name = \ self._generate_indxt(ctoc) + if last_name is None: + self._oeb.log.warn('Input document has no TOC. No idex generated.') + return indx1 = StringIO() indx1.write('INDX'+pack('>I', 0xc0)) # header length From 654dfbdf2c9096c3efe295cc6f8a411fa1b6921d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 31 May 2009 16:26:50 -0700 Subject: [PATCH 03/20] Use os.path.relpath instead of custom implementation --- src/calibre/__init__.py | 34 +---------------------------- src/calibre/ebooks/metadata/opf2.py | 7 +++--- src/calibre/ebooks/mobi/writer.py | 13 ++++++----- src/calibre/gui2/main.py | 2 +- 4 files changed, 13 insertions(+), 43 deletions(-) diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index 79dc659f34..2bbf18d9e0 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -284,39 +284,7 @@ def launch(path_or_url): path_or_url = 'file:'+path_or_url QDesktopServices.openUrl(QUrl(path_or_url)) -def relpath(target, base=os.curdir): - """ - Return a relative path to the target from either the current dir or an optional base dir. - Base can be a directory specified either as absolute or relative to current dir. - """ - - #if not os.path.exists(target): - # raise OSError, 'Target does not exist: '+target - if target == base: - raise ValueError('target and base are both: %s'%target) - if not os.path.isdir(base): - raise OSError, 'Base is not a directory or does not exist: '+base - - base_list = (os.path.abspath(base)).split(os.sep) - target_list = (os.path.abspath(target)).split(os.sep) - - # On the windows platform the target may be on a completely different drive from the base. - if iswindows and base_list[0].upper() != target_list[0].upper(): - raise OSError, 'Target is on a different drive to base. Target: '+repr(target)+', base: '+repr(base) - - # Starting from the filepath root, work out how much of the filepath is - # shared by base and target. - for i in range(min(len(base_list), len(target_list))): - if base_list[i] != target_list[i]: break - else: - # If we broke out of the loop, i is pointing to the first differing path elements. - # If we didn't break out of the loop, i is pointing to identical path elements. - # Increment i so that in all cases it points to the first differing path elements. - i+=1 - - rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:] - return os.path.join(*rel_list) - +relpath = os.path.relpath _spat = re.compile(r'^the\s+|^a\s+|^an\s+', re.IGNORECASE) def english_sort(x, y): ''' diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 4d1af0ee75..f801dbf65c 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -15,7 +15,6 @@ from lxml import etree from dateutil import parser from calibre.ebooks.chardet import xml_to_unicode -from calibre import relpath from calibre.constants import __appname__, __version__ from calibre.ebooks.metadata.toc import TOC from calibre.ebooks.metadata import MetaInformation, string_to_authors @@ -86,8 +85,8 @@ class Resource(object): if self.path == basedir: return ''+frag try: - rpath = relpath(self.path, basedir) - except OSError: # On windows path and basedir could be on different drives + rpath = os.path.relpath(self.path, basedir) + except ValueError: # On windows path and basedir could be on different drives rpath = self.path if isinstance(rpath, unicode): rpath = rpath.encode('utf-8') @@ -560,7 +559,7 @@ class OPF(object): has_path = True break if not has_path: - href = relpath(path, self.base_dir).replace(os.sep, '/') + href = os.path.relpath(path, self.base_dir).replace(os.sep, '/') item = self.create_manifest_item(href, media_type) manifest = self.manifest_ppath(self.root)[0] manifest.append(item) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 7d63744e57..f63eaa0940 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -511,7 +511,7 @@ class MobiWriter(object): indxt, indxt_count, indices, last_name = \ self._generate_indxt(ctoc) if last_name is None: - self._oeb.log.warn('Input document has no TOC. No idex generated.') + self._oeb.log.warn('Input document has no TOC. No index generated.') return indx1 = StringIO() @@ -628,8 +628,8 @@ class MobiWriter(object): self._last_toc_entry = None ctoc = StringIO() - def add_node(node, cls): - t = node.title + def add_node(node, cls, title=None): + t = node.title if title is None else title if t and t.strip(): t = t.strip() if not isinstance(t, unicode): @@ -640,8 +640,10 @@ class MobiWriter(object): self._ctoc_name_map[node] = t ctoc.write(decint(len(t), DECINT_FORWARD)+t) + first = True for child in toc.iter(): - add_node(child, 'chapter') + add_node(child, 'chapter', title='Title Page' if first else None) + first = False return align_block(ctoc.getvalue()) @@ -842,7 +844,8 @@ class MobiWriter(object): if INDEXING: # Write unknown EXTH records as 0s for code, size in [(204,4), (205,4), (206,4), (207,4), (300,40)]: - exth.write(pack('>I', code)+'\0'*size) + exth.write(pack('>II', code, 8+size)+'\0'*size) + nrecs += 1 exth = exth.getvalue() trail = len(exth) % 4 pad = '\0' * (4 - trail) # Always pad w/ at least 1 byte diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 0a77839ce1..bdc4568dce 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -1670,7 +1670,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): def update_found(self, version): os = 'windows' if iswindows else 'osx' if isosx else 'linux' url = 'http://%s.kovidgoyal.net/download_%s'%(__appname__, os) - self.latest_version = '
'+_('' + self.latest_version = '
' + _('' 'Latest version: %s')%(url, version) self.vanity.setText(self.vanity_template%\ (dict(version=self.latest_version, From 029fd0b3ac053cc18967b90bbd5898a25a9f7b71 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 31 May 2009 18:00:17 -0700 Subject: [PATCH 04/20] More misc. fixes --- installer/linux/freeze.py | 2 ++ installer/osx/freeze.py | 2 +- installer/windows/freeze.py | 1 + src/calibre/ebooks/mobi/writer.py | 2 +- src/calibre/gui2/convert/page_setup.py | 6 ++++++ src/calibre/gui2/images/welcome_wizard.svg | 6 +++--- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/installer/linux/freeze.py b/installer/linux/freeze.py index 31f645dff1..1fc18d3600 100644 --- a/installer/linux/freeze.py +++ b/installer/linux/freeze.py @@ -93,6 +93,8 @@ def freeze(): 'dateutil', 'dns', 'email'] includes += ['calibre.web.feeds.recipes.'+r for r in recipe_modules] + includes += [x.split('/')[-1].rpartition('.')[0] for x in \ + glob.glob('src/calibre/gui2/convert/*.py')] LOADER = '/tmp/loader.py' open(LOADER, 'wb').write('# This script is never actually used.\nimport sys') diff --git a/installer/osx/freeze.py b/installer/osx/freeze.py index 75621da017..a16dd3aaee 100644 --- a/installer/osx/freeze.py +++ b/installer/osx/freeze.py @@ -347,7 +347,7 @@ def main(): 'PyQt4.QtSvg', 'PyQt4.QtWebKit', 'commands', 'mechanize', 'ClientForm', 'usbobserver', 'genshi', 'calibre.web.feeds.recipes.*', - 'calibre.ebooks.lrf.any.*', 'calibre.ebooks.lrf.feeds.*', + 'calibre.gui2.convert.*', 'keyword', 'codeop', 'pydoc', 'readline', 'BeautifulSoup', 'calibre.ebooks.lrf.fonts.prs500.*', 'dateutil', 'email.iterators', diff --git a/installer/windows/freeze.py b/installer/windows/freeze.py index f545f7e534..ae5b503be7 100644 --- a/installer/windows/freeze.py +++ b/installer/windows/freeze.py @@ -175,6 +175,7 @@ def main(args=sys.argv): 'BeautifulSoup', 'pyreadline', 'pydoc', 'IPython.Extensions.*', 'calibre.web.feeds.recipes.*', + 'calibre.gui2.convert.*', 'calibre.ebooks.lrf.fonts.prs500.*', 'PyQt4.QtWebKit', 'PyQt4.QtNetwork', ], diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index f63eaa0940..e65a090b22 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -642,7 +642,7 @@ class MobiWriter(object): first = True for child in toc.iter(): - add_node(child, 'chapter', title='Title Page' if first else None) + add_node(child, 'chapter')#, title='Title Page' if first else None) first = False return align_block(ctoc.getvalue()) diff --git a/src/calibre/gui2/convert/page_setup.py b/src/calibre/gui2/convert/page_setup.py index 3f59537db0..9faaf04ecc 100644 --- a/src/calibre/gui2/convert/page_setup.py +++ b/src/calibre/gui2/convert/page_setup.py @@ -49,6 +49,12 @@ class PageSetupWidget(Widget, Ui_Form): x.setMouseTracking(True) self.connect(x, SIGNAL('entered(QModelIndex)'), self.show_desc) self.initialize_options(get_option, get_help, db, book_id) + it = unicode(self.opt_input_profile.toolTip()) + self.opt_input_profile.setToolTip('

'+it.replace('t.','t.\n
')) + it = unicode(self.opt_output_profile.toolTip()) + self.opt_output_profile.setToolTip('

'+it.replace('t.','ce.\n
')) + + def show_desc(self, index): desc = index.model().data(index, Qt.StatusTipRole).toString() diff --git a/src/calibre/gui2/images/welcome_wizard.svg b/src/calibre/gui2/images/welcome_wizard.svg index d8ed0e69c9..5d5f4635d6 100644 --- a/src/calibre/gui2/images/welcome_wizard.svg +++ b/src/calibre/gui2/images/welcome_wizard.svg @@ -9,8 +9,8 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="250" - height="525" + width="150" + height="350" id="svg2347" sodipodi:version="0.32" inkscape:version="0.46" @@ -1149,7 +1149,7 @@ + transform="matrix(1.2103698,0,0,2.7823904,-2.5000367,-12.695448)"> Date: Sun, 31 May 2009 20:23:22 -0700 Subject: [PATCH 05/20] Fix PIL imports on OS X --- src/calibre/ebooks/pdb/ereader/writer.py | 7 ++++++- src/calibre/ebooks/pml/output.py | 17 +++++++++++------ src/calibre/ebooks/rb/writer.py | 12 ++++++++---- src/calibre/ebooks/rtf/rtfml.py | 13 +++++++++---- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/calibre/ebooks/pdb/ereader/writer.py b/src/calibre/ebooks/pdb/ereader/writer.py index 79cb11fdb9..dc32246957 100644 --- a/src/calibre/ebooks/pdb/ereader/writer.py +++ b/src/calibre/ebooks/pdb/ereader/writer.py @@ -11,7 +11,12 @@ __docformat__ = 'restructuredtext en' import struct import zlib -import Image +try: + from PIL import Image + Image +except ImportError: + import Image + import cStringIO from calibre.ebooks.pdb.formatwriter import FormatWriter diff --git a/src/calibre/ebooks/pml/output.py b/src/calibre/ebooks/pml/output.py index 8be8cc18ee..700407d058 100644 --- a/src/calibre/ebooks/pml/output.py +++ b/src/calibre/ebooks/pml/output.py @@ -6,7 +6,12 @@ __docformat__ = 'restructuredtext en' import os -import Image +try: + from PIL import Image + Image +except ImportError: + import Image + import cStringIO from calibre.customize.conversion import OutputFormatPlugin @@ -27,24 +32,24 @@ class PMLOutput(OutputFormatPlugin): content = pmlmlizer.extract_content(oeb_book, opts) with open(os.path.join(tdir, 'index.pml'), 'wb') as out: out.write(content.encode('utf-8')) - + self.write_images(oeb_book.manifest, tdir) pmlz = ZipFile(output_path, 'w') pmlz.add_dir(tdir) - + def write_images(self, manifest, out_dir): for item in manifest: if item.media_type in OEB_IMAGES: im = Image.open(cStringIO.StringIO(item.data)) - + data = cStringIO.StringIO() im.save(data, 'PNG') data = data.getvalue() - + name = os.path.splitext(os.path.basename(item.href))[0] + '.png' path = os.path.join(out_dir, name) - + with open(path, 'wb') as out: out.write(data) diff --git a/src/calibre/ebooks/rb/writer.py b/src/calibre/ebooks/rb/writer.py index f9057d5c61..4e697f6d36 100644 --- a/src/calibre/ebooks/rb/writer.py +++ b/src/calibre/ebooks/rb/writer.py @@ -1,4 +1,3 @@ -import os.path # -*- coding: utf-8 -*- __license__ = 'GPL 3' @@ -9,7 +8,12 @@ import os import struct import zlib -import Image +try: + from PIL import Image + Image +except ImportError: + import Image + import cStringIO from calibre.ebooks.rb.rbml import RBMLizer @@ -121,7 +125,7 @@ class RBWriter(object): name = unique_name(name, used_names) used_names.append(name) self.name_map[os.path.basename(item.href)] = name - + images.append((name, data)) return images @@ -140,4 +144,4 @@ class RBWriter(object): text += 'BODY=index.html\n' return text - \ No newline at end of file + diff --git a/src/calibre/ebooks/rtf/rtfml.py b/src/calibre/ebooks/rtf/rtfml.py index cb8e9af883..dbecd62faf 100644 --- a/src/calibre/ebooks/rtf/rtfml.py +++ b/src/calibre/ebooks/rtf/rtfml.py @@ -11,7 +11,12 @@ Transform OEB content into RTF markup import os import re -import Image +try: + from PIL import Image + Image +except ImportError: + import Image + import cStringIO from calibre.ebooks.oeb.base import XHTML, XHTML_NS, barename, namespace, \ @@ -73,7 +78,7 @@ TODO: * Fonts ''' class RTFMLizer(object): - + def __init__(self, ignore_tables=False): self.ignore_tables = ignore_tables @@ -120,7 +125,7 @@ class RTFMLizer(object): data = cStringIO.StringIO() im.save(data, 'JPEG') data = data.getvalue() - + raw_hex = '' for char in data: raw_hex += hex(ord(char)).replace('0x', '').rjust(2, '0') @@ -230,5 +235,5 @@ class RTFMLizer(object): text += '%s ' % elem.tail else: text += '{\\par \\pard \\hyphpar %s}' % elem.tail - + return text From f43a4467d36dcdbb0e3867bf6de9a1a4d941bf71 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 1 Jun 2009 09:54:01 -0700 Subject: [PATCH 06/20] Fix climate progress recipe --- src/calibre/web/feeds/recipes/recipe_climate_progress.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/calibre/web/feeds/recipes/recipe_climate_progress.py b/src/calibre/web/feeds/recipes/recipe_climate_progress.py index 081997f7fe..c49c4718a3 100644 --- a/src/calibre/web/feeds/recipes/recipe_climate_progress.py +++ b/src/calibre/web/feeds/recipes/recipe_climate_progress.py @@ -32,8 +32,6 @@ class ClimateProgress(BasicNewsRecipe): html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"' - remove_tags = [dict(name='a', attrs={'rel':'bookmark'})] - feeds = [(u'Posts', u'http://feeds.feedburner.com/climateprogress/lCrX')] def preprocess_html(self, soup): From e3fabe843a1a15c312841ca68fde039e0d06adeb Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 1 Jun 2009 18:12:57 -0700 Subject: [PATCH 07/20] Switch to using a C extension module to interface with fontconfig. This means that calibre now has a build time dependency on fontconfig as well. You can tell calibre where to find the font config headers and library via the environment variables: FC_INC_DIR and FC_LIB_DIR --- installer/osx/freeze.py | 2 - setup.py | 13 + src/calibre/constants.py | 3 +- src/calibre/ebooks/lrf/__init__.py | 3 +- src/calibre/gui2/convert/comic_input.py | 1 + src/calibre/gui2/convert/epub_output.py | 1 + src/calibre/gui2/convert/lrf_output.py | 1 + src/calibre/gui2/convert/mobi_output.py | 2 + src/calibre/gui2/convert/pdb_output.py | 1 + src/calibre/gui2/convert/pdf_output.py | 1 + src/calibre/gui2/convert/txt_output.py | 1 + src/calibre/gui2/convert/xpath_wizard.py | 2 +- src/calibre/gui2/convert/xpath_wizard.ui | 106 +++--- src/calibre/gui2/dialogs/config.py | 6 +- src/calibre/gui2/dialogs/scheduler.ui | 2 +- src/calibre/gui2/main.py | 18 +- src/calibre/gui2/widgets.py | 4 +- src/calibre/gui2/wizard/__init__.py | 10 + src/calibre/linux.py | 1 - src/calibre/utils/fontconfig.py | 400 ----------------------- src/calibre/utils/fonts/__init__.py | 150 +++++++++ src/calibre/utils/fonts/fontconfig.c | 331 +++++++++++++++++++ 22 files changed, 596 insertions(+), 463 deletions(-) delete mode 100644 src/calibre/utils/fontconfig.py create mode 100644 src/calibre/utils/fonts/__init__.py create mode 100644 src/calibre/utils/fonts/fontconfig.c diff --git a/installer/osx/freeze.py b/installer/osx/freeze.py index a16dd3aaee..8dee8feb7a 100644 --- a/installer/osx/freeze.py +++ b/installer/osx/freeze.py @@ -254,8 +254,6 @@ _check_symlinks_prescript() os.link(os.path.expanduser('~/pdftohtml/pdftohtml'), os.path.join(frameworks_dir, 'pdftohtml')) os.link(os.path.expanduser('~/pdftohtml/libpoppler.4.dylib'), os.path.join(frameworks_dir, 'libpoppler.4.dylib')) - print 'Adding plugins' - module_dir = os.path.join(resource_dir, 'lib', 'python2.6', 'lib-dynload') print 'Adding fontconfig' for f in glob.glob(os.path.expanduser('~/fontconfig-bundled/*')): dest = os.path.join(frameworks_dir, os.path.basename(f)) diff --git a/setup.py b/setup.py index ee2d54cc5a..14bbbf0a3f 100644 --- a/setup.py +++ b/setup.py @@ -76,8 +76,21 @@ if __name__ == '__main__': print 'WARNING: PoDoFo not found on your system. Various PDF related', print 'functionality will not work.' + fc_inc = '/usr/include/fontconfig' if islinux else \ + r'C:\cygwin\home\kovid\fontconfig\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 \ + '/Users/kovid/fontconfig/lib' + ext_modules = optional + [ + Extension('calibre.plugins.fontconfig', + sources = ['src/calibre/utils/fonts/fontconfig.c'], + include_dirs = [os.environ.get('FC_INC_DIR', fc_inc)], + libraries=['fontconfig'], + library_dirs=[os.environ.get('FC_LIB_DIR', fc_lib)]), + Extension('calibre.plugins.lzx', sources=['src/calibre/utils/lzx/lzxmodule.c', 'src/calibre/utils/lzx/compressor.c', diff --git a/src/calibre/constants.py b/src/calibre/constants.py index e7f7ffc344..bee906e01e 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -59,7 +59,8 @@ if plugins is None: plugin_path = getattr(pkg_resources, 'resource_filename')('calibre', 'plugins') sys.path.insert(0, plugin_path) - for plugin in ['pictureflow', 'lzx', 'msdes', 'podofo', 'cPalmdoc'] + \ + for plugin in ['pictureflow', 'lzx', 'msdes', 'podofo', 'cPalmdoc', + 'fontconfig'] + \ (['winutil'] if iswindows else []) + \ (['usbobserver'] if isosx else []): try: diff --git a/src/calibre/ebooks/lrf/__init__.py b/src/calibre/ebooks/lrf/__init__.py index 9f6be65e3a..e4a18a1f91 100644 --- a/src/calibre/ebooks/lrf/__init__.py +++ b/src/calibre/ebooks/lrf/__init__.py @@ -35,7 +35,8 @@ class PRS500_PROFILE(object): name = 'prs500' def find_custom_fonts(options, logger): - from calibre.utils.fontconfig import files_for_family + from calibre.utils.fonts import fontconfig + files_for_family = fontconfig.files_for_family fonts = {'serif' : None, 'sans' : None, 'mono' : None} def family(cmd): return cmd.split(',')[-1].strip() diff --git a/src/calibre/gui2/convert/comic_input.py b/src/calibre/gui2/convert/comic_input.py index 00e095fb2a..e53d169e9a 100644 --- a/src/calibre/gui2/convert/comic_input.py +++ b/src/calibre/gui2/convert/comic_input.py @@ -13,6 +13,7 @@ from calibre.gui2.convert import Widget class PluginWidget(Widget, Ui_Form): TITLE = _('Comic Input') + HELP = _('Options specific to')+' comic '+_('input') def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, 'comic_input', diff --git a/src/calibre/gui2/convert/epub_output.py b/src/calibre/gui2/convert/epub_output.py index 74f0913398..98699f705f 100644 --- a/src/calibre/gui2/convert/epub_output.py +++ b/src/calibre/gui2/convert/epub_output.py @@ -13,6 +13,7 @@ from calibre.gui2.convert import Widget class PluginWidget(Widget, Ui_Form): TITLE = _('EPUB Output') + HELP = _('Options specific to')+' EPUB '+_('output') def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, 'epub_output', diff --git a/src/calibre/gui2/convert/lrf_output.py b/src/calibre/gui2/convert/lrf_output.py index 78a7bfa3fa..a9f1bfa6d1 100644 --- a/src/calibre/gui2/convert/lrf_output.py +++ b/src/calibre/gui2/convert/lrf_output.py @@ -16,6 +16,7 @@ font_family_model = None class PluginWidget(Widget, Ui_Form): TITLE = _('LRF Output') + HELP = _('Options specific to')+' LRF '+_('output') def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, 'lrf_output', diff --git a/src/calibre/gui2/convert/mobi_output.py b/src/calibre/gui2/convert/mobi_output.py index 32cb74ba47..797ab31493 100644 --- a/src/calibre/gui2/convert/mobi_output.py +++ b/src/calibre/gui2/convert/mobi_output.py @@ -13,6 +13,8 @@ from calibre.gui2.convert import Widget class PluginWidget(Widget, Ui_Form): TITLE = _('MOBI Output') + HELP = _('Options specific to')+' MOBI '+_('output') + def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, 'mobi_output', diff --git a/src/calibre/gui2/convert/pdb_output.py b/src/calibre/gui2/convert/pdb_output.py index 66563c3b24..57bf218d33 100644 --- a/src/calibre/gui2/convert/pdb_output.py +++ b/src/calibre/gui2/convert/pdb_output.py @@ -14,6 +14,7 @@ format_model = None class PluginWidget(Widget, Ui_Form): TITLE = _('PDB Output') + HELP = _('Options specific to')+' PDB '+_('output') def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, 'pdb_output', ['format']) diff --git a/src/calibre/gui2/convert/pdf_output.py b/src/calibre/gui2/convert/pdf_output.py index 2225b59436..99fb817cfc 100644 --- a/src/calibre/gui2/convert/pdf_output.py +++ b/src/calibre/gui2/convert/pdf_output.py @@ -15,6 +15,7 @@ orientation_model = None class PluginWidget(Widget, Ui_Form): TITLE = _('PDF Output') + HELP = _('Options specific to')+' PDF '+_('output') def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, 'pdf_output', ['paper_size', 'orientation']) diff --git a/src/calibre/gui2/convert/txt_output.py b/src/calibre/gui2/convert/txt_output.py index 6c084b18ff..dd36dc8cfc 100644 --- a/src/calibre/gui2/convert/txt_output.py +++ b/src/calibre/gui2/convert/txt_output.py @@ -14,6 +14,7 @@ newline_model = None class PluginWidget(Widget, Ui_Form): TITLE = _('TXT Output') + HELP = _('Options specific to')+' TXT '+_('output') def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, 'txt_output', ['newline']) diff --git a/src/calibre/gui2/convert/xpath_wizard.py b/src/calibre/gui2/convert/xpath_wizard.py index ebb43e7e79..d2a0d55a48 100644 --- a/src/calibre/gui2/convert/xpath_wizard.py +++ b/src/calibre/gui2/convert/xpath_wizard.py @@ -38,7 +38,7 @@ class Wizard(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) - self.resize(400, 300) + self.resize(440, 480) self.verticalLayout = QVBoxLayout(self) self.widget = WizardWidget(self) self.verticalLayout.addWidget(self.widget) diff --git a/src/calibre/gui2/convert/xpath_wizard.ui b/src/calibre/gui2/convert/xpath_wizard.ui index c23a2d1b7c..6f67312c47 100644 --- a/src/calibre/gui2/convert/xpath_wizard.ui +++ b/src/calibre/gui2/convert/xpath_wizard.ui @@ -1,7 +1,8 @@ - + + Form - - + + 0 0 @@ -9,133 +10,146 @@ 381 - + Form - - - - + + + + Match HTML &tags with tag name: - + tag - - - + + + true - + * - + a - + br - + div - + h1 - + h2 - + h3 - + h4 - + h5 - + h6 - + hr - + span - - - + + + Having the &attribute: - + attribute - - + + - - - + + + With &value: - + value - - - - - - + + + (A regular expression) - - - - <p>For example, to match all h2 tags that have class="chapter", set tag to <i>h2</i>, attribute to <i>class</i> and value to <i>chapter</i>.</p><p>Leaving attribute blank will match any attribute and leaving value blank will match any value. Setting tag to * will match any tag.</p><p>To learn more advanced usage of XPath see the <a href="http://calibre.kovidgoyal.net/user_manual/xpath.html">XPath Tutorial</a>. + + + + + + + <p>For example, to match all h2 tags that have class="chapter", set tag to <i>h2</i>, attribute to <i>class</i> and value to <i>chapter</i>.</p><p>Leaving attribute blank will match any attribute and leaving value blank will match any value. Setting tag to * will match any tag.</p><p>To learn more advanced usage of XPath see the <a href="http://calibre.kovidgoyal.net/user_manual/xpath.html">XPath Tutorial</a>. - + true - + true + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/src/calibre/gui2/dialogs/config.py b/src/calibre/gui2/dialogs/config.py index c0030d7b3e..59e148046d 100644 --- a/src/calibre/gui2/dialogs/config.py +++ b/src/calibre/gui2/dialogs/config.py @@ -59,7 +59,6 @@ class ConfigTabs(QTabWidget): fromlist=[1]) pw = input_widget.PluginWidget pw.ICON = ':/images/forward.svg' - pw.HELP = _('Options specific to the input format.') self.widgets.append(widget_factory(pw)) except ImportError: continue @@ -71,14 +70,15 @@ class ConfigTabs(QTabWidget): fromlist=[1]) pw = output_widget.PluginWidget pw.ICON = ':/images/forward.svg' - pw.HELP = _('Options specific to the input format.') self.widgets.append(widget_factory(pw)) except ImportError: continue - for widget in self.widgets: + for i, widget in enumerate(self.widgets): self.addTab(widget, widget.TITLE.replace('\n', ' ').replace('&', '&&')) + self.setTabToolTip(i, widget.HELP if widget.HELP else widget.TITLE) + self.setUsesScrollButtons(True) def commit(self): for widget in self.widgets: diff --git a/src/calibre/gui2/dialogs/scheduler.ui b/src/calibre/gui2/dialogs/scheduler.ui index 84eb3daa6f..497b1215dc 100644 --- a/src/calibre/gui2/dialogs/scheduler.ui +++ b/src/calibre/gui2/dialogs/scheduler.ui @@ -6,7 +6,7 @@ 0 0 - 738 + 767 575 diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index bdc4568dce..ad472ed4db 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -107,7 +107,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): MainWindow.__init__(self, opts, parent) # Initialize fontconfig in a separate thread as this can be a lengthy # process if run for the first time on this machine - self.fc = __import__('calibre.utils.fontconfig', fromlist=1) + from calibre.utils.fonts import fontconfig + self.fc = fontconfig self.listener = Listener(listener) self.check_messages_timer = QTimer() self.connect(self.check_messages_timer, SIGNAL('timeout()'), @@ -1735,7 +1736,12 @@ def run_gui(opts, args, actions, listener, app): if getattr(main, 'restart_after_quit', False): e = sys.executable if getattr(sys, 'froze', False) else sys.argv[0] print 'Restarting with:', e, sys.argv - os.execvp(e, sys.argv) + if hasattr(sys, 'frameworks_dir'): + app = os.path.dirname(os.path.dirname(sys.frameworks_dir)) + import subprocess + subprocess.Popen('sleep 3s; open '+app, shell=True) + else: + os.execvp(e, sys.argv) else: if iswindows: try: @@ -1829,7 +1835,9 @@ if __name__ == '__main__': logfile = os.path.join(os.path.expanduser('~'), 'calibre.log') if os.path.exists(logfile): log = open(logfile).read().decode('utf-8', 'ignore') - d = QErrorMessage(('Error:%s
Traceback:
' - '%sLog:
%s')%(unicode(err), unicode(tb), log)) - d.exec_() + d = QErrorMessage() + d.showMessage(('Error:%s
Traceback:
' + '%sLog:
%s')%(unicode(err), + unicode(tb).replace('\n', '
'), + log.replace('\n', '
'))) diff --git a/src/calibre/gui2/widgets.py b/src/calibre/gui2/widgets.py index d6df39b5d2..e918fa060e 100644 --- a/src/calibre/gui2/widgets.py +++ b/src/calibre/gui2/widgets.py @@ -16,7 +16,7 @@ from calibre.gui2 import human_readable, NONE, TableView, \ from calibre.gui2.dialogs.job_view_ui import Ui_Dialog from calibre.gui2.filename_pattern_ui import Ui_Form from calibre import fit_image -from calibre.utils.fontconfig import find_font_families +from calibre.utils.fonts import fontconfig from calibre.ebooks.metadata.meta import metadata_from_filename from calibre.utils.config import prefs @@ -293,7 +293,7 @@ class FontFamilyModel(QAbstractListModel): def __init__(self, *args): QAbstractListModel.__init__(self, *args) try: - self.families = find_font_families() + self.families = fontconfig.find_font_families() except: self.families = [] print 'WARNING: Could not load fonts' diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index 1a0b626fbb..467aecd93f 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -23,6 +23,7 @@ from calibre.gui2.wizard.library_ui import Ui_WizardPage as LibraryUI from calibre.gui2.wizard.finish_ui import Ui_WizardPage as FinishUI from calibre.gui2.wizard.kindle_ui import Ui_WizardPage as KindleUI from calibre.gui2.wizard.stanza_ui import Ui_WizardPage as StanzaUI +from calibre.gui2 import min_available_height, available_width from calibre.utils.config import dynamic, prefs from calibre.gui2 import NONE, choose_dir, error_dialog @@ -483,6 +484,15 @@ class Wizard(QWizard): self.setPage(self.stanza_page.ID, self.stanza_page) self.device_extra_page = None + nh, nw = min_available_height()-75, available_width()-30 + if nh < 0: + nh = 580 + if nw < 0: + nw = 400 + nh = min(400, nh) + nw = min(580, nw) + self.resize(nw, nh) + def accept(self): self.device_page.commit() diff --git a/src/calibre/linux.py b/src/calibre/linux.py index 1492374b8e..183ba73e04 100644 --- a/src/calibre/linux.py +++ b/src/calibre/linux.py @@ -27,7 +27,6 @@ entry_points = { 'librarything = calibre.ebooks.metadata.library_thing:main', 'calibre-debug = calibre.debug:main', 'calibredb = calibre.library.cli:main', - 'calibre-fontconfig = calibre.utils.fontconfig:main', 'calibre-parallel = calibre.utils.ipc.worker:main', 'calibre-customize = calibre.customize.ui:main', 'calibre-complete = calibre.utils.complete:main', diff --git a/src/calibre/utils/fontconfig.py b/src/calibre/utils/fontconfig.py deleted file mode 100644 index 2a5207c67c..0000000000 --- a/src/calibre/utils/fontconfig.py +++ /dev/null @@ -1,400 +0,0 @@ -#!/usr/bin/env python -__license__ = 'GPL v3' -__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' -__docformat__ = 'restructuredtext en' - -''' -:mod:`fontconfig` -- Query system fonts -============================================= -.. module:: fontconfig - :platform: Unix, Windows, OS X - :synopsis: Query system fonts -.. moduleauthor:: Kovid Goyal - -A ctypes based wrapper around the `fontconfig `_ library. -It can be used to find all fonts available on the system as well as the closest -match to a given font specification. The main functions in this module are: - -.. autofunction:: find_font_families - -.. autofunction:: files_for_family - -.. autofunction:: match -''' - -import sys, os, locale, codecs, subprocess, re -from ctypes import cdll, c_void_p, Structure, c_int, POINTER, c_ubyte, c_char, util, \ - pointer, byref, create_string_buffer, Union, c_char_p, c_double - -try: - preferred_encoding = locale.getpreferredencoding() - codecs.lookup(preferred_encoding) -except: - preferred_encoding = 'utf-8' - -iswindows = 'win32' in sys.platform or 'win64' in sys.platform -isosx = 'darwin' in sys.platform -isbsd = 'bsd' in sys.platform -DISABLED = False -#if isosx: -# libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c')) -# size = ctypes.c_uint(0) -# ok = libc.sysctlbyname("hw.cpu64bit_capable", None, byref(size), None, 0) -# if ok != 0: -# is64bit = False -# else: -# buf = ctypes.c_char_p("\0" * size.value) -# ok = libc.sysctlbyname("hw.cpu64bit_capable", buf, byref(size), None, 0) -# if ok != 0: -# is64bit = False -# else: -# is64bit = '1' in buf.value -# DISABLED = is64bit - -def load_library(): - if isosx: - lib = os.path.join(getattr(sys, 'frameworks_dir'), 'libfontconfig.1.dylib') \ - if hasattr(sys, 'frameworks_dir') else util.find_library('fontconfig') - return cdll.LoadLibrary(lib) - elif iswindows: - return cdll.LoadLibrary('libfontconfig-1') - elif isbsd: - raw = subprocess.Popen('pkg-config --libs-only-L fontconfig'.split(), - stdout=subprocess.PIPE).stdout.read().strip() - match = re.search(r'-L([^\s,]+)', raw) - if not match: - return cdll.LoadLibrary('libfontconfig.so') - return cdll.LoadLibrary(match.group(1)+'/libfontconfig.so') - else: - try: - return cdll.LoadLibrary(util.find_library('fontconfig')) - except: - try: - return cdll.LoadLibrary('libfontconfig.so') - except: - return cdll.LoadLibrary('libfontconfig.so.1') - -class FcPattern(Structure): - _fields_ = [ - ('num', c_int), - ('size', c_int), - ('elts_offset', c_void_p), - ('ref', c_int) - ] -class FcFontSet(Structure): - _fields_ = [ - ('nfont', c_int), - ('sfont', c_int), - ('fonts', POINTER(POINTER(FcPattern))) - ] -( - FcTypeVoid, - FcTypeInteger, - FcTypeDouble, - FcTypeString, - FcTypeBool, - FcTypeMatrix, - FcTypeCharSet, - FcTypeFTFace, - FcTypeLangSet -) = map(c_int, range(9)) -(FcMatchPattern, FcMatchFont, FcMatchScan) = map(c_int, range(3)) -( -FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId, - FcResultOutOfMemory -) = map(c_int, range(5)) -FcFalse, FcTrue = c_int(0), c_int(1) - -class _FcValue(Union): - _fields_ = [ - ('s', c_char_p), - ('i', c_int), - ('b', c_int), - ('d', c_double), - ] - -class FcValue(Structure): - _fields_ = [ - ('type', c_int), - ('u', _FcValue) - ] - -class FcObjectSet(Structure): pass - -lib = load_library() -lib.FcPatternBuild.restype = POINTER(FcPattern) -lib.FcPatternCreate.restype = c_void_p -lib.FcObjectSetCreate.restype = POINTER(FcObjectSet) -lib.FcFontSetDestroy.argtypes = [POINTER(FcFontSet)] -lib.FcFontList.restype = POINTER(FcFontSet) -lib.FcNameUnparse.argtypes = [POINTER(FcPattern)] -lib.FcNameUnparse.restype = POINTER(c_ubyte) -lib.FcPatternGetString.argtypes = [POINTER(FcPattern), POINTER(c_char), c_int, c_void_p] -lib.FcPatternGetString.restype = c_int -lib.FcPatternAdd.argtypes = [c_void_p, POINTER(c_char), FcValue, c_int] -lib.FcPatternGetInteger.argtypes = [POINTER(FcPattern), POINTER(c_char), c_int, POINTER(c_int)] -lib.FcPatternGetInteger.restype = c_int -lib.FcNameParse.argtypes = [c_char_p] -lib.FcNameParse.restype = POINTER(FcPattern) -lib.FcDefaultSubstitute.argtypes = [POINTER(FcPattern)] -lib.FcConfigSubstitute.argtypes = [c_void_p, POINTER(FcPattern), c_int] -lib.FcFontSetCreate.restype = POINTER(FcFontSet) -lib.FcFontMatch.argtypes = [c_void_p, POINTER(FcPattern), POINTER(c_int)] -lib.FcFontMatch.restype = POINTER(FcPattern) -lib.FcFontSetAdd.argtypes = [POINTER(FcFontSet), POINTER(FcPattern)] -lib.FcFontSort.argtypes = [c_void_p, POINTER(FcPattern), c_int, c_void_p, POINTER(c_int)] -lib.FcFontSort.restype = POINTER(FcFontSet) -lib.FcFontRenderPrepare.argtypes = [c_void_p, POINTER(FcPattern), POINTER(FcPattern)] -lib.FcFontRenderPrepare.restype = POINTER(FcPattern) -lib.FcConfigCreate.restype = c_void_p -lib.FcConfigSetCurrent.argtypes = [c_void_p] -lib.FcConfigSetCurrent.restype = c_int -lib.FcConfigParseAndLoad.argtypes = [c_void_p, POINTER(c_char), c_int] -lib.FcConfigParseAndLoad.restype = c_int -lib.FcConfigBuildFonts.argtypes = [c_void_p] -lib.FcConfigBuildFonts.restype = c_int - -_init_error = None -_initialized = False -from threading import Thread - -class FontScanner(Thread): - def run(self): - # Initialize the fontconfig library. This has to be done manually - # for the OS X bundle as it may have its own private fontconfig. - if getattr(sys, 'frameworks_dir', False):# and not os.path.exists('/usr/X11/lib/libfontconfig.1.dylib'): - config_dir = os.path.join(os.path.dirname(getattr(sys, 'frameworks_dir')), 'Resources', 'fonts') - if isinstance(config_dir, unicode): - config_dir = config_dir.encode(sys.getfilesystemencoding()) - config = lib.FcConfigCreate() - if not lib.FcConfigParseAndLoad(config, os.path.join(config_dir, 'fonts.conf'), 1): - _init_error = 'Could not parse the fontconfig configuration' - return - if not lib.FcConfigBuildFonts(config): - _init_error = 'Could not build fonts' - return - if not lib.FcConfigSetCurrent(config): - _init_error = 'Could not set font config' - return - elif not lib.FcInit(): - _init_error = _('Could not initialize the fontconfig library') - return - global _initialized - _initialized = True - -if not DISABLED: - _scanner = FontScanner() - _scanner.start() - -def join(): - _scanner.join(120) - if _scanner.isAlive(): - raise RuntimeError('Scanning for system fonts seems to have hung. Try again in a little while.') - if _init_error is not None: - raise RuntimeError(_init_error) - -def find_font_families(allowed_extensions=['ttf', 'otf']): - ''' - Return an alphabetically sorted list of font families available on the system. - - `allowed_extensions`: A list of allowed extensions for font file types. Defaults to - `['ttf', 'otf']`. If it is empty, it is ignored. - ''' - if DISABLED: - return [] - join() - allowed_extensions = [i.lower() for i in allowed_extensions] - - empty_pattern = lib.FcPatternCreate() - oset = lib.FcObjectSetCreate() - if not lib.FcObjectSetAdd(oset, 'file'): - raise RuntimeError('Allocation failure') - if not lib.FcObjectSetAdd(oset, 'family'): - raise RuntimeError('Allocation failure') - fs = lib.FcFontList(0, empty_pattern, oset) - font_set = fs.contents - file = pointer(create_string_buffer(chr(0), 5000)) - family = pointer(create_string_buffer(chr(0), 200)) - font_families = [] - for i in range(font_set.nfont): - pat = font_set.fonts[i] - if lib.FcPatternGetString(pat, 'file', 0, byref(file)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - path = str(file.contents.value) - ext = os.path.splitext(path)[1] - if ext: - ext = ext[1:].lower() - if (not allowed_extensions) or (allowed_extensions and ext in allowed_extensions): - if lib.FcPatternGetString(pat, 'family', 0, byref(family)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - font_families.append(str(family.contents.value)) - - lib.FcObjectSetDestroy(oset) - lib.FcPatternDestroy(empty_pattern) - lib.FcFontSetDestroy(fs) - font_families = list(set(font_families)) - font_families.sort() - return font_families - -def files_for_family(family, normalize=True): - ''' - Find all the variants in the font family `family`. - Returns a dictionary of tuples. Each tuple is of the form (Full font name, path to font file). - The keys of the dictionary depend on `normalize`. If `normalize` is `False`, - they are a tuple (slant, weight) otherwise they are strings from the set - `('normal', 'bold', 'italic', 'bi', 'light', 'li')` - ''' - if DISABLED: - return {} - join() - if isinstance(family, unicode): - family = family.encode(preferred_encoding) - family_pattern = lib.FcPatternBuild(0, 'family', FcTypeString, family, None) - if not family_pattern: - raise RuntimeError('Allocation failure') - #lib.FcPatternPrint(family_pattern) - oset = lib.FcObjectSetCreate() - if not lib.FcObjectSetAdd(oset, 'file'): - raise RuntimeError('Allocation failure') - if not lib.FcObjectSetAdd(oset, 'weight'): - raise RuntimeError('Allocation failure') - if not lib.FcObjectSetAdd(oset, 'fullname'): - raise RuntimeError('Allocation failure') - if not lib.FcObjectSetAdd(oset, 'slant'): - raise RuntimeError('Allocation failure') - if not lib.FcObjectSetAdd(oset, 'style'): - raise RuntimeError('Allocation failure') - fonts = {} - fs = lib.FcFontList(0, family_pattern, oset) - font_set = fs.contents - file = pointer(create_string_buffer(5000)) - full_name = pointer(create_string_buffer(200)) - weight = c_int(0) - slant = c_int(0) - fname = '' - for i in range(font_set.nfont): - pat = font_set.fonts[i] - #lib.FcPatternPrint(pat) - pat = font_set.fonts[i] - if lib.FcPatternGetString(pat, 'file', 0, byref(file)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - if lib.FcPatternGetInteger(pat, 'weight', 0, byref(weight)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - if lib.FcPatternGetString(pat, 'fullname', 0, byref(full_name)) != FcResultMatch.value: - if lib.FcPatternGetString(pat, 'fullname', 0, byref(full_name)) == FcResultNoMatch.value: - if lib.FcPatternGetString(pat, 'style', 0, byref(full_name)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - fname = family + ' ' + full_name.contents.value - else: - raise RuntimeError('Error processing pattern') - else: - fname = full_name.contents.value - if lib.FcPatternGetInteger(pat, 'slant', 0, byref(slant)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - style = (slant.value, weight.value) - if normalize: - italic = slant.value > 0 - normal = weight.value == 80 - bold = weight.value > 80 - if italic: - style = 'italic' if normal else 'bi' if bold else 'li' - else: - style = 'normal' if normal else 'bold' if bold else 'light' - fonts[style] = (file.contents.value, fname) - lib.FcObjectSetDestroy(oset) - lib.FcPatternDestroy(family_pattern) - if not iswindows: - lib.FcFontSetDestroy(fs) - - return fonts - -def match(name, sort=False, verbose=False): - ''' - Find the system font that most closely matches `name`, where `name` is a specification - of the form:: - familyname-::... - - For example, `verdana:weight=bold:slant=italic` - - Returns a list of dictionaries. Each dictionary has the keys: 'weight', 'slant', 'family', 'file' - - `sort`: If `True` return a sorted list of matching fonts, where the sort id in order of - decreasing closeness of matching. - `verbose`: If `True` print debugging information to stdout - ''' - if DISABLED: - return [] - join() - if isinstance(name, unicode): - name = name.encode(preferred_encoding) - pat = lib.FcNameParse(name) - if not pat: - raise ValueError('Could not parse font name') - if verbose: - print 'Searching for pattern' - lib.FcPatternPrint(pat) - if not lib.FcConfigSubstitute(0, pat, FcMatchPattern): - raise RuntimeError('Allocation failure') - lib.FcDefaultSubstitute(pat) - fs = lib.FcFontSetCreate() - result = c_int(0) - matches = [] - if sort: - font_patterns = lib.FcFontSort(0, pat, FcFalse, 0, byref(result)) - if not font_patterns: - raise RuntimeError('Allocation failed') - fps = font_patterns.contents - for j in range(fps.nfont): - fpat = fps.fonts[j] - fp = lib.FcFontRenderPrepare(0, pat, fpat) - if fp: - lib.FcFontSetAdd(fs, fp) - lib.FcFontSetDestroy(font_patterns) - else: - match_pat = lib.FcFontMatch(0, pat, byref(result)) - if pat: - lib.FcFontSetAdd(fs, match_pat) - if result.value != FcResultMatch.value: - lib.FcPatternDestroy(pat) - return matches - font_set = fs.contents - - file = pointer(create_string_buffer(chr(0), 5000)) - family = pointer(create_string_buffer(chr(0), 200)) - weight = c_int(0) - slant = c_int(0) - for j in range(font_set.nfont): - fpat = font_set.fonts[j] - #lib.FcPatternPrint(fpat) - if lib.FcPatternGetString(fpat, 'file', 0, byref(file)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - if lib.FcPatternGetString(fpat, 'family', 0, byref(family)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - if lib.FcPatternGetInteger(fpat, 'weight', 0, byref(weight)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - if lib.FcPatternGetInteger(fpat, 'slant', 0, byref(slant)) != FcResultMatch.value: - raise RuntimeError('Error processing pattern') - - matches.append({ - 'file' : file.contents.value, - 'family' : family.contents.value, - 'weight' : weight.value, - 'slant' : slant.value, - } - ) - - lib.FcPatternDestroy(pat) - lib.FcFontSetDestroy(fs) - return matches - -def main(args=sys.argv): - print find_font_families() - if len(args) > 1: - print - print files_for_family(args[1]) - print - print match(args[1], verbose=True) - return 0 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/src/calibre/utils/fonts/__init__.py b/src/calibre/utils/fonts/__init__.py new file mode 100644 index 0000000000..f492132534 --- /dev/null +++ b/src/calibre/utils/fonts/__init__.py @@ -0,0 +1,150 @@ +#!/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 os, sys +from threading import Thread + +from calibre.constants import plugins + +_fc, _fc_err = plugins['fontconfig'] + +if _fc is None: + raise RuntimeError('Failed to load fontconfig with error:'+_fc_err) + +class FontConfig(Thread): + + def __init__(self): + Thread.__init__(self) + self.daemon = True + self.failed = False + + def run(self): + config = None + if getattr(sys, 'frameworks_dir', False): + config_dir = os.path.join(os.path.dirname( + getattr(sys, 'frameworks_dir')), 'Resources', '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: + import traceback + traceback.print_exc() + self.failed = True + + def wait(self): + self.join() + if self.failed: + raise RuntimeError('Failed to initialize fontconfig') + + def find_font_families(self, allowed_extensions=['ttf', 'otf']): + ''' + Return an alphabetically sorted list of font families available on the system. + + `allowed_extensions`: A list of allowed extensions for font file types. Defaults to + `['ttf', 'otf']`. If it is empty, it is ignored. + ''' + self.wait() + ans = _fc.find_font_families([bytes('.'+x) for x in allowed_extensions]) + ans = sorted(set(ans), cmp=lambda x,y:cmp(x.lower(), y.lower())) + ans2 = [] + for x in ans: + try: + ans2.append(x.decode('utf-8')) + except UnicodeDecodeError: + continue + return ans2 + + def files_for_family(self, family, normalize=True): + ''' + Find all the variants in the font family `family`. + Returns a dictionary of tuples. Each tuple is of the form (Full font name, path to font file). + The keys of the dictionary depend on `normalize`. If `normalize` is `False`, + they are a tuple (slant, weight) otherwise they are strings from the set + `('normal', 'bold', 'italic', 'bi', 'light', 'li')` + ''' + self.wait() + if isinstance(family, unicode): + family = family.encode('utf-8') + fonts = {} + ofamily = str(family).decode('utf-8') + for fullname, path, style, nfamily, weight, slant in \ + _fc.files_for_family(str(family)): + style = (slant, weight) + if normalize: + italic = slant > 0 + normal = weight == 80 + bold = weight > 80 + if italic: + style = 'italic' if normal else 'bi' if bold else 'li' + else: + style = 'normal' if normal else 'bold' if bold else 'light' + try: + fullname, path = fullname.decode('utf-8'), path.decode('utf-8') + nfamily = nfamily.decode('utf-8') + except UnicodeDecodeError: + continue + if style in fonts: + if nfamily.lower().strip() == ofamily.lower().strip() \ + and 'Condensed' not in fullname and 'ExtraLight' not in fullname: + fonts[style] = (path, fullname) + else: + fonts[style] = (path, fullname) + + return fonts + + def match(self, name, all=False, verbose=False): + ''' + Find the system font that most closely matches `name`, where `name` is a specification + of the form:: + familyname-::... + + For example, `verdana:weight=bold:slant=italic` + + Returns a list of dictionaries, or a single dictionary. + Each dictionary has the keys: + 'weight', 'slant', 'family', 'file', 'fullname', 'style' + + `all`: If `True` return a sorted list of matching fonts, where the sort + is in order of decreasing closeness of matching. If `False` only the + best match is returned. ''' + self.wait() + if isinstance(name, unicode): + name = name.encode('utf-8') + fonts = [] + for fullname, path, style, family, weight, slant in \ + _fc.match(str(name), bool(all), bool(verbose)): + try: + fullname = fullname.decode('utf-8') + path = path.decode('utf-8') + style = style.decode('utf-8') + family = family.decode('utf-8') + fonts.append({ + 'fullname' : fullname, + 'path' : path, + 'style' : style, + 'family' : family, + 'weight' : weight, + 'slant' : slant + }) + except UnicodeDecodeError: + continue + return fonts if all else fonts[0] + +fontconfig = FontConfig() +fontconfig.start() + +def test(): + from pprint import pprint; + pprint(fontconfig.find_font_families()); + pprint(fontconfig.files_for_family('liberation serif')); + pprint(fontconfig.match('liberation serif:slant=italic:weight=bold', verbose=True)) + +if __name__ == '__main__': + test() diff --git a/src/calibre/utils/fonts/fontconfig.c b/src/calibre/utils/fonts/fontconfig.c new file mode 100644 index 0000000000..54ff22d915 --- /dev/null +++ b/src/calibre/utils/fonts/fontconfig.c @@ -0,0 +1,331 @@ +/* +:mod:`fontconfig` -- Pythonic interface to fontconfig +===================================================== + +.. module:: fontconfig + :platform: All + :synopsis: Pythonic interface to the fontconfig library + +.. moduleauthor:: Kovid Goyal Copyright 2009 + +*/ + +#define PY_SSIZE_T_CLEAN +#include +#include +#include +#include + +static PyObject * +fontconfig_initialize(PyObject *self, PyObject *args) { + char *path; + FcBool ok; + FcConfig *config; + PyThreadState *_save; + + if (!PyArg_ParseTuple(args, "z", &path)) + return NULL; + if (path == NULL) { + _save = PyEval_SaveThread(); + ok = FcInit(); + PyEval_RestoreThread(_save); + } else { + config = FcConfigCreate(); + if (config == NULL) return PyErr_NoMemory(); + _save = PyEval_SaveThread(); + ok = FcConfigParseAndLoad(config, path, FcTrue); + if (ok) ok = FcConfigBuildFonts(config); + if (ok) ok = FcConfigSetCurrent(config); + PyEval_RestoreThread(_save); + if (!ok) return PyErr_NoMemory(); + ok = 1; + } + if (ok) Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + +static +fontconfig_cleanup_find(FcPattern *p, FcObjectSet *oset, FcFontSet *fs) { + if (p != NULL) FcPatternDestroy(p); + if (oset != NULL) FcObjectSetDestroy(oset); + if (fs != NULL) FcFontSetDestroy(fs); +} + + +static PyObject * +fontconfig_find_font_families(PyObject *self, PyObject *args) { + int i; + size_t flen; + char *ext; + Py_ssize_t l, j, extlen; + FcBool ok; + FcPattern *pat, *temp; + FcObjectSet *oset; + FcFontSet *fs; + FcValue v, w; + PyObject *ans, *exts, *t; + + ans = PyList_New(0); + fs = NULL; oset = NULL; pat = NULL; + + if (ans == NULL) return PyErr_NoMemory(); + + if (!PyArg_ParseTuple(args, "O", &exts)) + return NULL; + + if (!PySequence_Check(exts)) { + PyErr_SetString(PyExc_ValueError, "Must pass sequence of extensions"); + return NULL; + } + l = PySequence_Size(exts); + + + pat = FcPatternCreate(); + if (pat == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + + oset = FcObjectSetCreate(); + if (oset == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcObjectSetAdd(oset, FC_FILE)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcObjectSetAdd(oset, FC_FAMILY)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + + fs = FcFontList(FcConfigGetCurrent(), pat, oset); + if (fs == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + + for (i = 0; i < fs->nfont; i++) { + temp = fs->fonts[i]; + + if (temp == NULL) continue; + if (FcPatternGet(temp, FC_FILE, 0, &v) != FcResultMatch) continue; + + if (v.type == FcTypeString) { + flen = strlen((char *)v.u.s); + ok = FcFalse; + if (l == 0) ok = FcTrue; + for ( j = 0; j < l && !ok; j++) { + ext = PyBytes_AS_STRING(PySequence_ITEM(exts, j)); + extlen = PyBytes_GET_SIZE(PySequence_ITEM(exts, j)); + ok = flen > extlen && extlen > 0 && + PyOS_strnicmp(ext, v.u.s + (flen - extlen), extlen) == 0; + } + + if (ok) { + if (FcPatternGet(temp, FC_FAMILY, 0, &w) != FcResultMatch) continue; + if (w.type != FcTypeString) continue; + t = PyString_FromString(w.u.s); + if (t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (PyList_Append(ans, t) != 0) + { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + } + } + + } + fontconfig_cleanup_find(pat, oset, fs); + Py_INCREF(ans); + return ans; +} + +static PyObject * +fontconfig_files_for_family(PyObject *self, PyObject *args) { + char *family; int i; + FcPattern *pat, *tp; + FcObjectSet *oset; + FcFontSet *fs; + FcValue file, weight, fullname, style, slant, family2; + PyObject *ans, *temp, *t; + + if (!PyArg_ParseTuple(args, "s", &family)) + return NULL; + + ans = PyList_New(0); + if (ans == NULL) return PyErr_NoMemory(); + + fs = NULL; oset = NULL; pat = NULL; + + pat = FcPatternBuild(0, FC_FAMILY, FcTypeString, family, (char *) 0); + if (pat == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + + oset = FcObjectSetCreate(); + if (oset == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcObjectSetAdd(oset, FC_FILE)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcObjectSetAdd(oset, FC_STYLE)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcObjectSetAdd(oset, FC_SLANT)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcObjectSetAdd(oset, FC_WEIGHT)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcObjectSetAdd(oset, FC_FAMILY)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcObjectSetAdd(oset, "fullname")) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + + fs = FcFontList(FcConfigGetCurrent(), pat, oset); + if (fs == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + + for (i = 0; i < fs->nfont; i++) { + tp = fs->fonts[i]; + + if (tp == NULL) continue; + if (FcPatternGet(tp, FC_FILE, 0, &file) != FcResultMatch) continue; + if (FcPatternGet(tp, FC_STYLE, 0, &style) != FcResultMatch) continue; + if (FcPatternGet(tp, FC_WEIGHT, 0, &weight) != FcResultMatch) continue; + if (FcPatternGet(tp, FC_SLANT, 0, &slant) != FcResultMatch) continue; + if (FcPatternGet(tp, FC_FAMILY, 0, &family2) != FcResultMatch) continue; + if (FcPatternGet(tp, "fullname", 0, &fullname) != FcResultMatch) continue; + + temp = PyTuple_New(6); + if(temp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + t = PyBytes_FromString(fullname.u.s); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 0, t); + t = PyBytes_FromString(file.u.s); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 1, t); + t = PyBytes_FromString(style.u.s); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 2, t); + t = PyBytes_FromString(family2.u.s); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 3, t); + t = PyInt_FromLong((long)weight.u.i); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 4, t); + t = PyInt_FromLong((long)slant.u.i); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 5, t); + if (PyList_Append(ans, temp) != 0) + { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + } + fontconfig_cleanup_find(pat, oset, fs); + Py_INCREF(ans); + return ans; +} + +static PyObject * +fontconfig_match(PyObject *self, PyObject *args) { + char *namespec; int i; + FcPattern *pat, *tp; + FcObjectSet *oset; + FcFontSet *fs, *fs2; + FcValue file, weight, fullname, style, slant, family; + FcResult res; + PyObject *ans, *temp, *t, *all, *verbose; + + if (!PyArg_ParseTuple(args, "sOO", &namespec, &all, &verbose)) + return NULL; + + ans = PyList_New(0); + if (ans == NULL) return PyErr_NoMemory(); + + fs = NULL; oset = NULL; pat = NULL; fs2 = NULL; + + pat = FcNameParse(namespec); + if (pat == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (PyObject_IsTrue(verbose)) FcPatternPrint(pat); + + if (!FcConfigSubstitute(FcConfigGetCurrent(), pat, FcMatchPattern)) + { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + FcDefaultSubstitute(pat); + + fs = FcFontSetCreate(); + if (fs == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (PyObject_IsTrue(all)) { + fs2 = FcFontSort(FcConfigGetCurrent(), pat, FcTrue, NULL, &res); + if (fs2 == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + + for (i = 0; i < fs2->nfont; i++) { + tp = fs2->fonts[i]; + if (tp == NULL) continue; + tp = FcFontRenderPrepare(FcConfigGetCurrent(), pat, tp); + if (tp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcFontSetAdd(fs, tp)) + { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + } + if (fs2 != NULL) FcFontSetDestroy(fs2); + } else { + tp = FcFontMatch(FcConfigGetCurrent(), pat, &res); + if (tp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + if (!FcFontSetAdd(fs, tp)) + { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + } + + for (i = 0; i < fs->nfont; i++) { + tp = fs->fonts[i]; + if (tp == NULL) continue; + if (FcPatternGet(tp, FC_FILE, 0, &file) != FcResultMatch) continue; + if (FcPatternGet(tp, FC_STYLE, 0, &style) != FcResultMatch) continue; + if (FcPatternGet(tp, FC_WEIGHT, 0, &weight) != FcResultMatch) continue; + if (FcPatternGet(tp, FC_SLANT, 0, &slant) != FcResultMatch) continue; + if (FcPatternGet(tp, FC_FAMILY, 0, &family) != FcResultMatch) continue; + if (FcPatternGet(tp, "fullname", 0, &fullname) != FcResultMatch) continue; + + temp = PyTuple_New(6); + if(temp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + t = PyBytes_FromString(fullname.u.s); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 0, t); + t = PyBytes_FromString(file.u.s); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 1, t); + t = PyBytes_FromString(style.u.s); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 2, t); + t = PyBytes_FromString(family.u.s); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 3, t); + t = PyInt_FromLong((long)weight.u.i); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 4, t); + t = PyInt_FromLong((long)slant.u.i); + if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + PyTuple_SET_ITEM(temp, 5, t); + if (PyList_Append(ans, temp) != 0) + { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } + + } + fontconfig_cleanup_find(pat, oset, fs); + Py_INCREF(ans); + return ans; +} + + + +static +PyMethodDef fontconfig_methods[] = { + {"initialize", fontconfig_initialize, METH_VARARGS, + "initialize(path_to_config_file)\n\n" + "Initialize the library. If path to config file is specified it is used instead of the " + "default configuration. Returns True iff the initialization succeeded." + }, + + {"find_font_families", fontconfig_find_font_families, METH_VARARGS, + "find_font_families(allowed_extensions)\n\n" + "Find all font families on the system for fonts of the specified types. If no " + "types are specified all font families are returned." + }, + + {"files_for_family", fontconfig_files_for_family, METH_VARARGS, + "files_for_family(family, normalize)\n\n" + "Find all the variants in the font family `family`. " + "Returns a list of tuples. Each tuple is of the form " + "(fullname, path, style, family, weight, slant). " + }, + + {"match", fontconfig_match, METH_VARARGS, + "match(namespec,all,verbose)\n\n" + "Find all system fonts that match namespec, in decreasing order " + "of closeness. " + "Returns a list of tuples. Each tuple is of the form " + "(fullname, path, style, family, weight, slant). " + + }, + + {NULL, NULL, 0, NULL} +}; + + + +PyMODINIT_FUNC +initfontconfig(void) { + PyObject *m; + m = Py_InitModule3( + "fontconfig", fontconfig_methods, + "Find fonts." + ); + if (m == NULL) return; +} + From 3fecb610dc6b5318a72f409e474732a2ccf51086 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 1 Jun 2009 20:49:30 -0700 Subject: [PATCH 08/20] A more sensible error when markdown fails --- src/calibre/ebooks/txt/input.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/calibre/ebooks/txt/input.py b/src/calibre/ebooks/txt/input.py index 86d5e23d10..f6900a5a2a 100644 --- a/src/calibre/ebooks/txt/input.py +++ b/src/calibre/ebooks/txt/input.py @@ -10,7 +10,7 @@ from calibre.customize.conversion import InputFormatPlugin from calibre.ebooks.txt.processor import txt_to_markdown, opf_writer class TXTInput(InputFormatPlugin): - + name = 'TXT Input' author = 'John Schember' description = 'Convert TXT files to HTML' @@ -22,16 +22,20 @@ class TXTInput(InputFormatPlugin): if options.input_encoding: ienc = options.input_encoding txt = stream.read().decode(ienc) - - html = txt_to_markdown(txt) + + try: + html = txt_to_markdown(txt) + except RuntimeError: + raise ValueError('This txt file has malformed markup, it cannot be' + 'converted by calibre. See http://daringfireball.net/projects/markdown/syntax') with open('index.html', 'wb') as index: index.write(html.encode('utf-8')) - + from calibre.ebooks.metadata.meta import get_metadata mi = get_metadata(stream, 'txt') manifest = [('index.html', None)] spine = ['index.html'] opf_writer(os.getcwd(), 'metadata.opf', manifest, spine, mi) - + return os.path.join(os.getcwd(), 'metadata.opf') From d67f0a0fd264d819cfb213b9b97eb0a3347c1415 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 1 Jun 2009 21:11:11 -0700 Subject: [PATCH 09/20] MOBI Indexing: Write secondary index records --- src/calibre/ebooks/mobi/writer.py | 61 +++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index e65a090b22..9196eb81ce 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -67,7 +67,9 @@ TAGX = { 'subchapter' : '\x00\x00\x00\x01\x01\x01\x01\x00\x02\x01\x02\x00\x03\x01\x04\x00\x04\x01\x08\x00\x05\x01\x10\x00\x15\x01\x10\x00\x16\x01\x20\x00\x17\x01\x40\x00\x00\x00\x00\x01', 'periodical' : - '\x00\x00\x00\x02\x01\x01\x01\x00\x02\x01\x02\x00\x03\x01\x04\x00\x04\x01\x08\x00\x05\x01\x10\x00\x15\x01\x20\x00\x16\x01\x40\x00\x17\x01\x80\x00\x00\x00\x00\x01\x45\x01\x01\x00\x46\x01\x02\x00\x47\x01\x04\x00\x00\x00\x00\x01' + '\x00\x00\x00\x02\x01\x01\x01\x00\x02\x01\x02\x00\x03\x01\x04\x00\x04\x01\x08\x00\x05\x01\x10\x00\x15\x01\x20\x00\x16\x01\x40\x00\x17\x01\x80\x00\x00\x00\x00\x01\x45\x01\x01\x00\x46\x01\x02\x00\x47\x01\x04\x00\x00\x00\x00\x01', + 'secondary_book':'\x00\x00\x00\x01\x01\x01\x01\x00\x00\x00\x00\x01', + 'secondary_periodical':'\x00\x00\x00\x01\x01\x01\x01\x00\x0b\x03\x02\x00\x00\x00\x00\x01' } INDXT = { @@ -608,16 +610,61 @@ class MobiWriter(object): indx0 = indx0.getvalue() self._primary_index_record = len(self._records) + self._records.extend([indx0, indx1, ctoc]) + + # Write secondary index records + tagx = TAGX['secondary_'+\ + ('periodical' if self.opts.mobi_periodical else 'book')] + tagx_len = 8 + len(tagx) + + indx0 = StringIO() + indx0.write('INDX'+pack('>I', 0xc0)+'\0'*8) + indx0.write(pack('>I', 0x02)) + indx0.write(pack('>I', 0xc0+tagx_len+4)) + indx0.write(pack('>I', 1)) + indx0.write(pack('>I', 65001)) + indx0.write('\xff'*4) + indx0.write(pack('>I', 1)) + indx0.write('\0'*4) + indx0.write('\0'*136) + indx0.write(pack('>I', 0xc0)) + indx0.write('\0'*8) + indx0.write('TAGX'+pack('>I', tagx_len)+tagx) + if self.opts.mobi_periodical: + raise NotImplementedError + else: + indx0.write('\0'*3 + '\x01' + 'IDXT' + '\0\xd4\0\0') + indx1 = StringIO() + indx1.write('INDX' + pack('>I', 0xc0) + '\0'*4) + indx1.write(pack('>I', 1)) + extra = 0xf0 if self.opts.mobi_periodical else 4 + indx1.write('\0'*4 + pack('>I', 0xc0+extra)) + num = 4 if self.opts.mobi_periodical else 1 + indx1.write(pack('>I', num)) + indx1.write('\xff'*8) + indx1.write('\0'*(0xc0-indx1.tell())) + if self.opts.mobi_periodical: + raise NotImplementedError + else: + indx1.write('\0\x01\x80\0') + indx1.write('IDXT') + if self.opts.mobi_periodical: + raise NotImplementedError + else: + indx1.write('\0\xc0\0\0') + + indx0, indx1 = indx0.getvalue(), indx1.getvalue() + self._records.extend((indx0, indx1)) if self.opts.verbose > 3: from tempfile import mkdtemp import os t = mkdtemp() - open(os.path.join(t, 'indx0.bin'), 'wb').write(indx0) - open(os.path.join(t, 'indx1.bin'), 'wb').write(indx1) - open(os.path.join(t, 'ctoc.bin'), 'wb').write(ctoc) + for i, n in enumerate(['sindx1', 'sindx0', 'ctoc', 'indx0', 'indx1']): + open(os.path.join(t, n+'.bin'), 'wb').write(self._records[-(i+1)]) self._oeb.log.debug('Index records dumped to', t) - self._records.extend([indx0, indx1, ctoc]) + + def _generate_ctoc(self): if self.opts.mobi_periodical: @@ -711,8 +758,8 @@ class MobiWriter(object): record0.write('\xff' * 8) # 0x20 - 0x23 : Secondary index record - # TODO: implement - record0.write('\xff' * 4) + record0.write(pack('>I', 0xffffffff if self._primary_index_record is + None else self._primary_index_record+3)) # 0x24 - 0x3f : Unknown record0.write('\xff' * 28) From 8adf54c7b4b038740c4efef069d1091d6ddd5229 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 1 Jun 2009 21:11:48 -0700 Subject: [PATCH 10/20] Misc. fixes --- installer/windows/calibre/calibre.mpi | 2 -- src/calibre/utils/fonts/__init__.py | 2 +- src/calibre/utils/ipc/launch.py | 6 +++++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/installer/windows/calibre/calibre.mpi b/installer/windows/calibre/calibre.mpi index ad7a8f5ded..aed72bc2bd 100644 --- a/installer/windows/calibre/calibre.mpi +++ b/installer/windows/calibre/calibre.mpi @@ -392,7 +392,6 @@ File ::6ED1C675-C4D5-6BFF-7C8A-9AB4BF39D00C -name _hashlib.pyd -parent 8E5D85A4- File ::21F7F333-3063-71E3-85F5-5C88584B15CC -name IM_MOD_RL_tga_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::26741B21-C241-E100-8BB1-8B679BC3E662 -name configure.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::7D491E89-C6D3-1E6E-F4BD-8E55260FE33E -name libexpat.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::A4910EB3-0F1C-F6F0-CD2D-16A64BBAA92B -name calibre-fontconfig.exe.local -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::476CB977-5155-D56F-26CA-EB243AEBBA99 -name unrar.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::2E2A9EDA-5386-444E-8479-557386794552 -name IM_MOD_RL_uil_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D3301E15-1B1A-E2AB-1B04-30A601B3FB44 -name IM_MOD_RL_cut_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 @@ -458,7 +457,6 @@ File ::3F6735E8-D4E6-A6F9-C9F8-4219E6BBC827 -name CORE_RL_jpeg_.dll -parent 8E5D File ::918BE500-1E97-90C0-3FB3-4056FE8D0E15 -name IM_MOD_RL_wbmp_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::D59F7D54-24A7-774D-79EB-423A64E8CB21 -name IM_MOD_RL_stegano_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::17F9A868-E52D-F961-9DB7-8AC69BA702EA -name CORE_RL_jp2_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 -File ::81715796-F363-675F-998E-EEEF890009A2 -name calibre-fontconfig.exe -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::878003DC-9B1D-7C58-29F8-14D4565ABA64 -name IM_MOD_RL_yuv_.dll -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::602B3244-CF6C-F934-E86C-8161800DB150 -name coder.xml -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 File ::C23261F0-19EA-2216-A8D6-45FCC4ECBECE -name win32file.pyd -parent 8E5D85A4-7608-47A1-CF7C-309060D5FF40 diff --git a/src/calibre/utils/fonts/__init__.py b/src/calibre/utils/fonts/__init__.py index f492132534..bc6b117147 100644 --- a/src/calibre/utils/fonts/__init__.py +++ b/src/calibre/utils/fonts/__init__.py @@ -135,7 +135,7 @@ class FontConfig(Thread): }) except UnicodeDecodeError: continue - return fonts if all else fonts[0] + return fonts if all else (fonts[0] if fonts else None) fontconfig = FontConfig() fontconfig.start() diff --git a/src/calibre/utils/ipc/launch.py b/src/calibre/utils/ipc/launch.py index 14530d7fea..2a578ed7d9 100644 --- a/src/calibre/utils/ipc/launch.py +++ b/src/calibre/utils/ipc/launch.py @@ -101,6 +101,10 @@ class Worker(object): contents = os.path.join(self.osx_contents_dir, 'console.app', 'Contents') resources = os.path.join(contents, 'Resources') fd = os.path.join(contents, 'Frameworks') + sp = os.path.join(resources, 'lib', 'python'+sys.version[:3], 'site-packages.zip') + self.osx_prefix = 'import sys; sys.frameworks_dir = "%s"; sys.frozen = "macosx_app"; '%fd + self.osx_prefix += 'sys.path.insert(0, %s); '%repr(sp) + self._env['PYTHONHOME'] = resources self._env['MAGICK_HOME'] = os.path.join(fd, 'ImageMagick') self._env['DYLD_LIBRARY_PATH'] = os.path.join(fd, 'ImageMagick', 'lib') @@ -124,7 +128,7 @@ class Worker(object): priority = prefs['worker_process_priority'] cmd = [exe] if isosx: - cmd += ['-c', 'from calibre.utils.worker import main; main()'] + cmd += ['-c', self.osx_prefix + 'from calibre.utils.ipc.worker import main; main()'] args = { 'env' : env, 'cwd' : _cwd, From f05215d88a8a7b849e4861cb9d26d44ce28edcf0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 1 Jun 2009 21:42:03 -0700 Subject: [PATCH 11/20] Add conversion profile for Kindle DX --- src/calibre/customize/profiles.py | 17 ++++++++++++++++- src/calibre/gui2/wizard/__init__.py | 9 ++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/calibre/customize/profiles.py b/src/calibre/customize/profiles.py index 4c184ca36d..3844ab43a5 100644 --- a/src/calibre/customize/profiles.py +++ b/src/calibre/customize/profiles.py @@ -235,7 +235,22 @@ class KindleOutput(OutputProfile): def tags_to_string(cls, tags): return 'ttt '.join(tags)+'ttt ' +class KindleDXOutput(OutputProfile): + + name = 'Kindle DX' + short_name = 'kindle_dx' + description = _('This profile is intended for the Amazon Kindle DX.') + + # Screen size is a best guess + screen_size = (1200, 824) + dpi = 150.0 + comic_screen_size = (1180, 800) + + @classmethod + def tags_to_string(cls, tags): + return 'ttt '.join(tags)+'ttt ' + output_profiles = [OutputProfile, SonyReaderOutput, MSReaderOutput, MobipocketOutput, HanlinV3Output, CybookG3Output, KindleOutput, - SonyReaderLandscapeOutput] + SonyReaderLandscapeOutput, KindleDXOutput] diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index 467aecd93f..4ba4abc263 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -63,6 +63,13 @@ class Kindle(Device): manufacturer = 'Amazon' id = 'kindle' +class KindleDX(Kindle): + + output_profile = 'kindle_dx' + output_format = 'MOBI' + name = 'Kindle DX' + id = 'kindledx' + class Sony500(Device): output_profile = 'sony' @@ -307,7 +314,7 @@ class DevicePage(QWizardPage, DeviceUI): def nextId(self): idx = list(self.device_view.selectionModel().selectedIndexes())[0] dev = self.dev_model.data(idx, Qt.UserRole) - if dev is Kindle: + if dev in (Kindle, KindleDX): return KindlePage.ID if dev is iPhone: return StanzaPage.ID From 972c7706671a809598951fbed6e27a6e34d7909a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 08:54:17 -0700 Subject: [PATCH 12/20] Fix #2152 (Typo in GUI) --- src/calibre/devices/usbms/driver.py | 8 +- src/calibre/ebooks/metadata/cli.py | 34 +-- src/calibre/translations/calibre.pot | 402 ++++++++++++++------------- 3 files changed, 234 insertions(+), 210 deletions(-) diff --git a/src/calibre/devices/usbms/driver.py b/src/calibre/devices/usbms/driver.py index f871bc20e7..2276efc91b 100644 --- a/src/calibre/devices/usbms/driver.py +++ b/src/calibre/devices/usbms/driver.py @@ -74,9 +74,9 @@ class USBMS(CLI, Device): self.report_progress((i+1) / float(len(paths)), _('Getting list of books on device...')) if path_to_ext(filename) in self.FORMATS: bl.append(self.__class__.book_from_path(os.path.join(path, filename))) - + self.report_progress(1.0, _('Getting list of books on device...')) - + return bl def _sanity_check(self, on_card, files): @@ -85,7 +85,7 @@ class USBMS(CLI, Device): elif on_card == 'cardb' and not self._card_b_prefix: raise ValueError(_('The reader has no storage card in this slot.')) elif on_card and on_card not in ('carda', 'cardb'): - raise DeviceError(_('Selected slot: %s is not supported.' % on_card)) + raise DeviceError(_('Selected slot: %s is not supported.') % on_card) if on_card == 'carda': path = os.path.join(self._card_a_prefix, self.EBOOK_DIR_CARD_A) @@ -165,7 +165,7 @@ class USBMS(CLI, Device): self.report_progress((i+1) / float(len(files)), _('Transferring books to device...')) self.report_progress(1.0, _('Transferring books to device...')) - + return zip(paths, cycle([on_card])) def add_books_to_metadata(self, locations, metadata, booklists): diff --git a/src/calibre/ebooks/metadata/cli.py b/src/calibre/ebooks/metadata/cli.py index 8053b82e90..958e317158 100644 --- a/src/calibre/ebooks/metadata/cli.py +++ b/src/calibre/ebooks/metadata/cli.py @@ -39,11 +39,11 @@ def config(): 'Firstname Lastname.')) c.add_opt('title_sort', ['--title-sort'], help=_('The version of the title to be used for sorting. ' - 'If unspecified, and the title is specified, it will ' + 'If unspecified, and the title is specified, it will ' 'be auto-generated from the title.')) c.add_opt('author_sort', ['--author-sort'], help=_('String to be used when sorting by author. ' - 'If unspecified, and the author(s) are specified, it will ' + 'If unspecified, and the author(s) are specified, it will ' 'be auto-generated from the author(s).')) c.add_opt('cover', ['--cover'], help=_('Set the cover to the specified file.')) @@ -67,7 +67,7 @@ def config(): help=_('Set the book producer.')) c.add_opt('language', ['-l', '--language'], help=_('Set the language.')) - + c.add_opt('get_cover', ['--get-cover'], help=_('Get the cover from the ebook and save it at as the ' 'specified file.')) @@ -76,9 +76,9 @@ def config(): 'be written to the OPF file.')) c.add_opt('from_opf', ['--from-opf'], help=_('Read metadata from the specified OPF file and use it to ' - 'set metadata in the ebook. Metadata specified on the' + 'set metadata in the ebook. Metadata specified on the ' 'command line will override metadata read from the OPF file')) - + c.add_opt('lrf_bookid', ['--lrf-bookid'], help=_('Set the BookID in LRF files')) return c @@ -99,16 +99,16 @@ def do_set_metadata(opts, mi, stream, stream_type): mi = MetaInformation(mi) for x in ('guide', 'toc', 'manifest', 'spine'): setattr(mi, x, None) - + from_opf = getattr(opts, 'from_opf', None) if from_opf is not None: from calibre.ebooks.metadata.opf2 import OPF opf_mi = MetaInformation(OPF(open(from_opf, 'rb'))) mi.smart_update(opf_mi) - + for pref in config().option_set.preferences: - if pref.name in ('to_opf', 'from_opf', 'authors', 'title_sort', - 'author_sort', 'get_cover', 'cover', 'tags', + if pref.name in ('to_opf', 'from_opf', 'authors', 'title_sort', + 'author_sort', 'get_cover', 'cover', 'tags', 'lrf_bookid'): continue val = getattr(opts, pref.name, None) @@ -125,13 +125,13 @@ def do_set_metadata(opts, mi, stream, stream_type): mi.title_sort = title_sort(opts.title) if getattr(opts, 'tags', None) is not None: mi.tags = [t.strip() for t in opts.tags.split(',')] - + if getattr(opts, 'cover', None) is not None: ext = os.path.splitext(opts.cover)[1].replace('.', '').upper() mi.cover_data = (ext, open(opts.cover, 'rb').read()) - + set_metadata(stream, mi, stream_type) - + def main(args=sys.argv): parser = option_parser() @@ -143,7 +143,7 @@ def main(args=sys.argv): path = args[1] stream = open(path, 'r+b') stream_type = os.path.splitext(path)[1].replace('.', '').lower() - + trying_to_set = False for pref in config().option_set.preferences: if pref.name in ('to_opf', 'get_cover'): @@ -158,7 +158,7 @@ def main(args=sys.argv): if trying_to_set: metadata = '\t'+'\n\t'.join(metadata.split('\n')) prints(metadata) - + if trying_to_set: stream.seek(0) do_set_metadata(opts, mi, stream, stream_type) @@ -176,14 +176,14 @@ def main(args=sys.argv): prints(metadata) if lrf is not None: prints('\tBookID:', lrf.book_id) - + if opts.to_opf is not None: from calibre.ebooks.metadata.opf2 import OPFCreator opf = OPFCreator(os.getcwdu(), mi) with open(opts.opf, 'wb') as f: opf.render(f) prints(_('OPF created in'), opts.opf) - + if opts.get_cover is not None: if mi.cover_data and mi.cover_data[1]: with open(opts.get_cover, 'wb') as f: @@ -191,7 +191,7 @@ def main(args=sys.argv): prints(_('Cover saved to'), f.name) else: prints(_('No cover found'), file=sys.stderr) - + return 0 if __name__ == '__main__': diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 26ebc84299..8670d515a5 100644 --- a/src/calibre/translations/calibre.pot +++ b/src/calibre/translations/calibre.pot @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: calibre 0.5.14\n" -"POT-Creation-Date: 2009-05-31 09:36+PDT\n" -"PO-Revision-Date: 2009-05-31 09:36+PDT\n" +"Project-Id-Version: calibre 0.6.0b1\n" +"POT-Creation-Date: 2009-06-02 08:53+PDT\n" +"PO-Revision-Date: 2009-06-02 08:53+PDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -48,7 +48,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/mobi.py:153 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf.py:333 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf.py:448 -#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:866 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:865 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pdb.py:39 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pdf.py:58 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/topaz.py:29 @@ -57,8 +57,8 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:69 #: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:78 #: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:149 -#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:520 -#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:704 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:531 +#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:715 #: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:44 #: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:46 #: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:791 @@ -66,8 +66,8 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/oeb/reader.py:162 #: /home/kovid/work/calibre/src/calibre/ebooks/oeb/reader.py:165 #: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/jacket.py:82 -#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:96 -#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:97 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:101 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ereader/writer.py:102 #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/input.py:26 #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/palmdoc/writer.py:28 #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/ztxt/writer.py:26 @@ -261,31 +261,35 @@ msgstr "" msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc, in landscape mode. Mainly useful for comics." msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:30 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:242 +msgid "This profile is intended for the Amazon Kindle DX." +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:29 msgid "Installed plugins" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:31 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:30 msgid "Mapping for filetype plugins" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:32 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:31 msgid "Local plugin customization" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:33 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:32 msgid "Disabled plugins" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:75 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:74 msgid "No valid plugin found in " msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:215 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:214 msgid "Initialization of plugin %s failed with traceback:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:333 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:332 msgid "" " %prog options\n" "\n" @@ -293,27 +297,27 @@ msgid "" " " msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:339 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:338 msgid "Add a plugin by specifying the path to the zip file containing it." msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:341 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:340 msgid "Remove a custom plugin by name. Has no effect on builtin plugins" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:343 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:342 msgid "Customize plugin. Specify name of plugin and customization string separated by a comma." msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:345 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:344 msgid "List all installed plugins" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:347 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:346 msgid "Enable the named plugin" msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/ui.py:349 +#: /home/kovid/work/calibre/src/calibre/customize/ui.py:348 msgid "Disable the named plugin" msgstr "" @@ -446,7 +450,6 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:110 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:84 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:86 -#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:88 msgid "The reader has no storage card in this slot." msgstr "" @@ -489,6 +492,10 @@ msgstr "" msgid "Communicate with an eBook reader." msgstr "" +#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:88 +msgid "Selected slot: %s is not supported." +msgstr "" + #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:173 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:181 msgid "Adding books to device metadata listing..." @@ -563,7 +570,7 @@ msgstr "" msgid "Page" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:10 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:19 msgid "" "input_file output_file [options]\n" "\n" @@ -578,43 +585,43 @@ msgid "" "For full documentation of the conversion system see\n" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:86 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:87 msgid "INPUT OPTIONS" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:87 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:88 msgid "Options to control the processing of the input %s file" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:93 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:94 msgid "OUTPUT OPTIONS" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:94 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:95 msgid "Options to control the processing of the output %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:108 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:109 msgid "Options to control the look and feel of the output" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:122 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:123 msgid "Control auto-detection of document structure." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:132 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:133 msgid "Control the automatic generation of a Table of Contents. By default, if the source file has a Table of Contents, it will be used in preference to the automatically generated one." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:142 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:143 msgid "Options to set metadata in the output" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:145 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:146 msgid "Options to help with debugging the conversion" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:219 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:220 msgid "Output saved to" msgstr "" @@ -1225,7 +1232,7 @@ msgid "Specify the name of an OPF file. The metadata will be written to the OPF msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:78 -msgid "Read metadata from the specified OPF file and use it to set metadata in the ebook. Metadata specified on thecommand line will override metadata read from the OPF file" +msgid "Read metadata from the specified OPF file and use it to set metadata in the ebook. Metadata specified on the command line will override metadata read from the OPF file" msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:83 @@ -1805,6 +1812,20 @@ msgstr "" msgid "Comic Input" msgstr "" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16 +msgid "input" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:19 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:17 +msgid "Options specific to" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:76 #: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:38 #: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:85 @@ -1818,7 +1839,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:61 #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:31 #: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_edit_ui.py:41 -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:65 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:67 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:53 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:35 #: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:96 @@ -1884,6 +1905,15 @@ msgstr "" msgid "EPUB Output" msgstr "" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:19 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:17 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:17 +msgid "output" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:39 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/epub_ui.py:513 msgid "Do not &split on page breaks" @@ -2295,8 +2325,6 @@ msgid "Convert" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/single.py:162 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config.py:62 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config.py:74 msgid "Options specific to the input format." msgstr "" @@ -2455,71 +2483,71 @@ msgstr "" msgid "Use a wizard to help construct the XPath expression" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:66 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:68 msgid "Match HTML &tags with tag name:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:67 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:69 msgid "*" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:68 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:70 msgid "a" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:69 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:71 msgid "br" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:70 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:72 msgid "div" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:71 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:73 msgid "h1" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:72 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:74 msgid "h2" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:73 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:75 msgid "h3" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:74 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:76 msgid "h4" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:75 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:77 msgid "h5" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:76 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:78 msgid "h6" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:77 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:79 msgid "hr" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:78 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:80 msgid "span" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:79 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:81 msgid "Having the &attribute:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:80 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:82 msgid "With &value:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:81 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:83 msgid "(A regular expression)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:82 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:84 msgid "

For example, to match all h2 tags that have class=\"chapter\", set tag to h2, attribute to class and value to chapter.

Leaving attribute blank will match any attribute and leaving value blank will match any value. Setting tag to * will match any tag.

To learn more advanced usage of XPath see the XPath Tutorial." msgstr "" @@ -2882,12 +2910,12 @@ msgid "Access log:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config.py:607 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:513 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:514 msgid "Failed to start content server" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config.py:631 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:423 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:431 msgid "Select location for books" msgstr "" @@ -4379,137 +4407,137 @@ msgstr "" msgid "Save single format to disk..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:134 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:911 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:912 #: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:49 msgid "Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:135 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:136 msgid "Error communicating with device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:149 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:150 msgid "&Restore" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:151 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:152 msgid "&Donate to support calibre" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:156 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:157 msgid "&Restart" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:182 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:183 msgid "

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

" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:205 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:206 msgid "Edit metadata individually" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:207 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:208 msgid "Edit metadata in bulk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:209 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:210 msgid "Download metadata and covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:210 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:211 msgid "Download only metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:211 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:212 msgid "Download only covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:214 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:215 msgid "Add books from a single directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:215 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:216 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:218 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:219 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:254 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:255 #: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:357 msgid "Save to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:255 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:256 msgid "Save to disk in a single directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:256 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1388 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:257 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1389 msgid "Save only %s format to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:264 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:265 #: /home/kovid/work/calibre/src/calibre/gui2/main_ui.py:363 msgid "View" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:265 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:266 msgid "View specific format" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:291 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:292 msgid "Convert individually" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:292 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:293 msgid "Bulk convert" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:303 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:304 msgid "Run welcome wizard" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:335 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:336 msgid "Similar books..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:392 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:393 msgid "Bad database location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:395 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1516 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:396 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1517 msgid "Choose a location for your ebook library." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:556 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:557 msgid "Browse by covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:657 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:658 msgid "Device: " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:659 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:660 msgid " detected." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:681 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:682 msgid "Connected " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:693 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:694 msgid "Device database corrupted" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:694 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:695 msgid "" "\n" "

The database of books on the reader is corrupted. Try the following:\n" @@ -4520,286 +4548,286 @@ msgid "" " " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:761 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:804 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:762 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:805 msgid "Uploading books to device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:769 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:770 msgid "Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:770 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:771 msgid "EPUB Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:771 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:772 msgid "LRF Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:772 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:773 msgid "HTML Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:773 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:774 msgid "LIT Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:774 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:775 msgid "MOBI Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:775 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:776 msgid "Text books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:776 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:777 msgid "PDF Books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:777 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:778 msgid "Comics" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:778 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:779 msgid "Archives" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:825 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:826 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:842 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:843 msgid "Deleting books from device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:873 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:874 msgid "Cannot download metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:874 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:924 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:951 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:976 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1106 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:875 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:925 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:952 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:977 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1107 msgid "No books selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:883 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:884 msgid "covers" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:883 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:884 msgid "metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:885 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:886 msgid "Downloading %s for %d book(s)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:906 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:907 msgid "Failed to download some metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:907 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:908 msgid "Failed to download metadata for the following:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:910 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:911 msgid "Failed to download metadata:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:923 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:950 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:924 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:951 msgid "Cannot edit metadata" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:975 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:976 msgid "Cannot save to disk" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:978 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:979 msgid "Choose destination directory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1000 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1001 msgid "Error while saving" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1001 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1002 msgid "There was an error while saving." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1005 #: /home/kovid/work/calibre/src/calibre/gui2/main.py:1006 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1007 msgid "Could not save some books" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1007 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1008 msgid "as the %s format is not available for them." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1008 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1009 msgid "Click the show details button to see which ones." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1027 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1028 msgid "Fetching news from " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1040 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1041 msgid " fetched." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1105 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1106 msgid "Cannot convert" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1282 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1301 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1283 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1302 msgid "No book selected" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1282 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1331 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1283 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1332 msgid "Cannot view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1288 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1336 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1289 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1337 msgid "Choose the format to view" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1300 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1301 msgid "Cannot open folder" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1332 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1333 msgid "%s has no available formats." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1373 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1374 msgid "Cannot configure" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1374 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1375 msgid "Cannot configure while there are running jobs." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1417 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1418 msgid "No detailed info available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1418 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1419 msgid "No detailed information is available for books on the device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1466 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1467 msgid "Error talking to device" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1467 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1468 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:1484 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1499 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1485 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1500 msgid "Conversion Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1485 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1486 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:1500 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1501 msgid "Failed" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1525 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1526 msgid "Invalid library location" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1526 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1527 msgid "Could not access %s. Using %s as the library." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1574 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1575 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:1598 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1599 msgid "There are active jobs. Are you sure you want to quit?" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1601 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1602 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:1605 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1606 msgid "WARNING: Active jobs" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1654 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1655 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:1673 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1674 msgid "Latest version: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1681 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1682 msgid "Update available" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1682 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1683 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:1700 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1701 msgid "Use the library located at the specified path." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1702 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1703 msgid "Start minimized to system tray." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1704 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1705 msgid "Log debugging information to console" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1747 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1753 msgid "If you are sure it is not running" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1749 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1755 msgid "Cannot Start " msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1750 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1756 msgid "%s is already running." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1753 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1759 msgid "may be running in the system tray, in the" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1755 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1761 msgid "upper right region of the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1757 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1763 msgid "lower right region of the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1760 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1766 msgid "try rebooting your computer." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1762 -#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1782 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1768 +#: /home/kovid/work/calibre/src/calibre/gui2/main.py:1788 msgid "try deleting the file" msgstr "" @@ -5122,7 +5150,7 @@ msgid "Options to customize the ebook viewer" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/viewer/documentview.py:57 -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:629 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:630 msgid "Remember last used window size" msgstr "" @@ -5227,19 +5255,19 @@ msgstr "" msgid "DRM Error" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:546 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:547 msgid "Could not open ebook" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:619 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:620 msgid "Options to control the ebook viewer" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:626 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:627 msgid "If specified, viewer window will try to come to the front when started." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:635 +#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:636 msgid "" "%prog [options] file\n" "\n" @@ -5350,39 +5378,39 @@ msgstr "" msgid "Click to see the list of books on storage card B in your reader" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:35 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:36 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:119 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:120 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:127 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:128 msgid "Default" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:325 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:333 msgid "Moving library..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:341 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:342 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:349 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:350 msgid "Failed to move library" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:351 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:359 msgid "Copied" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:395 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:403 msgid "Invalid database" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:396 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:404 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:407 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:415 msgid "Could not move library" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:466 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:474 msgid "welcome wizard" msgstr "" @@ -5863,10 +5891,6 @@ msgstr "" msgid "The priority of worker processes" msgstr "" -#: /home/kovid/work/calibre/src/calibre/utils/fontconfig.py:180 -msgid "Could not initialize the fontconfig library" -msgstr "" - #: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:39 msgid "Waiting..." msgstr "" From d1b305cf6678ce0cfa2e00c7434c92605c1ea9e8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 09:10:54 -0700 Subject: [PATCH 13/20] MOBI Output: Add a pad record at the end of the text records --- src/calibre/ebooks/mobi/writer.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 9196eb81ce..82ed1da7c1 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -446,9 +446,12 @@ class MobiWriter(object): nrecords += 1 offset += RECORD_SIZE data, overlap = self._read_text_record(text) - extra = len(''.join(buf))%4 - if extra > 0 and INDEXING: - self._records[-1] += '\0'*(4-extra) + if INDEXING: + extra = sum(map(len, buf))%4 + if extra == 0: + extra = 4 + self._records.append('\0'*(4-extra)) + nrecords += 1 self._text_nrecords = nrecords def _generate_indxt(self, ctoc): From be9c87a062887d49beea57e2c2f85b0cb9bc4f83 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 09:11:27 -0700 Subject: [PATCH 14/20] Flush stdout/stderr after each stage of conversion pipeline --- src/calibre/ebooks/conversion/plumber.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index 9bab5d6701..4f5df32479 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -3,7 +3,7 @@ __license__ = 'GPL 3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import os, re +import os, re, sys from calibre.customize.conversion import OptionRecommendation, DummyReporter from calibre.customize.ui import input_profiles, output_profiles, \ @@ -551,6 +551,13 @@ OptionRecommendation(name='list_recipes', self.read_user_metadata() + def flush(self): + try: + sys.stdout.flush() + sys.stderr.flush() + except: + pass + def run(self): ''' Run the conversion pipeline @@ -566,11 +573,13 @@ OptionRecommendation(name='list_recipes', self.log('\t'+title) self.log('%d recipes available'%len(titles)) raise SystemExit(0) + self.flush() # Run any preprocess plugins from calibre.customize.ui import run_plugins_on_preprocess self.input = run_plugins_on_preprocess(self.input) + self.flush() # Create an OEBBook from the input file. The input plugin does all the # heavy lifting. accelerators = {} @@ -595,11 +604,13 @@ OptionRecommendation(name='list_recipes', self.oeb = create_oebbook(self.log, self.oeb, self.opts, self.input_plugin) pr = CompositeProgressReporter(0.34, 0.67, self.ui_reporter) + self.flush() pr(0., _('Running transforms on ebook...')) from calibre.ebooks.oeb.transforms.guide import Clean Clean()(self.oeb, self.opts) pr(0.1) + self.flush() self.opts.source = self.opts.input_profile self.opts.dest = self.opts.output_profile @@ -608,10 +619,12 @@ OptionRecommendation(name='list_recipes', MergeMetadata()(self.oeb, self.user_metadata, self.opts.prefer_metadata_cover) pr(0.2) + self.flush() from calibre.ebooks.oeb.transforms.structure import DetectStructure DetectStructure()(self.oeb, self.opts) pr(0.35) + self.flush() from calibre.ebooks.oeb.transforms.flatcss import CSSFlattener fbase = self.opts.base_font_size @@ -626,6 +639,7 @@ OptionRecommendation(name='list_recipes', from calibre.ebooks.oeb.transforms.jacket import Jacket Jacket()(self.oeb, self.opts, self.user_metadata) pr(0.4) + self.flush() if self.opts.extra_css and os.path.exists(self.opts.extra_css): self.opts.extra_css = open(self.opts.extra_css, 'rb').read() @@ -651,6 +665,7 @@ OptionRecommendation(name='list_recipes', from calibre.ebooks.oeb.transforms.linearize_tables import LinearizeTables LinearizeTables()(self.oeb, self.opts) pr(0.9) + self.flush() from calibre.ebooks.oeb.transforms.trimmanifest import ManifestTrimmer @@ -660,6 +675,7 @@ OptionRecommendation(name='list_recipes', self.oeb.toc.rationalize_play_orders() pr(1.) + self.flush() self.log.info('Creating %s...'%self.output_plugin.name) our = CompositeProgressReporter(0.67, 1., self.ui_reporter) @@ -669,6 +685,7 @@ OptionRecommendation(name='list_recipes', self.opts, self.log) self.ui_reporter(1.) self.log(self.output_fmt.upper(), 'output written to', self.output) + self.flush() def create_oebbook(log, path_or_stream, opts, input_plugin, reader=None, encoding='utf-8'): From e6728649be886a230ac0fe83c4884483fc8c9c5a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 10:20:02 -0700 Subject: [PATCH 15/20] Speed up adding/saving of small numbers of books by maintaining a spare job server --- src/calibre/ebooks/metadata/worker.py | 14 ++++++++------ src/calibre/gui2/add.py | 12 ++++++++---- src/calibre/gui2/main.py | 22 +++++++++++++++++++--- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/calibre/ebooks/metadata/worker.py b/src/calibre/ebooks/metadata/worker.py index 281039fb12..3c5ffd1be2 100644 --- a/src/calibre/ebooks/metadata/worker.py +++ b/src/calibre/ebooks/metadata/worker.py @@ -53,8 +53,9 @@ class Progress(object): class ReadMetadata(Thread): - def __init__(self, tasks, result_queue): + def __init__(self, tasks, result_queue, spare_server=None): self.tasks, self.result_queue = tasks, result_queue + self.spare_server = spare_server self.canceled = False Thread.__init__(self) self.daemon = True @@ -67,7 +68,7 @@ class ReadMetadata(Thread): for b in t: ids.add(b[0]) progress = Progress(self.result_queue, self.tdir) - server = Server() + server = Server() if self.spare_server is None else self.spare_server for i, task in enumerate(self.tasks): job = ParallelJob('read_metadata', 'Read metadata (%d of %d)'%(i, len(self.tasks)), @@ -110,20 +111,20 @@ class ReadMetadata(Thread): os.remove(job.log_path) -def read_metadata(paths, result_queue, chunk=50): +def read_metadata(paths, result_queue, chunk=50, spare_server=None): tasks = [] pos = 0 while pos < len(paths): tasks.append(paths[pos:pos+chunk]) pos += chunk - t = ReadMetadata(tasks, result_queue) + t = ReadMetadata(tasks, result_queue, spare_server=spare_server) t.start() return t class SaveWorker(Thread): def __init__(self, result_queue, db, ids, path, by_author=False, - single_dir=False, single_format=None): + single_dir=False, single_format=None, spare_server=None): Thread.__init__(self) self.daemon = True self.path, self.by_author = path, by_author @@ -133,10 +134,11 @@ class SaveWorker(Thread): self.canceled = False self.result_queue = result_queue self.error = None + self.spare_server = spare_server self.start() def run(self): - server = Server() + server = Server() if self.spare_server is None else self.spare_server ids = set(self.ids) tasks = server.split(list(ids)) jobs = set([]) diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py index f5c8be4338..ec253e5ae0 100644 --- a/src/calibre/gui2/add.py +++ b/src/calibre/gui2/add.py @@ -39,9 +39,10 @@ class RecursiveFind(QThread): class Adder(QObject): - def __init__(self, parent, db, callback): + def __init__(self, parent, db, callback, spare_server=None): QObject.__init__(self, parent) self.pd = ProgressDialog(_('Adding...'), parent=parent) + self.spare_server = spare_server self.db = db self.pd.setModal(True) self.pd.show() @@ -79,7 +80,8 @@ class Adder(QObject): tasks.append((i, b)) self.ids[i] = b self.nmap[i] = os.path.basename(b[0]) - self.worker = read_metadata(tasks, self.rq) + self.worker = read_metadata(tasks, self.rq, + spare_server=self.spare_server) self.pd.set_min(0) self.pd.set_max(len(self.ids)) self.pd.value = 0 @@ -165,9 +167,11 @@ class Adder(QObject): class Saver(QObject): def __init__(self, parent, db, callback, rows, path, - by_author=False, single_dir=False, single_format=None): + by_author=False, single_dir=False, single_format=None, + spare_server=None): QObject.__init__(self, parent) self.pd = ProgressDialog(_('Saving...'), parent=parent) + self.spare_server = spare_server self.db = db self.pd.setModal(True) self.pd.show() @@ -183,7 +187,7 @@ class Saver(QObject): from calibre.ebooks.metadata.worker import SaveWorker self.worker = SaveWorker(self.rq, db, self.ids, path, by_author, - single_dir, single_format) + single_dir, single_format, spare_server=self.spare_server) self.connect(self.pd, SIGNAL('canceled()'), self.canceled) self.timer = QTimer(self) self.connect(self.timer, SIGNAL('timeout()'), self.update) diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index ad472ed4db..b2648409f2 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -18,6 +18,7 @@ from calibre import __version__, __appname__, sanitize_file_name, \ iswindows, isosx, prints, patheq from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.config import prefs, dynamic +from calibre.utils.ipc.server import Server from calibre.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \ initialize_file_icon_provider, question_dialog,\ pixmap_to_data, choose_dir, ORG_NAME, \ @@ -104,6 +105,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): def __init__(self, listener, opts, actions, parent=None): self.preferences_action, self.quit_action = actions + self.spare_servers = [] MainWindow.__init__(self, opts, parent) # Initialize fontconfig in a separate thread as this can be a lengthy # process if run for the first time on this machine @@ -460,6 +462,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.setMaximumHeight(max_available_height()) + ####################### Start spare job server ######################## + QTimer.singleShot(1000, self.add_spare_server) ####################### Setup device detection ######################## self.device_manager = DeviceManager(Dispatcher(self.device_detected), @@ -490,7 +494,16 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.connect(self.action_sync, SIGNAL('triggered(bool)'), self._sync_menu.trigger_default) + def add_spare_server(self, *args): + self.spare_servers.append(Server()) + @property + def spare_server(self): + try: + QTimer.singleShot(1000, self.add_spare_server) + return self.spare_servers.pop() + except: + pass def no_op(self, *args): pass @@ -730,7 +743,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): from calibre.gui2.add import Adder self._adder = Adder(self, self.library_view.model().db, - Dispatcher(self._files_added)) + Dispatcher(self._files_added), spare_server=self.spare_server) self._adder.add_recursive(root, single) def add_recursive_single(self, checked): @@ -793,7 +806,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.__adder_func = partial(self._files_added, on_card=on_card) self._adder = Adder(self, None if to_device else self.library_view.model().db, - Dispatcher(self.__adder_func)) + Dispatcher(self.__adder_func), spare_server=self.spare_server) self._adder.add(paths) def _files_added(self, paths=[], names=[], infos=[], on_card=None): @@ -986,7 +999,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): Dispatcher(self._books_saved), rows, path, by_author=self.library_view.model().by_author, single_dir=single_dir, - single_format=single_format) + single_format=single_format, + spare_server=self.spare_server) else: paths = self.current_view().model().paths(rows) @@ -1618,6 +1632,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.check_messages_timer.stop() self.listener.close() self.job_manager.server.close() + while self.spare_servers: + self.spare_servers.pop().close() self.device_manager.keep_going = False self.cover_cache.stop() self.hide() From cd648cad291e07be189ce49b6decab796eec3b0b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 12:01:08 -0700 Subject: [PATCH 16/20] Fix Globe and Mail recipe for updated site --- .../feeds/recipes/recipe_globe_and_mail.py | 65 ++++++++----------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/src/calibre/web/feeds/recipes/recipe_globe_and_mail.py b/src/calibre/web/feeds/recipes/recipe_globe_and_mail.py index c50405096a..6214fa0578 100644 --- a/src/calibre/web/feeds/recipes/recipe_globe_and_mail.py +++ b/src/calibre/web/feeds/recipes/recipe_globe_and_mail.py @@ -8,46 +8,37 @@ globeandmail.com ''' from calibre.web.feeds.news import BasicNewsRecipe -from calibre.ebooks.BeautifulSoup import BeautifulSoup class GlobeAndMail(BasicNewsRecipe): - + title = 'Globe and Mail' __author__ = 'Kovid Goyal' language = _('English') + oldest_article = 2.0 + no_stylesheets = True description = 'Canada\'s national newspaper' - keep_only_tags = [dict(id='content')] - remove_tags = [dict(attrs={'class':'nav'}), dict(id=['related', 'TPphoto', 'secondaryNav', 'articleBottomToolsHolder'])] - - def parse_index(self): - src = self.browser.open('http://www.theglobeandmail.com/frontpage/').read() - soup = BeautifulSoup(src) - - feeds = [] - articles = [] - feed = 'Front Page' - for tag in soup.findAll(['h3', 'h4']): - if tag.name == 'h3': - a = tag.find('a', href=True) - if a is not None: - href = 'http://www.theglobeandmail.com' + a['href'].strip() - text = a.find(text=True) - if text: - text = text.strip() - desc = '' - summary = tag.findNextSiblings('p', attrs={'class':'summary'}, limit=1) - if summary: - desc = self.tag_to_string(summary[0], False) - articles.append({ - 'title': text, - 'url' : href, - 'desc' : desc, - 'date' : '', - }) - elif tag.name == 'h4': - if articles: - feeds.append((feed, articles)) - articles = [] - feed = self.tag_to_string(tag, False) - - return feeds \ No newline at end of file + remove_tags_before = dict(id="article-top") + remove_tags = [ + {'id':['util', 'article-tabs', 'comments', 'article-relations', + 'gallery-controls', 'video', 'galleryLoading']}, + ] + remove_tags_after = dict(id='article-content') + + feeds = [ + ('Latest headlines', 'http://www.theglobeandmail.com/?service=rss'), + ('Top stories', 'http://www.theglobeandmail.com/?service=rss&feed=topstories'), + ('National', 'http://www.theglobeandmail.com/news/national/?service=rss'), + ('Politics', 'http://www.theglobeandmail.com/news/politics/?service=rss'), + ('World', 'http://www.theglobeandmail.com/news/world/?service=rss'), + ('Business', 'http://www.theglobeandmail.com/report-on-business/?service=rss'), + ('Opinions', 'http://www.theglobeandmail.com/news/opinions/?service=rss'), + ('Columnists', 'http://www.theglobeandmail.com/news/opinions/columnists/?service=rss'), + ('Globe Investor', 'http://www.theglobeandmail.com/globe-investor/?service=rss'), + ('Sports', 'http://www.theglobeandmail.com/sports/?service=rss'), + ('Technology', 'http://www.theglobeandmail.com/news/technology/?service=rss'), + ('Arts', 'http://www.theglobeandmail.com/news/arts/?service=rss'), + ('Life', 'http://www.theglobeandmail.com/life/?service=rss'), + ('Blogs', 'http://www.theglobeandmail.com/blogs/?service=rss'), + ('Real Estate', 'http://www.theglobeandmail.com/real-estate/?service=rss'), + ('Auto', 'http://www.theglobeandmail.com/auto/?service=rss'), + ] From aefd75f69f3b986e0a242ab716559d4e978541f2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 14:12:08 -0700 Subject: [PATCH 17/20] Fix #2520 (San Francisco Chronicle Feed causes Sony PSR700 to Reset) --- .../web/feeds/recipes/recipe_san_fran_chronicle.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/calibre/web/feeds/recipes/recipe_san_fran_chronicle.py b/src/calibre/web/feeds/recipes/recipe_san_fran_chronicle.py index 7d93d7a5db..148383b496 100644 --- a/src/calibre/web/feeds/recipes/recipe_san_fran_chronicle.py +++ b/src/calibre/web/feeds/recipes/recipe_san_fran_chronicle.py @@ -12,19 +12,19 @@ class SanFranciscoChronicle(BasicNewsRecipe): title = u'San Francisco Chronicle' __author__ = u'Darko Miletic' description = u'San Francisco news' - language = _('English') + language = _('English') oldest_article = 7 max_articles_per_feed = 100 no_stylesheets = True use_embedded_content = False - keep_only_tags = [dict(name='td' , attrs={'class':'column1 w627'})] + remove_tags_before = {'class':'articleheadings'} remove_tags_after = dict(name='div', attrs={'id':'articlecontent' }) remove_tags = [ dict(name='div', attrs={'class':'tools tools_top'}) ,dict(name='div', attrs={'id':'articlebox' }) ] - feeds = [ + feeds = [ (u'Top News Stories', u'http://www.sfgate.com/rss/feeds/news.xml') - ] \ No newline at end of file + ] From 253a93d324558764ce6bfd69c9df5d536d6a2373 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 16:48:25 -0700 Subject: [PATCH 18/20] ... --- src/calibre/ebooks/mobi/writer.py | 2 +- upload.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 82ed1da7c1..291e937b2c 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -735,7 +735,7 @@ class MobiWriter(object): # The PalmDOC Header record0.write(pack('>HHIHHHH', self._compression, 0, self._text_length, - self._text_nrecords, RECORD_SIZE, 0, 0)) # 0 - 15 (0x0 - 0xf) + self._text_nrecords-1, RECORD_SIZE, 0, 0)) # 0 - 15 (0x0 - 0xf) uid = random.randint(0, 0xffffffff) title = str(metadata.title[0]) # The MOBI Header diff --git a/upload.py b/upload.py index 973e31c8ab..b3b1d9035a 100644 --- a/upload.py +++ b/upload.py @@ -707,6 +707,15 @@ class stage1(OptionlessCommand): ('upload_demo', None), ] +class betas(OptionlessCommand): + description = 'Build an upload beta builds to the servers' + + sub_commands = [ ('stage2', None) ] + + def run(self): + OptionlessCommand.run(self) + check_call('scp dist/* divok:'+BETAS, shell=True) + class upload(OptionlessCommand): description = 'Build and upload calibre to the servers' From 581838308add8e2be07aac45393192d1b99ae330 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 16:49:39 -0700 Subject: [PATCH 19/20] ... --- todo | 3 --- 1 file changed, 3 deletions(-) diff --git a/todo b/todo index 9b2a90f0b2..d7f7645f14 100644 --- a/todo +++ b/todo @@ -1,9 +1,6 @@ * Refactor web.fetch.simple to use per connection timeouts via the timeout kwarg for mechanize.open -* Rationalize books table. Add a pubdate column, remove the uri column (and associated support in add_books) and convert series_index to a float. - - test adding/recusrsize adding and adding of duplicates - * Testing framework * MOBI navigation indexing support From cc04191f80bf0d1e29facf85fe77a72717291870 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 2 Jun 2009 16:52:53 -0700 Subject: [PATCH 20/20] Add command to upload betas --- setup.py | 3 ++- upload.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 14bbbf0a3f..92ee757fdd 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,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 + upload_rss, betas entry_points['console_scripts'].append( 'calibre_postinstall = calibre.linux:post_install') @@ -212,6 +212,7 @@ if __name__ == '__main__': 'stage2' : stage2, 'stage1' : stage1, 'publish' : upload, + 'betas' : betas, }, ) diff --git a/upload.py b/upload.py index b3b1d9035a..de68082db4 100644 --- a/upload.py +++ b/upload.py @@ -710,7 +710,7 @@ class stage1(OptionlessCommand): class betas(OptionlessCommand): description = 'Build an upload beta builds to the servers' - sub_commands = [ ('stage2', None) ] + sub_commands = [ ('update', None), ('stage2', None) ] def run(self): OptionlessCommand.run(self)