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
a108ac7a58
@ -54,8 +54,12 @@ class CHMReader(CHMFile):
|
|||||||
self._extracted = False
|
self._extracted = False
|
||||||
|
|
||||||
# location of '.hhc' file, which is the CHM TOC.
|
# location of '.hhc' file, which is the CHM TOC.
|
||||||
self.root, ext = os.path.splitext(self.topics.lstrip('/'))
|
if self.topics is None:
|
||||||
self.hhc_path = self.root + ".hhc"
|
self.root, ext = os.path.splitext(self.home.lstrip('/'))
|
||||||
|
self.hhc_path = self.root + ".hhc"
|
||||||
|
else:
|
||||||
|
self.root, ext = os.path.splitext(self.topics.lstrip('/'))
|
||||||
|
self.hhc_path = self.root + ".hhc"
|
||||||
|
|
||||||
def _parse_toc(self, ul, basedir=os.getcwdu()):
|
def _parse_toc(self, ul, basedir=os.getcwdu()):
|
||||||
toc = TOC(play_order=self._playorder, base_path=basedir, text='')
|
toc = TOC(play_order=self._playorder, base_path=basedir, text='')
|
||||||
|
@ -119,12 +119,12 @@ class JsonCodec(object):
|
|||||||
for item in js:
|
for item in js:
|
||||||
book = book_class(prefix, item.get('lpath', None))
|
book = book_class(prefix, item.get('lpath', None))
|
||||||
for key in item.keys():
|
for key in item.keys():
|
||||||
if key == 'classifiers':
|
|
||||||
key = 'identifiers'
|
|
||||||
meta = self.decode_metadata(key, item[key])
|
meta = self.decode_metadata(key, item[key])
|
||||||
if key == 'user_metadata':
|
if key == 'user_metadata':
|
||||||
book.set_all_user_metadata(meta)
|
book.set_all_user_metadata(meta)
|
||||||
else:
|
else:
|
||||||
|
if key == 'classifiers':
|
||||||
|
key = 'identifiers'
|
||||||
setattr(book, key, meta)
|
setattr(book, key, meta)
|
||||||
booklist.append(book)
|
booklist.append(book)
|
||||||
except:
|
except:
|
||||||
@ -132,6 +132,8 @@ class JsonCodec(object):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
def decode_metadata(self, key, value):
|
def decode_metadata(self, key, value):
|
||||||
|
if key == 'classifiers':
|
||||||
|
key = 'identifiers'
|
||||||
if key == 'user_metadata':
|
if key == 'user_metadata':
|
||||||
for k in value:
|
for k in value:
|
||||||
if value[k]['datatype'] == 'datetime':
|
if value[k]['datatype'] == 'datetime':
|
||||||
|
@ -10,7 +10,7 @@ from Queue import Queue
|
|||||||
|
|
||||||
from PyQt4.Qt import QPixmap, QSize, QWidget, Qt, pyqtSignal, QUrl, \
|
from PyQt4.Qt import QPixmap, QSize, QWidget, Qt, pyqtSignal, QUrl, \
|
||||||
QPropertyAnimation, QEasingCurve, QThread, QApplication, QFontInfo, \
|
QPropertyAnimation, QEasingCurve, QThread, QApplication, QFontInfo, \
|
||||||
QSizePolicy, QPainter, QRect, pyqtProperty, QLayout, QPalette
|
QSizePolicy, QPainter, QRect, pyqtProperty, QLayout, QPalette, QMenu
|
||||||
from PyQt4.QtWebKit import QWebView
|
from PyQt4.QtWebKit import QWebView
|
||||||
|
|
||||||
from calibre import fit_image, prepare_string_for_xml
|
from calibre import fit_image, prepare_string_for_xml
|
||||||
@ -18,7 +18,7 @@ from calibre.gui2.widgets import IMAGE_EXTENSIONS
|
|||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.constants import preferred_encoding
|
from calibre.constants import preferred_encoding
|
||||||
from calibre.library.comments import comments_to_html
|
from calibre.library.comments import comments_to_html
|
||||||
from calibre.gui2 import config, open_local_file, open_url
|
from calibre.gui2 import config, open_local_file, open_url, pixmap_to_data
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
|
|
||||||
# render_rows(data) {{{
|
# render_rows(data) {{{
|
||||||
@ -70,6 +70,7 @@ def render_rows(data):
|
|||||||
|
|
||||||
class CoverView(QWidget): # {{{
|
class CoverView(QWidget): # {{{
|
||||||
|
|
||||||
|
cover_changed = pyqtSignal(object, object)
|
||||||
|
|
||||||
def __init__(self, vertical, parent=None):
|
def __init__(self, vertical, parent=None):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
@ -151,6 +152,35 @@ class CoverView(QWidget): # {{{
|
|||||||
fset=setCurrentPixmapSize
|
fset=setCurrentPixmapSize
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def contextMenuEvent(self, ev):
|
||||||
|
cm = QMenu(self)
|
||||||
|
paste = cm.addAction(_('Paste Cover'))
|
||||||
|
copy = cm.addAction(_('Copy Cover'))
|
||||||
|
if not QApplication.instance().clipboard().mimeData().hasImage():
|
||||||
|
paste.setEnabled(False)
|
||||||
|
copy.triggered.connect(self.copy_to_clipboard)
|
||||||
|
paste.triggered.connect(self.paste_from_clipboard)
|
||||||
|
cm.exec_(ev.globalPos())
|
||||||
|
|
||||||
|
def copy_to_clipboard(self):
|
||||||
|
QApplication.instance().clipboard().setPixmap(self.pixmap)
|
||||||
|
|
||||||
|
def paste_from_clipboard(self):
|
||||||
|
cb = QApplication.instance().clipboard()
|
||||||
|
pmap = cb.pixmap()
|
||||||
|
if pmap.isNull() and cb.supportsSelection():
|
||||||
|
pmap = cb.pixmap(cb.Selection)
|
||||||
|
if not pmap.isNull():
|
||||||
|
self.pixmap = pmap
|
||||||
|
self.do_layout()
|
||||||
|
self.update()
|
||||||
|
if not config['disable_animations']:
|
||||||
|
self.animation.start()
|
||||||
|
id_ = self.data.get('id', None)
|
||||||
|
if id_ is not None:
|
||||||
|
self.cover_changed.emit(id_,
|
||||||
|
pixmap_to_data(pmap))
|
||||||
|
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
@ -362,7 +392,9 @@ class BookDetails(QWidget): # {{{
|
|||||||
# Drag 'n drop {{{
|
# Drag 'n drop {{{
|
||||||
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS
|
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS
|
||||||
files_dropped = pyqtSignal(object, object)
|
files_dropped = pyqtSignal(object, object)
|
||||||
|
cover_changed = pyqtSignal(object, object)
|
||||||
|
|
||||||
|
# application/x-moz-file-promise-url
|
||||||
@classmethod
|
@classmethod
|
||||||
def paths_from_event(cls, event):
|
def paths_from_event(cls, event):
|
||||||
'''
|
'''
|
||||||
@ -399,6 +431,7 @@ class BookDetails(QWidget): # {{{
|
|||||||
self.setLayout(self._layout)
|
self.setLayout(self._layout)
|
||||||
|
|
||||||
self.cover_view = CoverView(vertical, self)
|
self.cover_view = CoverView(vertical, self)
|
||||||
|
self.cover_view.cover_changed.connect(self.cover_changed.emit)
|
||||||
self._layout.addWidget(self.cover_view)
|
self._layout.addWidget(self.cover_view)
|
||||||
self.book_info = BookInfo(vertical, self)
|
self.book_info = BookInfo(vertical, self)
|
||||||
self._layout.addWidget(self.book_info)
|
self._layout.addWidget(self.book_info)
|
||||||
|
@ -264,10 +264,8 @@ class Scheduler(QObject):
|
|||||||
ids = list(self.recipe_model.db.tags_older_than(_('News'),
|
ids = list(self.recipe_model.db.tags_older_than(_('News'),
|
||||||
delta))
|
delta))
|
||||||
except:
|
except:
|
||||||
# Should never happen
|
# Happens if library is being switched
|
||||||
ids = []
|
ids = []
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
if ids:
|
if ids:
|
||||||
if ids:
|
if ids:
|
||||||
self.delete_old_news.emit(ids)
|
self.delete_old_news.emit(ids)
|
||||||
|
@ -262,6 +262,8 @@ class LayoutMixin(object): # {{{
|
|||||||
self.status_bar.initialize(self.system_tray_icon)
|
self.status_bar.initialize(self.system_tray_icon)
|
||||||
self.book_details.show_book_info.connect(self.iactions['Show Book Details'].show_book_info)
|
self.book_details.show_book_info.connect(self.iactions['Show Book Details'].show_book_info)
|
||||||
self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book)
|
self.book_details.files_dropped.connect(self.iactions['Add Books'].files_dropped_on_book)
|
||||||
|
self.book_details.cover_changed.connect(self.bd_cover_changed,
|
||||||
|
type=Qt.QueuedConnection)
|
||||||
self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id)
|
self.book_details.open_containing_folder.connect(self.iactions['View'].view_folder_for_id)
|
||||||
self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id)
|
self.book_details.view_specific_format.connect(self.iactions['View'].view_format_by_id)
|
||||||
|
|
||||||
@ -272,6 +274,10 @@ class LayoutMixin(object): # {{{
|
|||||||
self.library_view.currentIndex())
|
self.library_view.currentIndex())
|
||||||
self.library_view.setFocus(Qt.OtherFocusReason)
|
self.library_view.setFocus(Qt.OtherFocusReason)
|
||||||
|
|
||||||
|
def bd_cover_changed(self, id_, cdata):
|
||||||
|
self.library_view.model().db.set_cover(id_, cdata)
|
||||||
|
if self.cover_flow:
|
||||||
|
self.cover_flow.dataChanged()
|
||||||
|
|
||||||
def save_layout_state(self):
|
def save_layout_state(self):
|
||||||
for x in ('library', 'memory', 'card_a', 'card_b'):
|
for x in ('library', 'memory', 'card_a', 'card_b'):
|
||||||
|
@ -1135,7 +1135,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
collapse_model = 'partition'
|
collapse_model = 'partition'
|
||||||
collapse_template = tweaks['categories_collapsed_popularity_template']
|
collapse_template = tweaks['categories_collapsed_popularity_template']
|
||||||
|
|
||||||
def process_one_node(category, state_map):
|
def process_one_node(category, state_map): # {{{
|
||||||
collapse_letter = None
|
collapse_letter = None
|
||||||
category_index = self.createIndex(category.row(), 0, category)
|
category_index = self.createIndex(category.row(), 0, category)
|
||||||
category_node = category_index.internalPointer()
|
category_node = category_index.internalPointer()
|
||||||
@ -1277,6 +1277,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
# This id_set must not be None
|
# This id_set must not be None
|
||||||
node_parent.id_set |= tag.id_set
|
node_parent.id_set |= tag.id_set
|
||||||
return
|
return
|
||||||
|
# }}}
|
||||||
|
|
||||||
for category in self.category_nodes:
|
for category in self.category_nodes:
|
||||||
if len(category.children) > 0:
|
if len(category.children) > 0:
|
||||||
@ -2079,6 +2080,10 @@ class TagBrowserWidget(QWidget): # {{{
|
|||||||
_('Add your own categories to the Tag Browser'))
|
_('Add your own categories to the Tag Browser'))
|
||||||
parent.edit_categories.setStatusTip(parent.edit_categories.toolTip())
|
parent.edit_categories.setStatusTip(parent.edit_categories.toolTip())
|
||||||
|
|
||||||
|
# self.leak_test_timer = QTimer(self)
|
||||||
|
# self.leak_test_timer.timeout.connect(self.test_for_leak)
|
||||||
|
# self.leak_test_timer.start(5000)
|
||||||
|
|
||||||
def set_pane_is_visible(self, to_what):
|
def set_pane_is_visible(self, to_what):
|
||||||
self.tags_view.set_pane_is_visible(to_what)
|
self.tags_view.set_pane_is_visible(to_what)
|
||||||
|
|
||||||
@ -2140,5 +2145,13 @@ class TagBrowserWidget(QWidget): # {{{
|
|||||||
def not_found_label_timer_event(self):
|
def not_found_label_timer_event(self):
|
||||||
self.not_found_label.setVisible(False)
|
self.not_found_label.setVisible(False)
|
||||||
|
|
||||||
|
def test_for_leak(self):
|
||||||
|
from calibre.utils.mem import memory
|
||||||
|
import gc
|
||||||
|
before = memory()
|
||||||
|
self.tags_view.recount()
|
||||||
|
for i in xrange(3): gc.collect()
|
||||||
|
print 'Used memory:', memory(before)/(1024.), 'KB'
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -236,8 +236,8 @@ class ImageDropMixin(object): # {{{
|
|||||||
|
|
||||||
def contextMenuEvent(self, ev):
|
def contextMenuEvent(self, ev):
|
||||||
cm = QMenu(self)
|
cm = QMenu(self)
|
||||||
copy = cm.addAction(_('Copy Image'))
|
paste = cm.addAction(_('Paste Cover'))
|
||||||
paste = cm.addAction(_('Paste Image'))
|
copy = cm.addAction(_('Copy Cover'))
|
||||||
if not QApplication.instance().clipboard().mimeData().hasImage():
|
if not QApplication.instance().clipboard().mimeData().hasImage():
|
||||||
paste.setEnabled(False)
|
paste.setEnabled(False)
|
||||||
copy.triggered.connect(self.copy_to_clipboard)
|
copy.triggered.connect(self.copy_to_clipboard)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user