From 1f837ca129b0f5a0b7e0e311362ed907a7754224 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Jun 2011 06:34:52 -0600 Subject: [PATCH 1/9] ... --- setup/installer/windows/freeze.py | 2 +- setup/installer/windows/site.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/installer/windows/freeze.py b/setup/installer/windows/freeze.py index 0fe494e831..e67f75f9b0 100644 --- a/setup/installer/windows/freeze.py +++ b/setup/installer/windows/freeze.py @@ -72,7 +72,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() diff --git a/setup/installer/windows/site.py b/setup/installer/windows/site.py index 33f2e63585..d2212037ee 100644 --- a/setup/installer/windows/site.py +++ b/setup/installer/windows/site.py @@ -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): From 1620dee54830d88f769dfa2aa9d34eff2161f156 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Jun 2011 06:56:34 -0600 Subject: [PATCH 2/9] Clean up Qt plugins dir in windows build --- setup/installer/windows/freeze.py | 4 ++++ src/calibre/test_build.py | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/setup/installer/windows/freeze.py b/setup/installer/windows/freeze.py index e67f75f9b0..59d08cea64 100644 --- a/setup/installer/windows/freeze.py +++ b/setup/installer/windows/freeze.py @@ -197,6 +197,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' diff --git a/src/calibre/test_build.py b/src/calibre/test_build.py index 0610f01805..4d45077b93 100644 --- a/src/calibre/test_build.py +++ b/src/calibre/test_build.py @@ -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 From 9ba38f6585a80aa667c45b4a74ad994d41532fe4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Jun 2011 08:40:29 -0600 Subject: [PATCH 3/9] Allow has_device_jobs to also check for queued device jobs --- src/calibre/gui2/jobs.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/calibre/gui2/jobs.py b/src/calibre/gui2/jobs.py index 51c54843a4..6aae892d61 100644 --- a/src/calibre/gui2/jobs.py +++ b/src/calibre/gui2/jobs.py @@ -197,10 +197,12 @@ 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): - return True + if isinstance(job, DeviceJob): + if job.duration is None: # Running or waiting + if (job.is_running or queued_also): + return True return False def has_jobs(self): From 9baceb011a624448165cd275a3735020ca67a833 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Jun 2011 08:53:27 -0600 Subject: [PATCH 4/9] Make the Get Books dialog larger by default --- src/calibre/gui2/store/search/search.ui | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/calibre/gui2/store/search/search.ui b/src/calibre/gui2/store/search/search.ui index 1451aa09f1..ba5cb2b975 100644 --- a/src/calibre/gui2/store/search/search.ui +++ b/src/calibre/gui2/store/search/search.ui @@ -6,15 +6,15 @@ 0 0 - 584 - 533 + 872 + 610 Get Books - + :/images/store.png:/images/store.png @@ -82,8 +82,8 @@ 0 0 - 125 - 127 + 173 + 106 @@ -255,7 +255,7 @@ - + From 6f087f87d85bfc3bef95475a1f0c2d7c5087b1c6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Jun 2011 09:19:24 -0600 Subject: [PATCH 5/9] ... --- src/calibre/gui2/store/search/search.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/store/search/search.py b/src/calibre/gui2/store/search/search.py index 8289c89b96..c802238a35 100644 --- a/src/calibre/gui2/store/search/search.py +++ b/src/calibre/gui2/store/search/search.py @@ -281,11 +281,11 @@ class SearchDialog(QDialog, Ui_Dialog): tab_widget.setCurrentIndex(tab_index) d.exec_() - + # Save dialog state. self.config['config_dialog_geometry'] = bytearray(d.saveGeometry()) self.config['config_dialog_tab_index'] = tab_widget.currentIndex() - + search_config_widget.save_settings() self.config_changed() self.gui.load_store_plugins() From 95731c3be07553f2754f03772ab142b9d666a853 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Jun 2011 09:48:37 -0600 Subject: [PATCH 6/9] Add a cancel callback to ProceedNotification --- src/calibre/gui2/dialogs/message_box.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/calibre/gui2/dialogs/message_box.py b/src/calibre/gui2/dialogs/message_box.py index fdec19dc69..f7cd43bdbd 100644 --- a/src/calibre/gui2/dialogs/message_box.py +++ b/src/calibre/gui2/dialogs/message_box.py @@ -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() From b5a166753b02eea1712131ec004adfe2564b8db4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Jun 2011 11:33:32 -0600 Subject: [PATCH 7/9] Windows build: No longer install CRT in the system SxS folder. Makes calibre fully relocatable. --- setup/installer/windows/en-us.xml | 2 +- setup/installer/windows/freeze.py | 33 ++++++++++++++++++++++-- setup/installer/windows/wix-template.xml | 16 ++++++------ setup/installer/windows/wix.py | 1 - src/calibre/test_build.py | 7 +++++ 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/setup/installer/windows/en-us.xml b/setup/installer/windows/en-us.xml index 89cc25f0a2..d3cdac2a41 100644 --- a/setup/installer/windows/en-us.xml +++ b/setup/installer/windows/en-us.xml @@ -1,6 +1,6 @@ - If you are upgrading from a {app} version older than 0.6.17, please uninstall {app} first. Click Advanced to change installation settings. + Click Advanced to change installation settings. Computing space requirements, this may take upto five minutes... Computing space requirements, this may take upto five minutes... Computing space requirements, this may take upto five minutes... diff --git a/setup/installer/windows/freeze.py b/setup/installer/windows/freeze.py index 59d08cea64..63993c19f0 100644 --- a/setup/installer/windows/freeze.py +++ b/setup/installer/windows/freeze.py @@ -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' @@ -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).*Microsoft\.VC\d+\.CRT') + repl_pat = re.compile( + r'(?is).*?Microsoft\.VC\d+\.CRT.*?') + + 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): diff --git a/setup/installer/windows/wix-template.xml b/setup/installer/windows/wix-template.xml index 3ebe0882e0..46b5a07ead 100644 --- a/setup/installer/windows/wix-template.xml +++ b/setup/installer/windows/wix-template.xml @@ -11,6 +11,10 @@ SummaryCodepage='1252' /> + + - @@ -100,10 +103,6 @@ - - - - @@ -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 --> + diff --git a/setup/installer/windows/wix.py b/setup/installer/windows/wix.py index 857a667a9e..b43e14a711 100644 --- a/setup/installer/windows/wix.py +++ b/setup/installer/windows/wix.py @@ -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() diff --git a/src/calibre/test_build.py b/src/calibre/test_build.py index 4d45077b93..b987658d72 100644 --- a/src/calibre/test_build.py +++ b/src/calibre/test_build.py @@ -88,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() @@ -98,6 +104,7 @@ def test(): test_win32() test_qt() test_imaging() + test_unrar() if __name__ == '__main__': test() From 88e8e9db7eb9354f397c33203ae535972fe2f7ac Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 6 Jun 2011 12:14:03 -0600 Subject: [PATCH 8/9] Content server: Show stack trace on javascript errors --- resources/content_server/browse/browse.html | 4 ++-- resources/content_server/browse/browse.js | 8 +++++++- src/calibre/library/server/browse.py | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/resources/content_server/browse/browse.html b/resources/content_server/browse/browse.html index de78e432d7..6a9697dc06 100644 --- a/resources/content_server/browse/browse.html +++ b/resources/content_server/browse/browse.html @@ -20,8 +20,8 @@ - - + +