mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
GwR wip tweak_epub
This commit is contained in:
commit
58fa93c903
BIN
resources/images/news/popscience.png
Normal file
BIN
resources/images/news/popscience.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 737 B |
BIN
resources/images/tweak_epub.png
Normal file
BIN
resources/images/tweak_epub.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
59
resources/recipes/popscience.recipe
Normal file
59
resources/recipes/popscience.recipe
Normal file
@ -0,0 +1,59 @@
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class AdvancedUserRecipe1282101454(BasicNewsRecipe):
|
||||
title = 'Popular Science'
|
||||
language = 'en'
|
||||
__author__ = 'TonytheBookworm'
|
||||
description = 'Popular Science'
|
||||
publisher = 'Popular Science'
|
||||
category = 'gadgets,science'
|
||||
oldest_article = 7 # change this if you want more current articles. I like to go a week in
|
||||
max_articles_per_feed = 100
|
||||
no_stylesheets = True
|
||||
remove_javascript = True
|
||||
|
||||
masthead_url = 'http://www.raytheon.com/newsroom/rtnwcm/groups/Public/documents/masthead/rtn08_popscidec_masthead.jpg'
|
||||
|
||||
remove_tags = [dict(name='div', attrs={'id':['toolbar','main_supplements']}),
|
||||
dict(name='span', attrs={'class':['comments']}),
|
||||
dict(name='div', attrs={'class':['relatedinfo related-right','node_navigation','content2']}),
|
||||
dict(name='ul', attrs={'class':['item-list clear-block']})]
|
||||
feeds = [
|
||||
|
||||
('Gadgets', 'http://www.popsci.com/full-feed/gadgets'),
|
||||
('Cars', 'http://www.popsci.com/full-feed/cars'),
|
||||
('Science', 'http://www.popsci.com/full-feed/science'),
|
||||
('Technology', 'http://www.popsci.com/full-feed/technology'),
|
||||
('DIY', 'http://www.popsci.com/full-feed/diy'),
|
||||
|
||||
]
|
||||
|
||||
|
||||
#The following will get read of the Gallery: links when found
|
||||
|
||||
def preprocess_html(self, soup) :
|
||||
print 'SOUP IS: ', soup
|
||||
weblinks = soup.findAll(['head','h2'])
|
||||
if weblinks is not None:
|
||||
for link in weblinks:
|
||||
if re.search('(Gallery)(:)',str(link)):
|
||||
|
||||
link.parent.extract()
|
||||
return soup
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -176,6 +176,7 @@ def get_metadata(stream, extract_cover=True):
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
mi.timestamp = None
|
||||
return mi
|
||||
|
||||
def get_quick_metadata(stream):
|
||||
|
@ -39,7 +39,7 @@ gprefs.defaults['action-layout-context-menu'] = (
|
||||
'Edit Metadata', 'Send To Device', 'Save To Disk',
|
||||
'Connect Share', 'Copy To Library', None,
|
||||
'Convert Books', 'View', 'Open Folder', 'Show Book Details',
|
||||
'Similar Books', None, 'Remove Books',
|
||||
'Similar Books', 'Tweak ePub', None, 'Remove Books',
|
||||
)
|
||||
|
||||
gprefs.defaults['action-layout-context-menu-device'] = (
|
||||
|
@ -5,30 +5,61 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from calibre.constants import iswindows, isosx
|
||||
from calibre.gui2 import error_dialog
|
||||
from calibre.gui2.actions import InterfaceAction
|
||||
from calibre.gui2.dialogs.tweak_epub import TweakEpub
|
||||
|
||||
class TweakEpubAction(InterfaceAction):
|
||||
|
||||
name = 'Tweak ePub'
|
||||
action_spec = (_('Edit ePub in situ'), 'document_open.png', None, None)
|
||||
#dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
action_spec = (_('Tweak ePub'), 'tweak_epub.png', 'Edit ePub in situ',
|
||||
_('T'))
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
self.qaction.triggered.connect(self.edit_epub_in_situ)
|
||||
print "gui2.actions.tweak_epub:TweakEpubAction.genesis()"
|
||||
self.qaction.triggered.connect(self._edit_epub_in_situ)
|
||||
|
||||
def initialization_complete(self):
|
||||
print "gui2.actions.tweak_epub:TweakEpubAction.initialization_complete()"
|
||||
def _edit_epub_in_situ(self, *args):
|
||||
|
||||
def library_changed(self, db):
|
||||
print "gui2.actions.tweak_epub:TweakEpubAction.library_changed()"
|
||||
# Assure exactly one row selected
|
||||
rows = self.gui.library_view.selectionModel().selectedRows()
|
||||
if not rows or len(rows) == 0:
|
||||
d = error_dialog(self.gui, _('Cannot tweak ePub'), _('No book selected'))
|
||||
d.exec_()
|
||||
return
|
||||
if len(rows) > 1:
|
||||
d = error_dialog(self.gui, _('Cannot tweak ePub'), _('Multiple books selected'))
|
||||
d.exec_()
|
||||
return
|
||||
|
||||
def location_selected(self, loc):
|
||||
print "gui2.actions.tweak_epub:TweakEpubAction.location_selected()"
|
||||
# Confirm 'EPUB' in formats
|
||||
row = rows[0].row()
|
||||
formats = self.gui.library_view.model().db.formats(row).upper().split(',')
|
||||
if not 'EPUB' in formats:
|
||||
d = error_dialog(self.gui, _('Cannot tweak ePub'), _('No EPUB available'))
|
||||
d.exec_()
|
||||
return
|
||||
|
||||
def shutting_down(self):
|
||||
print "gui2.actions.tweak_epub:TweakEpubAction.shutting_down()"
|
||||
path_to_epub = self.gui.library_view.model().db.format_abspath(row, 'EPUB')
|
||||
id = self._get_selected_id()
|
||||
|
||||
# Launch a modal dialog waiting for user to complete or cancel
|
||||
dlg = TweakEpub(self.gui, path_to_epub)
|
||||
if dlg.exec_() == dlg.Accepted:
|
||||
self._update_db(id, dlg._output)
|
||||
dlg.cleanup()
|
||||
|
||||
def _get_selected_id(self):
|
||||
rows = self.gui.library_view.selectionModel().selectedRows()
|
||||
return map(self.gui.library_view.model().id, rows)[0]
|
||||
|
||||
def _update_db(self, id, rebuilt):
|
||||
'''
|
||||
Update the calibre db with the tweaked epub
|
||||
'''
|
||||
print "gui2.actions.tweak_epub:TweakEpubAction._update_db()"
|
||||
print " updating id %d from %s" % (id, rebuilt)
|
||||
self.gui.library_view.model().db.add_format_with_hooks(id, 'EPUB', rebuilt, index_is_id=True)
|
||||
|
||||
def edit_epub_in_situ(self, *args):
|
||||
print "gui2.actions.tweak_epub:TweakEpubAction.edit_epub_in_situ()"
|
||||
|
129
src/calibre/gui2/dialogs/tweak_epub.py
Executable file
129
src/calibre/gui2/dialogs/tweak_epub.py
Executable file
@ -0,0 +1,129 @@
|
||||
#!/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__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, shutil, subprocess, sys
|
||||
from contextlib import closing
|
||||
from zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
|
||||
|
||||
from PyQt4 import QtGui
|
||||
from PyQt4.Qt import QDialog, SIGNAL
|
||||
|
||||
from calibre import prints
|
||||
from calibre.constants import iswindows, isosx, DEBUG
|
||||
from calibre.gui2.dialogs.tweak_epub_ui import Ui_Dialog
|
||||
from calibre.libunzip import extract as zipextract
|
||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||
|
||||
class TweakEpub(QDialog, Ui_Dialog):
|
||||
'''
|
||||
Display controls for tweaking ePubs
|
||||
|
||||
To do:
|
||||
- need way to kill file browser proc in cleanup()
|
||||
- Windows file browser launch
|
||||
- linux file browser launch
|
||||
'''
|
||||
|
||||
def __init__(self, parent, epub):
|
||||
QDialog.__init__(self, parent)
|
||||
|
||||
self._epub = epub
|
||||
self._exploded = None
|
||||
self._file_browser_proc = None
|
||||
self._output = None
|
||||
|
||||
# Run the dialog setup generated from tweak_epub.ui
|
||||
self.setupUi(self)
|
||||
|
||||
self.connect(self.cancel_button,
|
||||
SIGNAL("clicked()"),
|
||||
self.cancel)
|
||||
self.connect(self.explode_button,
|
||||
SIGNAL("clicked()"),
|
||||
self.explode)
|
||||
self.connect(self.rebuild_button,
|
||||
SIGNAL("clicked()"),
|
||||
self.rebuild)
|
||||
|
||||
# Position update dialog overlaying top left of app window
|
||||
parent_loc = parent.pos()
|
||||
self.move(parent_loc.x(),parent_loc.y())
|
||||
|
||||
def cancel(self):
|
||||
if DEBUG:
|
||||
prints("gui2.dialogs.tweak_epub:TweakEpub.cancel()")
|
||||
return QDialog.reject(self)
|
||||
|
||||
def cleanup(self):
|
||||
'''
|
||||
Kill the file browser
|
||||
'''
|
||||
if DEBUG:
|
||||
prints("gui2.dialogs.tweak_epub:TweakEpub.cleanup()")
|
||||
# Kill file browser proc
|
||||
if self._file_browser_proc:
|
||||
if DEBUG:
|
||||
prints(" killing file browser proc")
|
||||
#self._file_browser_proc.terminate()
|
||||
#self._file_browser_proc.kill()
|
||||
#self._file_browser_send_signal()
|
||||
#self._file_browser_proc = None
|
||||
|
||||
# Delete directory containing exploded ePub
|
||||
if self._exploded is not None:
|
||||
if DEBUG:
|
||||
prints(" removing exploded dir\n %s" % self._exploded)
|
||||
shutil.rmtree(self._exploded, ignore_errors=True)
|
||||
|
||||
|
||||
def display_exploded(self):
|
||||
'''
|
||||
Generic subprocess launch of native file browser
|
||||
User can use right-click to 'Open with ...'
|
||||
'''
|
||||
if DEBUG:
|
||||
prints("gui2.dialogs.tweak_epub:TweakEpub.display_exploded()")
|
||||
if isosx:
|
||||
cmd = 'open %s' % self._exploded
|
||||
elif iswindows:
|
||||
cmd = 'start explorer.exe /e,/root,%s' % self._exploded
|
||||
else:
|
||||
cmd = '<linux command to open native file browser>'
|
||||
|
||||
# *** Kovid - need a way of launching this process than can be killed in cleanup() ***
|
||||
self._file_browser_proc = subprocess.Popen(cmd, shell=True)
|
||||
|
||||
def explode(self):
|
||||
if DEBUG:
|
||||
prints("gui2.dialogs.tweak_epub:TweakEpub.explode()")
|
||||
if self._exploded is None:
|
||||
if DEBUG:
|
||||
prints(" exploding %s" % self._epub)
|
||||
self._exploded = PersistentTemporaryDirectory("_exploded", prefix='')
|
||||
zipextract(self._epub, self._exploded)
|
||||
self.display_exploded()
|
||||
self.rebuild_button.setEnabled(True)
|
||||
|
||||
def rebuild(self):
|
||||
if DEBUG:
|
||||
prints("gui2.dialogs.tweak_epub:TweakEpub.rebuild()")
|
||||
self._output = os.path.join(self._exploded, 'rebuilt.epub')
|
||||
with closing(ZipFile(self._output, 'w', compression=ZIP_DEFLATED)) as zf:
|
||||
# Write mimetype
|
||||
zf.write(os.path.join(self._exploded,'mimetype'), 'mimetype', compress_type=ZIP_STORED)
|
||||
# Write everything else
|
||||
exclude_files = ['.DS_Store','mimetype','iTunesMetadata.plist']
|
||||
for root, dirs, files in os.walk(self._exploded):
|
||||
for fn in files:
|
||||
if fn in exclude_files:
|
||||
continue
|
||||
absfn = os.path.join(root, fn)
|
||||
zfn = absfn[len(self._exploded) + len(os.sep):]
|
||||
zf.write(absfn, zfn)
|
||||
return QDialog.accept(self)
|
||||
|
86
src/calibre/gui2/dialogs/tweak_epub.ui
Normal file
86
src/calibre/gui2/dialogs/tweak_epub.ui
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::NonModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>161</width>
|
||||
<height>132</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Tweak ePub</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>141</width>
|
||||
<height>110</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="explode_button">
|
||||
<property name="statusTip">
|
||||
<string>Display contents of exploded ePub</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Explode ePub</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rebuild_button">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Rebuild ePub from exploded contents</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rebuild ePub</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancel_button">
|
||||
<property name="statusTip">
|
||||
<string>Discard changes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
x
Reference in New Issue
Block a user