mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
fff3cb147a
@ -20,7 +20,7 @@
|
||||
<script type="text/javascript"
|
||||
src="{prefix}/static/jquery.multiselect.min.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="{prefix}/static/stacktrace.js"></script>
|
||||
<script type="text/javascript" src="{prefix}/static/browse/browse.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@ -129,7 +129,13 @@ function toplevel() {
|
||||
// }}}
|
||||
|
||||
function render_error(msg) {
|
||||
return '<div class="ui-widget"><div class="ui-state-error ui-corner-all" style="padding: 0pt 0.7em"><p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: 0.3em"> </span><strong>Error: </strong>'+msg+"</p></div></div>"
|
||||
var st = "";
|
||||
try {
|
||||
var st = printStackTrace();
|
||||
st = st.join('\n\n');
|
||||
} catch(e) {
|
||||
}
|
||||
return '<div class="ui-widget"><div class="ui-state-error ui-corner-all" style="padding: 0pt 0.7em"><p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: 0.3em"> </span><strong>Error: </strong>'+msg+"<pre>"+st+"</pre></p></div></div>"
|
||||
}
|
||||
|
||||
// Category feed {{{
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization">
|
||||
<String Id="AdvancedWelcomeEulaDlgDescriptionPerUser">If you are upgrading from a {app} version older than 0.6.17, please uninstall {app} first. Click Advanced to change installation settings.</String>
|
||||
<String Id="AdvancedWelcomeEulaDlgDescriptionPerUser">Click Advanced to change installation settings.</String>
|
||||
<String Id="ProgressTextFileCost">Computing space requirements, this may take upto five minutes...</String>
|
||||
<String Id="ProgressTextCostInitialize">Computing space requirements, this may take upto five minutes...</String>
|
||||
<String Id="ProgressTextCostFinalize">Computing space requirements, this may take upto five minutes...</String>
|
||||
|
@ -8,8 +8,8 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import sys, os, shutil, glob, py_compile, subprocess, re, zipfile, time
|
||||
|
||||
from setup import Command, modules, functions, basenames, __version__, \
|
||||
__appname__
|
||||
from setup import (Command, modules, functions, basenames, __version__,
|
||||
__appname__)
|
||||
from setup.build_environment import msvc, MT, RC
|
||||
from setup.installer.windows.wix import WixMixIn
|
||||
|
||||
@ -20,6 +20,7 @@ LIBUNRAR = 'C:\\Program Files\\UnrarDLL\\unrar.dll'
|
||||
SW = r'C:\cygwin\home\kovid\sw'
|
||||
IMAGEMAGICK = os.path.join(SW, 'build', 'ImageMagick-6.6.6',
|
||||
'VisualMagick', 'bin')
|
||||
CRT = r'C:\Microsoft.VC90.CRT'
|
||||
|
||||
VERSION = re.sub('[a-z]\d+', '', __version__)
|
||||
WINVER = VERSION+'.0'
|
||||
@ -72,7 +73,7 @@ class Win32Freeze(Command, WixMixIn):
|
||||
self.lib_dir = self.j(self.base, 'Lib')
|
||||
self.pylib = self.j(self.base, 'pylib.zip')
|
||||
self.dll_dir = self.j(self.base, 'DLLs')
|
||||
self.plugins_dir = os.path.join(self.base, 'plugins')
|
||||
self.plugins_dir = os.path.join(self.base, 'plugins2')
|
||||
|
||||
self.initbase()
|
||||
self.build_launchers()
|
||||
@ -81,8 +82,33 @@ class Win32Freeze(Command, WixMixIn):
|
||||
self.embed_manifests()
|
||||
self.install_site_py()
|
||||
self.archive_lib_dir()
|
||||
self.remove_CRT_from_manifests()
|
||||
self.create_installer()
|
||||
|
||||
def remove_CRT_from_manifests(self):
|
||||
'''
|
||||
The dependency on the CRT is removed from the manifests of all DLLs.
|
||||
This allows the CRT loaded by the .exe files to be used instead.
|
||||
'''
|
||||
search_pat = re.compile(r'(?is)<dependency>.*Microsoft\.VC\d+\.CRT')
|
||||
repl_pat = re.compile(
|
||||
r'(?is)<dependency>.*?Microsoft\.VC\d+\.CRT.*?</dependency>')
|
||||
|
||||
for dll in glob.glob(self.j(self.dll_dir, '*.dll')):
|
||||
bn = self.b(dll)
|
||||
with open(dll, 'rb') as f:
|
||||
raw = f.read()
|
||||
match = search_pat.search(raw)
|
||||
if match is None:
|
||||
continue
|
||||
self.info('Removing CRT dependency from manifest of: %s'%bn)
|
||||
# Blank out the bytes corresponding to the dependency specification
|
||||
nraw = repl_pat.sub(lambda m: b' '*len(m.group()), raw)
|
||||
if len(nraw) != len(raw):
|
||||
raise Exception('Something went wrong with %s'%bn)
|
||||
with open(dll, 'wb') as f:
|
||||
f.write(nraw)
|
||||
|
||||
def initbase(self):
|
||||
if self.e(self.base):
|
||||
shutil.rmtree(self.base)
|
||||
@ -103,6 +129,9 @@ class Win32Freeze(Command, WixMixIn):
|
||||
def freeze(self):
|
||||
shutil.copy2(self.j(self.src_root, 'LICENSE'), self.base)
|
||||
|
||||
self.info('Adding CRT')
|
||||
shutil.copytree(CRT, self.j(self.base, os.path.basename(CRT)))
|
||||
|
||||
self.info('Adding resources...')
|
||||
tgt = self.j(self.base, 'resources')
|
||||
if os.path.exists(tgt):
|
||||
@ -197,6 +226,10 @@ class Win32Freeze(Command, WixMixIn):
|
||||
if os.path.exists(tg):
|
||||
shutil.rmtree(tg)
|
||||
shutil.copytree(imfd, tg)
|
||||
for dirpath, dirnames, filenames in os.walk(tdir):
|
||||
for x in filenames:
|
||||
if not x.endswith('.dll'):
|
||||
os.remove(self.j(dirpath, x))
|
||||
|
||||
print
|
||||
print 'Adding third party dependencies'
|
||||
|
@ -92,7 +92,7 @@ def aliasmbcs():
|
||||
|
||||
def add_calibre_vars():
|
||||
sys.resources_location = os.path.join(sys.app_dir, 'resources')
|
||||
sys.extensions_location = os.path.join(sys.app_dir, 'plugins')
|
||||
sys.extensions_location = os.path.join(sys.app_dir, 'plugins2')
|
||||
|
||||
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
|
||||
if dv and os.path.exists(dv):
|
||||
|
@ -11,6 +11,10 @@
|
||||
SummaryCodepage='1252' />
|
||||
|
||||
<Media Id="1" Cabinet="{app}.cab" CompressionLevel="{compression}" EmbedCab="yes" />
|
||||
<!-- The following line ensures that DLLs are replaced even if their version is the same as before. This
|
||||
is necessary because of the manifest nuking that was part of making calibre isolated. But I think it
|
||||
is more rigorous anyway. -->
|
||||
<Property Id='REINSTALLMODE' Value='emus'/>
|
||||
|
||||
<Upgrade Id="{upgrade_code}">
|
||||
<UpgradeVersion Maximum="{version}"
|
||||
@ -33,7 +37,6 @@
|
||||
</Property>
|
||||
|
||||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||||
<Merge Id="VCRedist" SourceFile="{crt_msm}" DiskId="1" Language="0"/>
|
||||
<Directory Id='ProgramFilesFolder' Name='PFiles'>
|
||||
<Directory Id='APPLICATIONFOLDER' Name='{app}' />
|
||||
</Directory>
|
||||
@ -100,10 +103,6 @@
|
||||
<ComponentRef Id="RememberInstallDir"/>
|
||||
</Feature>
|
||||
|
||||
<Feature Id="VCRedist" Title="Visual C++ 8.0 Runtime" AllowAdvertise="no" Display="hidden" Level="1">
|
||||
<MergeRef Id="VCRedist"/>
|
||||
</Feature>
|
||||
|
||||
<Feature Id="FSMS" Title="Start menu shortcuts" Level="1"
|
||||
Description="Program shortcuts installed in the Start Menu">
|
||||
<ComponentRef Id="StartMenuShortcuts"/>
|
||||
@ -149,12 +148,13 @@
|
||||
Set default folder name and allow only per machine installs.
|
||||
For a per-machine installation, the default installation location
|
||||
will be [ProgramFilesFolder][ApplicationFolderName] and the user
|
||||
will be able to change it in the setup UI. This is because the installer
|
||||
has to install the VC90 merge module into the system winsxs folder for python
|
||||
to work, so per user installs are impossible anyway.
|
||||
will be able to change it in the setup UI. This is no longer necessary
|
||||
(i.e. per user installs should work) but left this way as I
|
||||
dont want to deal with the complications
|
||||
-->
|
||||
<Property Id="ApplicationFolderName" Value="Calibre2" />
|
||||
<Property Id="WixAppFolder" Value="WixPerMachineFolder" />
|
||||
<Property Id="ALLUSERS" Value="1" />
|
||||
<WixVariable Id="WixUISupportPerUser" Value="0" />
|
||||
|
||||
<!-- Add option to launch calibre after install -->
|
||||
|
@ -35,7 +35,6 @@ class WixMixIn:
|
||||
exe_map = self.smap,
|
||||
main_icon = self.j(self.src_root, 'icons', 'library.ico'),
|
||||
web_icon = self.j(self.src_root, 'icons', 'web.ico'),
|
||||
crt_msm = self.j(self.SW, 'Microsoft_VC90_CRT_x86.msm')
|
||||
)
|
||||
template = open(self.j(self.d(__file__), 'en-us.xml'),
|
||||
'rb').read()
|
||||
|
@ -11,7 +11,7 @@ import os, shutil, traceback, textwrap, time, codecs
|
||||
from Queue import Empty
|
||||
|
||||
from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation
|
||||
from calibre import extract, CurrentDir, prints
|
||||
from calibre import extract, CurrentDir, prints, walk
|
||||
from calibre.constants import filesystem_encoding
|
||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||
from calibre.utils.ipc.server import Server
|
||||
@ -27,6 +27,11 @@ def extract_comic(path_to_comic_file):
|
||||
# names
|
||||
tdir = tdir.decode(filesystem_encoding)
|
||||
extract(path_to_comic_file, tdir)
|
||||
for x in walk(tdir):
|
||||
bn = os.path.basename(x)
|
||||
nbn = bn.replace('#', '_')
|
||||
if nbn != bn:
|
||||
os.rename(x, os.path.join(os.path.dirname(x), nbn))
|
||||
return tdir
|
||||
|
||||
def find_pages(dir, sort_on_mtime=False, verbose=False):
|
||||
@ -362,6 +367,7 @@ class ComicInput(InputFormatPlugin):
|
||||
if not line:
|
||||
continue
|
||||
fname, title = line.partition(':')[0], line.partition(':')[-1]
|
||||
fname = fname.replace('#', '_')
|
||||
fname = os.path.join(tdir, *fname.split('/'))
|
||||
if not title:
|
||||
title = os.path.basename(fname).rpartition('.')[0]
|
||||
|
@ -154,13 +154,16 @@ _proceed_memory = []
|
||||
class ProceedNotification(MessageBox): # {{{
|
||||
|
||||
def __init__(self, callback, payload, html_log, log_viewer_title, title, msg,
|
||||
det_msg='', show_copy_button=False, parent=None):
|
||||
det_msg='', show_copy_button=False, parent=None,
|
||||
cancel_callback=None):
|
||||
'''
|
||||
A non modal popup that notifies the user that a background task has
|
||||
been completed.
|
||||
|
||||
:param callback: A callable that is called with payload if the user
|
||||
asks to proceed. Note that this is always called in the GUI thread
|
||||
asks to proceed. Note that this is always called in the GUI thread.
|
||||
:param cancel_callback: A callable that is called with the payload if
|
||||
the users asks not to proceed.
|
||||
:param payload: Arbitrary object, passed to callback
|
||||
:param html_log: An HTML or plain text log
|
||||
:param log_viewer_title: The title for the log viewer window
|
||||
@ -181,7 +184,7 @@ class ProceedNotification(MessageBox): # {{{
|
||||
self.vlb.clicked.connect(self.show_log)
|
||||
self.det_msg_toggle.setVisible(bool(det_msg))
|
||||
self.setModal(False)
|
||||
self.callback = callback
|
||||
self.callback, self.cancel_callback = callback, cancel_callback
|
||||
_proceed_memory.append(self)
|
||||
|
||||
def show_log(self):
|
||||
@ -192,9 +195,11 @@ class ProceedNotification(MessageBox): # {{{
|
||||
try:
|
||||
if result == self.Accepted:
|
||||
self.callback(self.payload)
|
||||
elif self.cancel_callback is not None:
|
||||
self.cancel_callback(self.payload)
|
||||
finally:
|
||||
# Ensure this notification is garbage collected
|
||||
self.callback = None
|
||||
self.callback = self.cancel_callback = None
|
||||
self.setParent(None)
|
||||
self.finished.disconnect()
|
||||
self.vlb.clicked.disconnect()
|
||||
|
@ -197,9 +197,11 @@ class JobManager(QAbstractTableModel): # {{{
|
||||
def row_to_job(self, row):
|
||||
return self.jobs[row]
|
||||
|
||||
def has_device_jobs(self):
|
||||
def has_device_jobs(self, queued_also=False):
|
||||
for job in self.jobs:
|
||||
if job.is_running and isinstance(job, DeviceJob):
|
||||
if isinstance(job, DeviceJob):
|
||||
if job.duration is None: # Running or waiting
|
||||
if (job.is_running or queued_also):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -6,15 +6,15 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>533</height>
|
||||
<width>872</width>
|
||||
<height>610</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Get Books</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<iconset resource="../../../../../resources/images.qrc">
|
||||
<normaloff>:/images/store.png</normaloff>:/images/store.png</iconset>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
@ -82,8 +82,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>125</width>
|
||||
<height>127</height>
|
||||
<width>173</width>
|
||||
<height>106</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
@ -255,7 +255,7 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../../resources/images.qrc"/>
|
||||
<include location="../../../../../resources/images.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
|
@ -770,7 +770,8 @@ class BrowseServer(object):
|
||||
summs.append(self.browse_summary_template.format(**args))
|
||||
|
||||
|
||||
return json.dumps('\n'.join(summs), ensure_ascii=False)
|
||||
raw = json.dumps('\n'.join(summs), ensure_ascii=False)
|
||||
return raw
|
||||
|
||||
def browse_render_details(self, id_):
|
||||
try:
|
||||
|
@ -65,7 +65,8 @@ def test_sqlite():
|
||||
def test_qt():
|
||||
from PyQt4.Qt import (QWebView, QDialog, QImageReader, QNetworkAccessManager)
|
||||
fmts = set(map(unicode, QImageReader.supportedImageFormats()))
|
||||
if 'jpg' not in fmts or 'png' not in fmts:
|
||||
testf = set(['jpg', 'png', 'mng', 'svg', 'ico', 'gif'])
|
||||
if testf.intersection(fmts) != testf:
|
||||
raise RuntimeError(
|
||||
"Qt doesn't seem to be able to load its image plugins")
|
||||
QWebView, QDialog
|
||||
@ -87,6 +88,12 @@ def test_imaging():
|
||||
raise RuntimeError('PIL choked!')
|
||||
print ('PIL OK!')
|
||||
|
||||
def test_unrar():
|
||||
from calibre.libunrar import _libunrar
|
||||
if not _libunrar:
|
||||
raise RuntimeError('Failed to load libunrar')
|
||||
print ('Unrar OK!')
|
||||
|
||||
def test():
|
||||
test_plugins()
|
||||
test_lxml()
|
||||
@ -97,6 +104,7 @@ def test():
|
||||
test_win32()
|
||||
test_qt()
|
||||
test_imaging()
|
||||
test_unrar()
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
|
Loading…
x
Reference in New Issue
Block a user