mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
16c81b450d
@ -23,7 +23,8 @@
|
||||
date: 2012-03-23
|
||||
|
||||
new features:
|
||||
- title: "E-book viewer: A whole new full screen mode, with no toolbars to distract from the text and the ability to set the width of the column of text via Preferences in the ebook viewer."
|
||||
- title: "E-book viewer: A whole new full screen mode."
|
||||
description: "The new mode has no toolbars to distract from the text and the ability to set the width of the column of text via Preferences in the ebook viewer. Click the Fullscreen button on the toolbar in the viewer to enter fullscreen mode (or press the F11 or Ctrl+Shit+F keys)"
|
||||
type: major
|
||||
tickets: [959830]
|
||||
|
||||
|
@ -328,7 +328,7 @@ class MOBIHeader(object): # {{{
|
||||
(self.sect_idx, self.skel_idx, self.datp_idx, self.oth_idx
|
||||
) = struct.unpack_from(b'>4L', self.raw, 248)
|
||||
self.unknown9 = self.raw[264:self.length]
|
||||
if self.meta_orth_indx != self.sect_idx:
|
||||
if self.meta_orth_indx not in {NULL_INDEX, self.sect_idx}:
|
||||
raise ValueError('KF8 header has different Meta orth and '
|
||||
'section indices')
|
||||
|
||||
|
@ -9,10 +9,10 @@ import re, os
|
||||
|
||||
from lxml import html
|
||||
|
||||
from PyQt4.Qt import QApplication, QFontInfo, QSize, QWidget, QPlainTextEdit, \
|
||||
QToolBar, QVBoxLayout, QAction, QIcon, Qt, QTabWidget, QUrl, \
|
||||
QSyntaxHighlighter, QColor, QChar, QColorDialog, QMenu, QInputDialog, \
|
||||
QHBoxLayout
|
||||
from PyQt4.Qt import (QApplication, QFontInfo, QSize, QWidget, QPlainTextEdit,
|
||||
QToolBar, QVBoxLayout, QAction, QIcon, Qt, QTabWidget, QUrl,
|
||||
QSyntaxHighlighter, QColor, QChar, QColorDialog, QMenu, QInputDialog,
|
||||
QHBoxLayout, QKeySequence)
|
||||
from PyQt4.QtWebKit import QWebView, QWebPage
|
||||
|
||||
from calibre.ebooks.chardet import xml_to_unicode
|
||||
@ -32,6 +32,7 @@ class PageAction(QAction): # {{{
|
||||
type=Qt.QueuedConnection)
|
||||
self.page_action.changed.connect(self.update_state,
|
||||
type=Qt.QueuedConnection)
|
||||
self.update_state()
|
||||
|
||||
@property
|
||||
def page_action(self):
|
||||
@ -66,6 +67,12 @@ class EditorWidget(QWebView): # {{{
|
||||
|
||||
self.comments_pat = re.compile(r'<!--.*?-->', re.DOTALL)
|
||||
|
||||
extra_shortcuts = {
|
||||
'ToggleBold': 'Bold',
|
||||
'ToggleItalic': 'Italic',
|
||||
'ToggleUnderline': 'Underline',
|
||||
}
|
||||
|
||||
for wac, name, icon, text, checkable in [
|
||||
('ToggleBold', 'bold', 'format-text-bold', _('Bold'), True),
|
||||
('ToggleItalic', 'italic', 'format-text-italic', _('Italic'),
|
||||
@ -106,6 +113,9 @@ class EditorWidget(QWebView): # {{{
|
||||
]:
|
||||
ac = PageAction(wac, icon, text, checkable, self)
|
||||
setattr(self, 'action_'+name, ac)
|
||||
ss = extra_shortcuts.get(wac, None)
|
||||
if ss:
|
||||
ac.setShortcut(QKeySequence(getattr(QKeySequence, ss)))
|
||||
|
||||
self.action_color = QAction(QIcon(I('format-text-color')), _('Foreground color'),
|
||||
self)
|
||||
|
@ -6,8 +6,8 @@ __copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
|
||||
from PyQt4.Qt import QLineEdit, QAbstractListModel, Qt, \
|
||||
QApplication, QCompleter
|
||||
from PyQt4.Qt import (QLineEdit, QAbstractListModel, Qt,
|
||||
QApplication, QCompleter, QMetaObject)
|
||||
|
||||
from calibre.utils.icu import sort_key, lower
|
||||
from calibre.gui2 import NONE
|
||||
@ -182,14 +182,27 @@ class MultiCompleteComboBox(EnComboBox):
|
||||
def set_add_separator(self, what):
|
||||
self.lineEdit().set_add_separator(what)
|
||||
|
||||
|
||||
def show_initial_value(self, what):
|
||||
'''
|
||||
Show an initial value. Handle the case of the initial value being blank
|
||||
correctly (on Qt 4.8.0 having a blank value causes the first value from
|
||||
the completer to be shown, when the event loop runs).
|
||||
'''
|
||||
what = unicode(what)
|
||||
le = self.lineEdit()
|
||||
if not what.strip():
|
||||
QMetaObject.invokeMethod(self, 'clearEditText',
|
||||
Qt.QueuedConnection)
|
||||
else:
|
||||
self.setEditText(what)
|
||||
le.selectAll()
|
||||
|
||||
if __name__ == '__main__':
|
||||
from PyQt4.Qt import QDialog, QVBoxLayout
|
||||
app = QApplication([])
|
||||
d = QDialog()
|
||||
d.setLayout(QVBoxLayout())
|
||||
le = MultiCompleteLineEdit(d)
|
||||
le = MultiCompleteComboBox(d)
|
||||
d.layout().addWidget(le)
|
||||
le.all_items = ['one', 'otwo', 'othree', 'ooone', 'ootwo', 'oothree']
|
||||
d.exec_()
|
||||
|
@ -128,8 +128,7 @@ class TextDelegate(QStyledItemDelegate): # {{{
|
||||
for item in sorted(complete_items, key=sort_key):
|
||||
editor.addItem(item)
|
||||
ct = index.data(Qt.DisplayRole).toString()
|
||||
editor.setEditText(ct)
|
||||
editor.lineEdit().selectAll()
|
||||
editor.show_initial_value(ct)
|
||||
else:
|
||||
editor = EnLineEdit(parent)
|
||||
return editor
|
||||
@ -170,8 +169,7 @@ class CompleteDelegate(QStyledItemDelegate): # {{{
|
||||
for item in sorted(all_items, key=sort_key):
|
||||
editor.addItem(item)
|
||||
ct = index.data(Qt.DisplayRole).toString()
|
||||
editor.setEditText(ct)
|
||||
editor.lineEdit().selectAll()
|
||||
editor.show_initial_value(ct)
|
||||
else:
|
||||
editor = EnLineEdit(parent)
|
||||
return editor
|
||||
@ -190,8 +188,7 @@ class LanguagesDelegate(QStyledItemDelegate): # {{{
|
||||
editor = LanguagesEdit(parent=parent)
|
||||
editor.init_langs(index.model().db)
|
||||
ct = index.data(Qt.DisplayRole).toString()
|
||||
editor.setEditText(ct)
|
||||
editor.lineEdit().selectAll()
|
||||
editor.show_initial_value(ct)
|
||||
return editor
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
|
@ -882,6 +882,11 @@ class FullFetch(QDialog): # {{{
|
||||
self.covers_widget.chosen.connect(self.ok_clicked)
|
||||
self.stack.addWidget(self.covers_widget)
|
||||
|
||||
# Workaround for Qt 4.8.0 bug that causes the frame of the window to go
|
||||
# off the top of the screen if a max height is not set for the
|
||||
# QWebView. Seems to only happen on windows, but keep it for all
|
||||
# platforms just in case.
|
||||
self.identify_widget.comments_view.setMaximumHeight(500)
|
||||
self.resize(850, 550)
|
||||
|
||||
self.finished.connect(self.cleanup)
|
||||
|
@ -709,7 +709,7 @@ class DocumentView(QWebView): # {{{
|
||||
if self.manager is not None:
|
||||
self.manager.load_started()
|
||||
self.loading_url = QUrl.fromLocalFile(path)
|
||||
html = re.sub(r'<\s*title\s*/\s*>', '', html, flags=re.IGNORECASE)
|
||||
html = re.sub(ur'<\s*title\s*/\s*>', u'', html, flags=re.IGNORECASE)
|
||||
if has_svg:
|
||||
self.setContent(QByteArray(html.encode(path.encoding)), mt, QUrl.fromLocalFile(path))
|
||||
else:
|
||||
|
@ -204,7 +204,8 @@ class DevNull(object):
|
||||
pass
|
||||
NULL = DevNull()
|
||||
|
||||
def do_add(db, paths, one_book_per_directory, recurse, add_duplicates):
|
||||
def do_add(db, paths, one_book_per_directory, recurse, add_duplicates, otitle,
|
||||
oauthors, oisbn, otags, oseries, oseries_index):
|
||||
orig = sys.stdout
|
||||
#sys.stdout = NULL
|
||||
try:
|
||||
@ -231,6 +232,11 @@ def do_add(db, paths, one_book_per_directory, recurse, add_duplicates):
|
||||
mi.title = os.path.splitext(os.path.basename(book))[0]
|
||||
if not mi.authors:
|
||||
mi.authors = [_('Unknown')]
|
||||
for x in ('title', 'authors', 'isbn', 'tags', 'series'):
|
||||
val = locals()[x]
|
||||
if val: setattr(mi, x[1:], val)
|
||||
if oseries:
|
||||
mi.series_index = oseries_index
|
||||
|
||||
formats.append(format)
|
||||
metadata.append(mi)
|
||||
@ -302,39 +308,56 @@ the directory related options below.
|
||||
parser.add_option('-e', '--empty', action='store_true', default=False,
|
||||
help=_('Add an empty book (a book with no formats)'))
|
||||
parser.add_option('-t', '--title', default=None,
|
||||
help=_('Set the title of the added empty book'))
|
||||
help=_('Set the title of the added book(s)'))
|
||||
parser.add_option('-a', '--authors', default=None,
|
||||
help=_('Set the authors of the added empty book'))
|
||||
help=_('Set the authors of the added book(s)'))
|
||||
parser.add_option('-i', '--isbn', default=None,
|
||||
help=_('Set the ISBN of the added empty book'))
|
||||
help=_('Set the ISBN of the added book(s)'))
|
||||
parser.add_option('-T', '--tags', default=None,
|
||||
help=_('Set the tags of the added book(s)'))
|
||||
parser.add_option('-s', '--series', default=None,
|
||||
help=_('Set the series of the added book(s)'))
|
||||
parser.add_option('-S', '--series-index', default=1.0, type=float,
|
||||
help=_('Set the series number of the added book(s)'))
|
||||
|
||||
|
||||
return parser
|
||||
|
||||
def do_add_empty(db, title, authors, isbn):
|
||||
from calibre.ebooks.metadata import MetaInformation, string_to_authors
|
||||
def do_add_empty(db, title, authors, isbn, tags, series, series_index):
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
mi = MetaInformation(None)
|
||||
if title is not None:
|
||||
mi.title = title
|
||||
if authors:
|
||||
mi.authors = string_to_authors(authors)
|
||||
mi.authors = authors
|
||||
if isbn:
|
||||
mi.isbn = isbn
|
||||
if tags:
|
||||
mi.tags = tags
|
||||
if series:
|
||||
mi.series, mi.series_index = series, series_index
|
||||
db.import_book(mi, [])
|
||||
write_dirtied(db)
|
||||
send_message()
|
||||
|
||||
def command_add(args, dbpath):
|
||||
from calibre.ebooks.metadata import string_to_authors
|
||||
parser = add_option_parser()
|
||||
opts, args = parser.parse_args(sys.argv[:1] + args)
|
||||
aut = string_to_authors(opts.authors) if opts.authors else []
|
||||
tags = [x.strip() for x in opts.tags.split(',')] if opts.tags else []
|
||||
if opts.empty:
|
||||
do_add_empty(get_db(dbpath, opts), opts.title, opts.authors, opts.isbn)
|
||||
do_add_empty(get_db(dbpath, opts), opts.title, aut, opts.isbn, tags,
|
||||
opts.series, opts.series_index)
|
||||
return 0
|
||||
if len(args) < 2:
|
||||
parser.print_help()
|
||||
print
|
||||
print >>sys.stderr, _('You must specify at least one file to add')
|
||||
return 1
|
||||
do_add(get_db(dbpath, opts), args[1:], opts.one_book_per_directory, opts.recurse, opts.duplicates)
|
||||
do_add(get_db(dbpath, opts), args[1:], opts.one_book_per_directory,
|
||||
opts.recurse, opts.duplicates, opts.title, opts.author, opts.isbn,
|
||||
tags, opts.series, opts.series_index)
|
||||
return 0
|
||||
|
||||
def do_remove(db, ids):
|
||||
|
Loading…
x
Reference in New Issue
Block a user