Pull from trunk

This commit is contained in:
Timothy Legge 2010-06-28 20:52:09 -03:00
commit 3b9a290ec0
35 changed files with 18799 additions and 15798 deletions

View File

@ -4,6 +4,53 @@
# for important features/bug fixes. # for important features/bug fixes.
# Also, each release can have new and improved recipes. # Also, each release can have new and improved recipes.
- version: 0.7.6
date: 2010-06-28
new features:
- title: "Add support for the new firmware of the Azbooka"
tickets: [5994]
- title: "A few speedups for calibre startup, should add up to a few seconds of startup time on slower machines"
- title: "Support for the Sweem MM300"
- title: "Add keyboard shorcut for Download metadata and covers"
bug fixes:
- title: "Fix regression in 0.7.5 that broke conversion of malformed HTML files (like those Microsoft Word outputs)"
type: major
tickets: [5991]
- title: "Don't download tags from librarything, as the tagging there is not very good"
- title: "Add mimetype for FB2 so that it can be served by the content server"
tickets: [6011]
- title: "Ensure cover is not resized to less than the available space in the Edit Meta Information dialog"
tickets: [6001]
- title: "SONY driver: Only update collections when sending book to device for the first time"
- title: "calibre should now work on windows when the location for the library contains non-ascii characters"
tickets: [5983]
- title: "Cover browser once again distorts instead of cropping covers that have an incorrect aspect ratio"
- title: "ISBNDb metadata plugin: Fix bug causing only first page of results to be fetched"
- title: "Move iTunes driver to the bottom so that it doesn't interfere with device detection for people that have iphones and an ereader plugged in"
improved recipes:
- Houston Chronicle
- Hindu
- Times of India
- New York Times
new recipes:
- title: Winnipeg Sun
author: rty
- version: 0.7.5 - version: 0.7.5
date: 2010-06-25 date: 2010-06-25

View File

@ -28,7 +28,7 @@ class OldNewThing(BasicNewsRecipe):
} }
remove_attributes = ['width','height'] remove_attributes = ['width','height']
keep_only_tags = [dict(attrs={'class':['postsub','comment']})] keep_only_tags = [dict(attrs={'class':'full-post'})]
remove_tags = [dict(attrs={'class':['post-attributes','post-tags','post-actions']})]
feeds = [(u'Posts', u'http://blogs.msdn.com/oldnewthing/rss.xml')] feeds = [(u'Posts', u'http://blogs.msdn.com/oldnewthing/rss.xml')]

View File

@ -153,6 +153,18 @@
<Property Id="WixShellExecTarget" Value="[#{exe_map[calibre]}]" /> <Property Id="WixShellExecTarget" Value="[#{exe_map[calibre]}]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" <CustomAction Id="LaunchApplication" BinaryKey="WixCA"
DllEntry="WixShellExec" Impersonate="yes"/> DllEntry="WixShellExec" Impersonate="yes"/>
<InstallExecuteSequence>
<FileCost Suppress="yes" />
</InstallExecuteSequence>
<InstallUISequence>
<FileCost Suppress="yes" />
</InstallUISequence>
<AdminExecuteSequence>
<FileCost Suppress="yes" />
</AdminExecuteSequence>
<AdminUISequence>
<FileCost Suppress="yes" />
</AdminUISequence>
</Product> </Product>
</Wix> </Wix>

View File

@ -30,6 +30,7 @@ mimetypes.add_type('application/epub+zip', '.epub')
mimetypes.add_type('text/x-sony-bbeb+xml', '.lrs') mimetypes.add_type('text/x-sony-bbeb+xml', '.lrs')
mimetypes.add_type('application/xhtml+xml', '.xhtml') mimetypes.add_type('application/xhtml+xml', '.xhtml')
mimetypes.add_type('image/svg+xml', '.svg') mimetypes.add_type('image/svg+xml', '.svg')
mimetypes.add_type('text/fb2+xml', '.fb2')
mimetypes.add_type('application/x-sony-bbeb', '.lrf') mimetypes.add_type('application/x-sony-bbeb', '.lrf')
mimetypes.add_type('application/x-sony-bbeb', '.lrx') mimetypes.add_type('application/x-sony-bbeb', '.lrx')
mimetypes.add_type('application/x-dtbncx+xml', '.ncx') mimetypes.add_type('application/x-dtbncx+xml', '.ncx')

View File

@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
__appname__ = 'calibre' __appname__ = 'calibre'
__version__ = '0.7.5' __version__ = '0.7.6'
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>" __author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
import re import re

View File

@ -298,8 +298,9 @@ class USBMS(CLI, Device):
# Clear the _new_book indication, as we are supposed to be done with # Clear the _new_book indication, as we are supposed to be done with
# adding books at this point # adding books at this point
for blist in booklists: for blist in booklists:
for book in blist: if blist is not None:
book._new_book = False for book in blist:
book._new_book = False
self.report_progress(1.0, _('Sending metadata to device...')) self.report_progress(1.0, _('Sending metadata to device...'))
debug_print('USBMS: finished sync_booklists') debug_print('USBMS: finished sync_booklists')

View File

@ -151,6 +151,7 @@ cpalmdoc_do_compress(buffer *b, char *output) {
for (j=0; j < temp.len; j++) *(output++) = (char)temp.data[j]; for (j=0; j < temp.len; j++) *(output++) = (char)temp.data[j];
} }
} }
PyMem_Free(temp.data);
return output - head; return output - head;
} }
@ -168,7 +169,9 @@ cpalmdoc_compress(PyObject *self, PyObject *args) {
for (j = 0; j < input_len; j++) for (j = 0; j < input_len; j++)
b.data[j] = (_input[j] < 0) ? _input[j]+256 : _input[j]; b.data[j] = (_input[j] < 0) ? _input[j]+256 : _input[j];
b.len = input_len; b.len = input_len;
output = (char *)PyMem_Malloc(sizeof(char) * b.len); // Make the output buffer larger than the input as sometimes
// compression results in a larger block
output = (char *)PyMem_Malloc(sizeof(char) * (int)(1.25*b.len));
if (output == NULL) return PyErr_NoMemory(); if (output == NULL) return PyErr_NoMemory();
j = cpalmdoc_do_compress(&b, output); j = cpalmdoc_do_compress(&b, output);
if ( j == 0) return PyErr_NoMemory(); if ( j == 0) return PyErr_NoMemory();

View File

@ -313,6 +313,8 @@ def search(title=None, author=None, publisher=None, isbn=None, isbndb_key=None,
def sort_func(x, y): def sort_func(x, y):
def cleanup_title(s): def cleanup_title(s):
if s is None:
s = _('Unknown')
s = s.strip().lower() s = s.strip().lower()
s = prefix_pat.sub(' ', s) s = prefix_pat.sub(' ', s)
s = trailing_paren_pat.sub('', s) s = trailing_paren_pat.sub('', s)

View File

@ -133,10 +133,10 @@ def get_social_metadata(title, authors, publisher, isbn, username=None,
if match is not None: if match is not None:
si = float(match.group()) si = float(match.group())
mi.series_index = si mi.series_index = si
tags = root.xpath('//div[@class="tags"]/span[@class="tag"]/a') #tags = root.xpath('//div[@class="tags"]/span[@class="tag"]/a')
if tags: #if tags:
mi.tags = [html.tostring(x, method='text', encoding=unicode) for x # mi.tags = [html.tostring(x, method='text', encoding=unicode) for x
in tags] # in tags]
span = root.xpath( span = root.xpath(
'//table[@class="wsltable"]/tr[@class="wslcontent"]/td[4]//span') '//table[@class="wsltable"]/tr[@class="wslcontent"]/td[4]//span')
if span: if span:

View File

@ -882,7 +882,7 @@ class Manifest(object):
"<?xml version='1.0' encoding='utf-8'?><o:p></o:p>", "<?xml version='1.0' encoding='utf-8'?><o:p></o:p>",
'') '')
data = data.replace("<?xml version='1.0' encoding='utf-8'??>", '') data = data.replace("<?xml version='1.0' encoding='utf-8'??>", '')
data = etree.fromstring(data) data = etree.fromstring(data, parser=RECOVER_PARSER)
elif namespace(data.tag) != XHTML_NS: elif namespace(data.tag) != XHTML_NS:
# OEB_DOC_NS, but possibly others # OEB_DOC_NS, but possibly others
ns = namespace(data.tag) ns = namespace(data.tag)

View File

@ -87,6 +87,9 @@ class MetadataWidget(Widget, Ui_Form):
if not pm.isNull(): if not pm.isNull():
self.cover.setPixmap(pm) self.cover.setPixmap(pm)
self.cover_data = cover self.cover_data = cover
else:
self.cover.setPixmap(QPixmap(I('default_cover.svg')))
def initialize_combos(self): def initialize_combos(self):
self.initalize_authors() self.initalize_authors()

View File

@ -20,36 +20,6 @@
<string>Book Cover</string> <string>Book Cover</string>
</property> </property>
<layout class="QGridLayout" name="_2"> <layout class="QGridLayout" name="_2">
<item row="0" column="0">
<layout class="QHBoxLayout" name="_3">
<item>
<widget class="ImageView" name="cover">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../resources/images.qrc">:/images/book.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="opt_prefer_metadata_cover">
<property name="text">
<string>Use cover from &amp;source file</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<layout class="QVBoxLayout" name="_4"> <layout class="QVBoxLayout" name="_4">
<property name="spacing"> <property name="spacing">
@ -101,6 +71,30 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0">
<widget class="QCheckBox" name="opt_prefer_metadata_cover">
<property name="text">
<string>Use cover from &amp;source file</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="_3">
<item>
<widget class="ImageView" name="cover" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
<zorder>opt_prefer_metadata_cover</zorder> <zorder>opt_prefer_metadata_cover</zorder>
<zorder></zorder> <zorder></zorder>
@ -308,11 +302,6 @@
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>ImageView</class>
<extends>QLabel</extends>
<header>widgets.h</header>
</customwidget>
<customwidget> <customwidget>
<class>EnLineEdit</class> <class>EnLineEdit</class>
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
@ -328,6 +317,12 @@
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
<header>widgets.h</header> <header>widgets.h</header>
</customwidget> </customwidget>
<customwidget>
<class>ImageView</class>
<extends>QWidget</extends>
<header>calibre/gui2/widgets.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>title</tabstop> <tabstop>title</tabstop>

View File

@ -11,7 +11,7 @@ import re
import time import time
import traceback import traceback
from PyQt4.Qt import SIGNAL, QObject, QCoreApplication, Qt, QTimer, QThread, QDate, \ from PyQt4.Qt import SIGNAL, QObject, Qt, QTimer, QThread, QDate, \
QPixmap, QListWidgetItem, QDialog QPixmap, QListWidgetItem, QDialog
from calibre.gui2 import error_dialog, file_icon_provider, dynamic, \ from calibre.gui2 import error_dialog, file_icon_provider, dynamic, \
@ -25,7 +25,6 @@ from calibre.ebooks import BOOK_EXTENSIONS
from calibre.ebooks.metadata import string_to_authors, \ from calibre.ebooks.metadata import string_to_authors, \
authors_to_string, check_isbn authors_to_string, check_isbn
from calibre.ebooks.metadata.library_thing import cover_from_isbn from calibre.ebooks.metadata.library_thing import cover_from_isbn
from calibre import islinux, isfreebsd
from calibre.ebooks.metadata.meta import get_metadata from calibre.ebooks.metadata.meta import get_metadata
from calibre.utils.config import prefs, tweaks from calibre.utils.config import prefs, tweaks
from calibre.utils.date import qt_to_dt from calibre.utils.date import qt_to_dt
@ -311,7 +310,6 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
self.formats.setAcceptDrops(True) self.formats.setAcceptDrops(True)
self.cover_changed = False self.cover_changed = False
self.cpixmap = None self.cpixmap = None
self.cover.setAcceptDrops(True)
self.pubdate.setMinimumDate(QDate(100,1,1)) self.pubdate.setMinimumDate(QDate(100,1,1))
pubdate_format = tweaks['gui_pubdate_display_format'] pubdate_format = tweaks['gui_pubdate_display_format']
if pubdate_format is not None: if pubdate_format is not None:
@ -399,11 +397,6 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
self.series.lineEdit().editingFinished.connect(self.increment_series_index) self.series.lineEdit().editingFinished.connect(self.increment_series_index)
self.show() self.show()
height_of_rest = self.frameGeometry().height() - self.cover.height()
width_of_rest = self.frameGeometry().width() - self.cover.width()
ag = QCoreApplication.instance().desktop().availableGeometry(self)
self.cover.MAX_HEIGHT = ag.height()-(25 if (islinux or isfreebsd) else 0)-height_of_rest
self.cover.MAX_WIDTH = ag.width()-(25 if (islinux or isfreebsd) else 0)-width_of_rest
pm = QPixmap() pm = QPixmap()
if cover: if cover:
pm.loadFromData(cover) pm.loadFromData(cover)

View File

@ -576,22 +576,13 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="ImageView" name="cover"> <widget class="ImageView" name="cover" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>100</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../resources/images.qrc">:/images/book.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -707,11 +698,6 @@
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>ImageView</class>
<extends>QLabel</extends>
<header>widgets.h</header>
</customwidget>
<customwidget> <customwidget>
<class>EnLineEdit</class> <class>EnLineEdit</class>
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
@ -732,6 +718,12 @@
<extends>QListWidget</extends> <extends>QListWidget</extends>
<header location="global">calibre/gui2/widgets.h</header> <header location="global">calibre/gui2/widgets.h</header>
</customwidget> </customwidget>
<customwidget>
<class>ImageView</class>
<extends>QWidget</extends>
<header>calibre/gui2/widgets.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>title</tabstop> <tabstop>title</tabstop>

View File

@ -13,7 +13,7 @@ from PyQt4.Qt import QListView, QIcon, QFont, QLabel, QListWidget, \
QRegExp, QSettings, QSize, QModelIndex, QSplitter, \ QRegExp, QSettings, QSize, QModelIndex, QSplitter, \
QAbstractButton, QPainter, QLineEdit, QComboBox, \ QAbstractButton, QPainter, QLineEdit, QComboBox, \
QMenu, QStringListModel, QCompleter, QStringList, \ QMenu, QStringListModel, QCompleter, QStringList, \
QTimer QTimer, QRect
from calibre.gui2 import NONE, error_dialog, pixmap_to_data, gprefs from calibre.gui2 import NONE, error_dialog, pixmap_to_data, gprefs
@ -146,10 +146,15 @@ class FormatList(QListWidget):
return QListWidget.keyPressEvent(self, event) return QListWidget.keyPressEvent(self, event)
class ImageView(QLabel): class ImageView(QWidget):
MAX_WIDTH = 400 def __init__(self, parent=None):
MAX_HEIGHT = 300 QWidget.__init__(self, parent)
self._pixmap = QPixmap(self)
self.setMinimumSize(QSize(150, 200))
self.setAcceptDrops(True)
# Drag 'n drop {{{
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS
@classmethod @classmethod
@ -186,13 +191,45 @@ class ImageView(QLabel):
def dragMoveEvent(self, event): def dragMoveEvent(self, event):
event.acceptProposedAction() event.acceptProposedAction()
# }}}
def setPixmap(self, pixmap): def setPixmap(self, pixmap):
QLabel.setPixmap(self, pixmap) if not isinstance(pixmap, QPixmap):
width, height = fit_image(pixmap.width(), pixmap.height(), self.MAX_WIDTH, self.MAX_HEIGHT)[1:] raise TypeError('Must use a QPixmap')
self.setMaximumWidth(width) self._pixmap = pixmap
self.setMaximumHeight(height) self.updateGeometry()
self.update()
def pixmap(self):
return self._pixmap
def sizeHint(self):
if self._pixmap.isNull():
return self.minimumSize()
return self._pixmap.size()
def paintEvent(self, event):
QWidget.paintEvent(self, event)
pmap = self._pixmap
if pmap.isNull():
return
w, h = pmap.width(), pmap.height()
cw, ch = self.rect().width(), self.rect().height()
scaled, nw, nh = fit_image(w, h, cw, ch)
if scaled:
pmap = pmap.scaled(nw, nh, Qt.IgnoreAspectRatio,
Qt.SmoothTransformation)
w, h = pmap.width(), pmap.height()
x = int(abs(cw - w)/2.)
y = int(abs(ch - h)/2.)
target = QRect(x, y, w, h)
p = QPainter(self)
p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
p.drawPixmap(target, pmap)
p.end()
# Clipboard copy/paste # {{{
def contextMenuEvent(self, ev): def contextMenuEvent(self, ev):
cm = QMenu(self) cm = QMenu(self)
copy = cm.addAction(_('Copy Image')) copy = cm.addAction(_('Copy Image'))
@ -215,6 +252,7 @@ class ImageView(QLabel):
self.setPixmap(pmap) self.setPixmap(pmap)
self.emit(SIGNAL('cover_changed(PyQt_PyObject)'), self.emit(SIGNAL('cover_changed(PyQt_PyObject)'),
pixmap_to_data(pmap)) pixmap_to_data(pmap))
# }}}
class LocationModel(QAbstractListModel): class LocationModel(QAbstractListModel):

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff