Date: Tue, 10 Feb 2009 13:38:10 -0800
Subject: [PATCH 06/21] IGN:Mark EPUB output as stable and commit temoprary fix
for #1817
---
src/calibre/ebooks/mobi/reader.py | 4 ++--
src/calibre/gui2/main.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py
index 6811f9ccda..8b81702bc1 100644
--- a/src/calibre/ebooks/mobi/reader.py
+++ b/src/calibre/ebooks/mobi/reader.py
@@ -308,8 +308,8 @@ class MobiReader(object):
if 'filepos-id' in attrib:
attrib['id'] = attrib.pop('filepos-id')
if 'filepos' in attrib:
- filepos = int(attrib.pop('filepos'))
- attrib['href'] = "#filepos%d" % filepos
+ filepos = attrib.pop('filepos')
+ attrib['href'] = "#filepos%s" % filepos
if tag.tag == 'img':
recindex = None
for attr in self.IMAGE_ATTRS:
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index c2e755a742..0e59e35e1e 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -391,7 +391,7 @@ class Main(MainWindow, Ui_MainWindow):
def change_output_format(self, x):
of = unicode(x).strip()
if of != prefs['output_format']:
- if of not in ('LRF',):
+ if of not in ('LRF', 'EPUB'):
warning_dialog(self, 'Warning',
'%s support is still in beta. If you find bugs, please report them by opening a ticket.'%of).exec_()
prefs.set('output_format', of)
From 4fa00105b39a1b802deafaf3c34ca803cddeee16 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 13:45:27 -0800
Subject: [PATCH 07/21] IGN:...
---
src/calibre/ebooks/mobi/reader.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py
index 8b81702bc1..1c434c9472 100644
--- a/src/calibre/ebooks/mobi/reader.py
+++ b/src/calibre/ebooks/mobi/reader.py
@@ -309,7 +309,10 @@ class MobiReader(object):
attrib['id'] = attrib.pop('filepos-id')
if 'filepos' in attrib:
filepos = attrib.pop('filepos')
- attrib['href'] = "#filepos%s" % filepos
+ try:
+ attrib['href'] = "#filepos%d" % int(filepos)
+ except ValueError:
+ attrib['href'] = filepos
if tag.tag == 'img':
recindex = None
for attr in self.IMAGE_ATTRS:
From de1f54d39f7420e147c6cdc27309cd4570f2d24d Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 13:45:52 -0800
Subject: [PATCH 08/21] IGN:...
---
src/calibre/ebooks/mobi/reader.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py
index 1c434c9472..bfbe8f5ae5 100644
--- a/src/calibre/ebooks/mobi/reader.py
+++ b/src/calibre/ebooks/mobi/reader.py
@@ -311,7 +311,7 @@ class MobiReader(object):
filepos = attrib.pop('filepos')
try:
attrib['href'] = "#filepos%d" % int(filepos)
- except ValueError:
+ except:
attrib['href'] = filepos
if tag.tag == 'img':
recindex = None
From 5c4294652ef219df1989df78d7089af09850d784 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 13:59:37 -0800
Subject: [PATCH 09/21] Fix system tray icon not being hidden when quitting on
windows
---
src/calibre/gui2/main.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index 0e59e35e1e..e674ca4fd6 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -1572,6 +1572,11 @@ def main(args=sys.argv):
print 'Restarting with:', e, sys.argv
os.execvp(e, sys.argv)
else:
+ if iswindows:
+ try:
+ main.system_tray_icon.hide()
+ except:
+ pass
return ret
return 0
From 005ca51c8441f729b09cc9373eaadb481db5dbff Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 14:23:29 -0800
Subject: [PATCH 10/21] Fix bug in handling of author names with commas when
sending books to device
---
src/calibre/gui2/library.py | 38 ++++++++++++++-----------------------
src/calibre/gui2/main.py | 1 -
2 files changed, 14 insertions(+), 25 deletions(-)
diff --git a/src/calibre/gui2/library.py b/src/calibre/gui2/library.py
index 9f0877ca09..199c4ada67 100644
--- a/src/calibre/gui2/library.py
+++ b/src/calibre/gui2/library.py
@@ -1,3 +1,4 @@
+from calibre.ebooks.metadata import authors_to_string
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal '
import os, textwrap, traceback, time, re
@@ -371,35 +372,24 @@ class BooksModel(QAbstractTableModel):
if not rows_are_ids:
rows = [self.db.id(row.row()) for row in rows]
for id in rows:
- au = self.db.authors(id, index_is_id=True)
- tags = self.db.tags(id, index_is_id=True)
- if not au:
- au = _('Unknown')
- au = au.split(',')
- if len(au) > 1:
- t = ', '.join(au[:-1])
- t += ' & ' + au[-1]
- au = t
- else:
- au = ' & '.join(au)
- if not tags:
- tags = []
- else:
- tags = tags.split(',')
- series = self.db.series(id, index_is_id=True)
- if series is not None:
- tags.append(series)
- mi = {
- 'title' : self.db.title(id, index_is_id=True),
+ mi = self.db.get_metadata(id, index_is_id=True)
+ au = authors_to_string(mi.authors if mi.authors else [_('Unknown')])
+ tags = mi.tags if mi.tags else []
+ if mi.series is not None:
+ tags.append(mi.series)
+ info = {
+ 'title' : mi.title,
'authors' : au,
'cover' : self.db.cover(id, index_is_id=True),
'tags' : tags,
- 'comments': self.db.comments(id, index_is_id=True),
+ 'comments': mi.comments,
}
- if series is not None:
- mi['tag order'] = {series:self.db.books_in_series_of(id, index_is_id=True)}
+ if mi.series is not None:
+ info['tag order'] = {
+ mi.series:self.db.books_in_series_of(id, index_is_id=True)
+ }
- metadata.append(mi)
+ metadata.append(info)
return metadata
def get_preferred_formats_from_ids(self, ids, all_formats, mode='r+b'):
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index e674ca4fd6..83665ac8a7 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -48,7 +48,6 @@ from calibre.ebooks import BOOK_EXTENSIONS
from calibre.library.database2 import LibraryDatabase2, CoverCache
from calibre.parallel import JobKilled
from calibre.utils.filenames import ascii_filename
-from calibre.gui2.widgets import WarningDialog
from calibre.gui2.dialogs.confirm_delete import confirm
class Main(MainWindow, Ui_MainWindow):
From 9991549be6eb776766f47035a7e182cfb5b6b588 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 14:37:15 -0800
Subject: [PATCH 11/21] version 0.4.136
---
src/calibre/constants.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calibre/constants.py b/src/calibre/constants.py
index cbb7fba14e..2d77964693 100644
--- a/src/calibre/constants.py
+++ b/src/calibre/constants.py
@@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = 'calibre'
-__version__ = '0.4.135'
+__version__ = '0.4.136'
__author__ = "Kovid Goyal "
'''
Various run time constants.
From dd675d62102466c1b72c9facd27ec8a7b21e0aa8 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 14:41:54 -0800
Subject: [PATCH 12/21] IGN:Tag release
From b18f95c02f013eed0bc6150b3dfe7a157547b1a8 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 16:07:19 -0800
Subject: [PATCH 13/21] Fix #1805 (spurious ![endif]>![if> 's found in title
and chapter)
---
src/calibre/ebooks/html.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/calibre/ebooks/html.py b/src/calibre/ebooks/html.py
index e264fec7cb..ad4538b302 100644
--- a/src/calibre/ebooks/html.py
+++ b/src/calibre/ebooks/html.py
@@ -330,7 +330,8 @@ class PreProcessor(object):
sanitize_head),
# Convert all entities, since lxml doesn't handle them well
(re.compile(r'&(\S+?);'), convert_entities),
-
+ # Remove ]*>'), lambda match: ''),
]
# Fix pdftohtml markup
From 4a172b34adc586bbf709e7ed6716c3a702236e39 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 16:09:27 -0800
Subject: [PATCH 14/21] IGN:...
---
src/calibre/ebooks/html.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calibre/ebooks/html.py b/src/calibre/ebooks/html.py
index ad4538b302..f69f26a1e6 100644
--- a/src/calibre/ebooks/html.py
+++ b/src/calibre/ebooks/html.py
@@ -330,7 +330,7 @@ class PreProcessor(object):
sanitize_head),
# Convert all entities, since lxml doesn't handle them well
(re.compile(r'&(\S+?);'), convert_entities),
- # Remove ]*>'), lambda match: ''),
]
From 5aa219339dc0a8697cff65009318fc27523133eb Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 16:14:48 -0800
Subject: [PATCH 15/21] IGN:...
---
src/calibre/trac/plugins/download.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calibre/trac/plugins/download.py b/src/calibre/trac/plugins/download.py
index e63a7d8d0d..7abf7faed4 100644
--- a/src/calibre/trac/plugins/download.py
+++ b/src/calibre/trac/plugins/download.py
@@ -35,7 +35,7 @@ class Distribution(object):
('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'),
('dbus-python', '0.82.2', 'dbus-python', 'python-dbus', 'dbus-python'),
('lxml', '2.0.5', 'lxml', 'python-lxml', 'python-lxml'),
- ('python-dateutil', '1.4.1', 'python-dateutil', 'python-dateutil', 'python-dateutil')
+ ('python-dateutil', '1.4.1', 'python-dateutil', 'python-dateutil', 'python-dateutil'),
('BeautifulSoup', '3.0.5', 'beautifulsoup', 'python-beautifulsoup', 'python-BeautifulSoup'),
('help2man', '1.36.4', 'help2man', 'help2man', 'help2man'),
]
From 78e5a7d928e2324663dbc1110fc754797671dd96 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Tue, 10 Feb 2009 18:19:58 -0800
Subject: [PATCH 16/21] IGN:Mark politika recipe as Serbian
---
src/calibre/web/feeds/recipes/recipe_politika.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/calibre/web/feeds/recipes/recipe_politika.py b/src/calibre/web/feeds/recipes/recipe_politika.py
index 1575d8984f..f1d84915ce 100644
--- a/src/calibre/web/feeds/recipes/recipe_politika.py
+++ b/src/calibre/web/feeds/recipes/recipe_politika.py
@@ -16,6 +16,7 @@ class Politika(BasicNewsRecipe):
publisher = 'Politika novine i Magazini d.o.o'
category = 'news, politics, Serbia'
oldest_article = 2
+ language = _('Serbian')
max_articles_per_feed = 100
no_stylesheets = True
use_embedded_content = False
From 7b87aaf55f777895043e678be806658d12701246 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Wed, 11 Feb 2009 01:48:52 -0800
Subject: [PATCH 17/21] IGN:Add donate button to User Manual
---
src/calibre/manual/templates/layout.html | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 src/calibre/manual/templates/layout.html
diff --git a/src/calibre/manual/templates/layout.html b/src/calibre/manual/templates/layout.html
new file mode 100644
index 0000000000..3564357684
--- /dev/null
+++ b/src/calibre/manual/templates/layout.html
@@ -0,0 +1,12 @@
+{% extends "!layout.html" %}
+{% block sidebarlogo %}
+{{ super() }}
+
+
+{% endblock %}
+
From ded6c02dba002ae98d60c31c5dcbeb86f489cb0f Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Wed, 11 Feb 2009 11:24:15 -0800
Subject: [PATCH 18/21] Fix nasty bug in handling of dates in the database.
This can prevent calibre from starting. An update is highly recommended
---
src/calibre/library/sqlite.py | 39 +++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py
index 938e5e665c..cc30f6dd5c 100644
--- a/src/calibre/library/sqlite.py
+++ b/src/calibre/library/sqlite.py
@@ -12,11 +12,50 @@ from sqlite3 import IntegrityError
from threading import Thread
from Queue import Queue
from threading import RLock
+from datetime import tzinfo, datetime, timedelta
from calibre.library import title_sort
global_lock = RLock()
+def convert_timestamp(val):
+ datepart, timepart = val.split(' ')
+ tz, mult = None, 1
+ x = timepart.split('+')
+ if len(x) > 1:
+ timepart, tz = x
+ else:
+ x = timepart.split('-')
+ if len(x) > 1:
+ timepart, tz = x
+ mult = -1
+
+ year, month, day = map(int, datepart.split("-"))
+ timepart_full = timepart.split(".")
+ hours, minutes, seconds = map(int, timepart_full[0].split(":"))
+ if len(timepart_full) == 2:
+ microseconds = int(timepart_full[1])
+ else:
+ microseconds = 0
+ if tz is not None:
+ h, m = map(int, tz.split(':'))
+ delta = timedelta(minutes=mult*(60*h + m))
+ tz = type('CustomTZ', (tzinfo,), {'utcoffset':lambda self, dt:delta,
+ 'dst':lambda self,dt:timedelta(0)})()
+
+ val = datetime(year, month, day, hours, minutes, seconds, microseconds,
+ tzinfo=tz)
+ if tz is not None:
+ val = datetime(*(val.utctimetuple()[:6]))
+ return val
+
+def adapt_datetime(dt):
+ dt = datetime(*(dt.utctimetuple()[:6]))
+ return dt.isoformat(' ')
+
+sqlite.register_adapter(datetime, adapt_datetime)
+sqlite.register_converter('timestamp', convert_timestamp)
+
class Concatenate(object):
'''String concatenation aggregator for sqlite'''
def __init__(self, sep=','):
From 759c17bec3971ad01bd7b38c18c393bf1037e77e Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Wed, 11 Feb 2009 11:33:25 -0800
Subject: [PATCH 19/21] Fix #1826 (sending to SD card on reader)
---
src/calibre/devices/prs505/books.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/calibre/devices/prs505/books.py b/src/calibre/devices/prs505/books.py
index b63b089fdd..06d205fb02 100644
--- a/src/calibre/devices/prs505/books.py
+++ b/src/calibre/devices/prs505/books.py
@@ -186,7 +186,10 @@ class BookList(_BookList):
node = self.document.createElement(self.prefix + "text")
mime = MIME_MAP[name.rpartition('.')[-1].lower()]
cid = self.max_id()+1
- sourceid = str(self[0].sourceid) if len(self) else "1"
+ try:
+ sourceid = str(self[0].sourceid) if len(self) else '1'
+ except:
+ sourceid = '1'
attrs = {
"title" : info["title"],
'titleSorter' : sortable_title(info['title']),
From 2b4a4a31e362e03d5f6e1b1faafa349eb1792857 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Wed, 11 Feb 2009 11:46:30 -0800
Subject: [PATCH 20/21] Fix #1823 (Calibre crashes on import of Mobipocket
file)
---
src/calibre/library/database2.py | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py
index 00da8f3e37..388a2d4fdb 100644
--- a/src/calibre/library/database2.py
+++ b/src/calibre/library/database2.py
@@ -19,7 +19,8 @@ from calibre.library import title_sort
from calibre.library.database import LibraryDatabase
from calibre.library.sqlite import connect, IntegrityError
from calibre.utils.search_query_parser import SearchQueryParser
-from calibre.ebooks.metadata import string_to_authors, authors_to_string, MetaInformation
+from calibre.ebooks.metadata import string_to_authors, authors_to_string, \
+ MetaInformation, authors_to_sort_string
from calibre.ebooks.metadata.meta import get_metadata, set_metadata, \
metadata_from_formats
from calibre.ebooks.metadata.opf2 import OPFCreator
@@ -1197,11 +1198,17 @@ class LibraryDatabase2(LibraryDatabase):
def import_book(self, mi, formats, notify=True):
series_index = 1 if mi.series_index is None else mi.series_index
+ if not mi.title:
+ mi.title = _('Unknown')
if not mi.authors:
mi.authors = [_('Unknown')]
- aus = mi.author_sort if mi.author_sort else ', '.join(mi.authors)
+ aus = mi.author_sort if mi.author_sort else authors_to_sort_string(mi.authors)
+ if isinstance(aus, str):
+ aus = aus.decode(preferred_encoding, 'replace')
+ title = mi.title if isinstance(mi.title, unicode) else \
+ mi.title.decode(preferred_encoding, 'replace')
obj = self.conn.execute('INSERT INTO books(title, uri, series_index, author_sort) VALUES (?, ?, ?, ?)',
- (mi.title, None, series_index, aus))
+ (title, None, series_index, aus))
id = obj.lastrowid
self.data.books_added([id], self.conn)
self.set_path(id, True)
From fbb6a3917eb66ebce310edd06847158928dcc241 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Wed, 11 Feb 2009 13:26:38 -0800
Subject: [PATCH 21/21] IGN:Show meaningful error if user tries to set cover
from format with no format selected
---
src/calibre/gui2/dialogs/metadata_single.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py
index 385e105c3a..78415f3a19 100644
--- a/src/calibre/gui2/dialogs/metadata_single.py
+++ b/src/calibre/gui2/dialogs/metadata_single.py
@@ -113,6 +113,10 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
def set_cover(self):
row = self.formats.currentRow()
fmt = self.formats.item(row)
+ if fmt is None:
+ error_dialog(self, _('No format selected'),
+ _('No format selected')).exec_()
+ return
ext = fmt.ext.lower()
if fmt.path is None:
stream = self.db.format(self.row, ext, as_file=True)
@@ -121,7 +125,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
try:
mi = get_metadata(stream, ext)
except:
- error_dialog(self, _('Could not read metadata'),
+ error_dialog(self, _('Could not read metadata'),
_('Could not read metadata from %s format')%ext).exec_()
return
cdata = None