mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge
This commit is contained in:
commit
276ae23670
@ -11,7 +11,7 @@ import subprocess, tempfile, os, time
|
|||||||
from setup import Command, installer_name
|
from setup import Command, installer_name
|
||||||
from setup.build_environment import HOST, PROJECT
|
from setup.build_environment import HOST, PROJECT
|
||||||
|
|
||||||
BASE_RSYNC = 'rsync -avz --delete'.split()
|
BASE_RSYNC = ['rsync', '-e', 'ssh -x', '-avz', '--delete']
|
||||||
EXCLUDES = []
|
EXCLUDES = []
|
||||||
for x in [
|
for x in [
|
||||||
'src/calibre/plugins', 'src/calibre/manual', 'src/calibre/trac',
|
'src/calibre/plugins', 'src/calibre/manual', 'src/calibre/trac',
|
||||||
|
@ -182,6 +182,7 @@ class TOC(list):
|
|||||||
except:
|
except:
|
||||||
play_order = 1
|
play_order = 1
|
||||||
href = fragment = text = None
|
href = fragment = text = None
|
||||||
|
nd = dest
|
||||||
nl = nl_path(np)
|
nl = nl_path(np)
|
||||||
if nl:
|
if nl:
|
||||||
nl = nl[0]
|
nl = nl[0]
|
||||||
@ -190,17 +191,14 @@ class TOC(list):
|
|||||||
text += etree.tostring(txt, method='text',
|
text += etree.tostring(txt, method='text',
|
||||||
encoding=unicode, with_tail=False)
|
encoding=unicode, with_tail=False)
|
||||||
content = content_path(np)
|
content = content_path(np)
|
||||||
if not content or not text:
|
if content and text:
|
||||||
return
|
content = content[0]
|
||||||
content = content[0]
|
src = get_attr(content, attr='src')
|
||||||
src = get_attr(content, attr='src')
|
if src:
|
||||||
if src is None:
|
purl = urlparse(unquote(content.get('src')))
|
||||||
return
|
href, fragment = purl[2], purl[5]
|
||||||
|
nd = dest.add_item(href, fragment, text)
|
||||||
purl = urlparse(unquote(content.get('src')))
|
nd.play_order = play_order
|
||||||
href, fragment = purl[2], purl[5]
|
|
||||||
nd = dest.add_item(href, fragment, text)
|
|
||||||
nd.play_order = play_order
|
|
||||||
|
|
||||||
for c in np_path(np):
|
for c in np_path(np):
|
||||||
process_navpoint(c, nd)
|
process_navpoint(c, nd)
|
||||||
|
@ -192,14 +192,15 @@ class EditMetadataAction(InterfaceAction):
|
|||||||
_('At least two books must be selected for merging'),
|
_('At least two books must be selected for merging'),
|
||||||
show=True)
|
show=True)
|
||||||
dest_id, src_books, src_ids = self.books_to_merge(rows)
|
dest_id, src_books, src_ids = self.books_to_merge(rows)
|
||||||
|
title = self.gui.library_view.model().db.title(dest_id, index_is_id=True)
|
||||||
if safe_merge:
|
if safe_merge:
|
||||||
if not confirm('<p>'+_(
|
if not confirm('<p>'+_(
|
||||||
'Book formats and metadata from the selected books '
|
'Book formats and metadata from the selected books '
|
||||||
'will be added to the <b>first selected book.</b> '
|
'will be added to the <b>first selected book</b> (%s). '
|
||||||
'ISBN will <i>not</i> be merged.<br><br> '
|
'ISBN will <i>not</i> be merged.<br><br> '
|
||||||
'The second and subsequently selected books will not '
|
'The second and subsequently selected books will not '
|
||||||
'be deleted or changed.<br><br>'
|
'be deleted or changed.<br><br>'
|
||||||
'Please confirm you want to proceed.')
|
'Please confirm you want to proceed.')%title
|
||||||
+'</p>', 'merge_books_safe', self.gui):
|
+'</p>', 'merge_books_safe', self.gui):
|
||||||
return
|
return
|
||||||
self.add_formats(dest_id, src_books)
|
self.add_formats(dest_id, src_books)
|
||||||
@ -207,14 +208,14 @@ class EditMetadataAction(InterfaceAction):
|
|||||||
else:
|
else:
|
||||||
if not confirm('<p>'+_(
|
if not confirm('<p>'+_(
|
||||||
'Book formats and metadata from the selected books will be merged '
|
'Book formats and metadata from the selected books will be merged '
|
||||||
'into the <b>first selected book</b>. '
|
'into the <b>first selected book</b> (%s). '
|
||||||
'ISBN will <i>not</i> be merged.<br><br>'
|
'ISBN will <i>not</i> be merged.<br><br>'
|
||||||
'After merger the second and '
|
'After merger the second and '
|
||||||
'subsequently selected books will be <b>deleted</b>. <br><br>'
|
'subsequently selected books will be <b>deleted</b>. <br><br>'
|
||||||
'All book formats of the first selected book will be kept '
|
'All book formats of the first selected book will be kept '
|
||||||
'and any duplicate formats in the second and subsequently selected books '
|
'and any duplicate formats in the second and subsequently selected books '
|
||||||
'will be permanently <b>deleted</b> from your computer.<br><br> '
|
'will be permanently <b>deleted</b> from your computer.<br><br> '
|
||||||
'Are you <b>sure</b> you want to proceed?')
|
'Are you <b>sure</b> you want to proceed?')%title
|
||||||
+'</p>', 'merge_books', self.gui):
|
+'</p>', 'merge_books', self.gui):
|
||||||
return
|
return
|
||||||
if len(rows)>5:
|
if len(rows)>5:
|
||||||
|
@ -358,10 +358,11 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
|
|
||||||
def toc_clicked(self, index):
|
def toc_clicked(self, index):
|
||||||
item = self.toc_model.itemFromIndex(index)
|
item = self.toc_model.itemFromIndex(index)
|
||||||
url = QUrl.fromLocalFile(item.abspath)
|
if item.abspath is not None:
|
||||||
if item.fragment:
|
url = QUrl.fromLocalFile(item.abspath)
|
||||||
url.setFragment(item.fragment)
|
if item.fragment:
|
||||||
self.link_clicked(url)
|
url.setFragment(item.fragment)
|
||||||
|
self.link_clicked(url)
|
||||||
|
|
||||||
def selection_changed(self, selected_text):
|
def selection_changed(self, selected_text):
|
||||||
self.selected_text = selected_text.strip()
|
self.selected_text = selected_text.strip()
|
||||||
|
@ -5,7 +5,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import sys
|
import sys, os
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from calibre.library.server import server_config as config
|
from calibre.library.server import server_config as config
|
||||||
@ -63,15 +63,47 @@ The OPDS interface is advertised via BonJour automatically.
|
|||||||
' work in all environments.'))
|
' work in all environments.'))
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
|
||||||
|
try:
|
||||||
|
pid = os.fork()
|
||||||
|
if pid > 0:
|
||||||
|
# exit first parent
|
||||||
|
sys.exit(0)
|
||||||
|
except OSError, e:
|
||||||
|
print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# decouple from parent environment
|
||||||
|
os.chdir("/")
|
||||||
|
os.setsid()
|
||||||
|
os.umask(0)
|
||||||
|
|
||||||
|
# do second fork
|
||||||
|
try:
|
||||||
|
pid = os.fork()
|
||||||
|
if pid > 0:
|
||||||
|
# exit from second parent
|
||||||
|
sys.exit(0)
|
||||||
|
except OSError, e:
|
||||||
|
print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Redirect standard file descriptors.
|
||||||
|
si = file(stdin, 'r')
|
||||||
|
so = file(stdout, 'a+')
|
||||||
|
se = file(stderr, 'a+', 0)
|
||||||
|
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||||
|
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||||
|
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
from calibre.library.database2 import LibraryDatabase2
|
from calibre.library.database2 import LibraryDatabase2
|
||||||
parser = option_parser()
|
parser = option_parser()
|
||||||
opts, args = parser.parse_args(args)
|
opts, args = parser.parse_args(args)
|
||||||
if opts.daemonize and not iswindows:
|
if opts.daemonize and not iswindows:
|
||||||
from cherrypy.process.plugins import Daemonizer
|
daemonize()
|
||||||
d = Daemonizer(cherrypy.engine)
|
|
||||||
d.subscribe()
|
|
||||||
if opts.pidfile is not None:
|
if opts.pidfile is not None:
|
||||||
from cherrypy.process.plugins import PIDFile
|
from cherrypy.process.plugins import PIDFile
|
||||||
PIDFile(cherrypy.engine, opts.pidfile).subscribe()
|
PIDFile(cherrypy.engine, opts.pidfile).subscribe()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user