Rationalize settings system. Unfortunately, this means you will lose most of your stored settings (Except the conversion defaults and the database location). Please spend a moment restoring them.

This commit is contained in:
Kovid Goyal 2008-06-14 12:21:47 -07:00
parent 8ead30992e
commit 65972716d4
15 changed files with 114 additions and 204 deletions

View File

@ -15,7 +15,7 @@ from optparse import OptionParser as _OptionParser
from optparse import IndentedHelpFormatter
from logging import Formatter
from PyQt4.QtCore import QSettings, QVariant, QUrl, QByteArray
from PyQt4.QtCore import QSettings, QVariant, QUrl, QByteArray, QString
from PyQt4.QtGui import QDesktopServices
from calibre.translations.msgfmt import make
@ -429,13 +429,9 @@ def singleinstance(name):
class Settings(QSettings):
def __init__(self):
def __init__(self, name='calibre2'):
QSettings.__init__(self, QSettings.IniFormat, QSettings.UserScope,
'kovidgoyal.net', 'calibre')
def migrate(self, settings):
for key in settings.allKeys():
self.setValue(key, settings.value(key, QVariant()))
'kovidgoyal.net', name)
def get(self, key, default=None):
key = str(key)
@ -451,10 +447,23 @@ class Settings(QSettings):
self.setValue(str(key), QVariant(QByteArray(val)))
_settings = Settings()
if not _settings.get('migrated from QSettings'):
_settings.migrate(QSettings('KovidsBrain', 'libprs500'))
_settings.set('migrated from QSettings', True)
_settings.sync()
if not _settings.get('rationalized'):
__settings = Settings(name='calibre')
dbpath = os.path.join(os.path.expanduser('~'), 'library1.db').decode(sys.getfilesystemencoding())
dbpath = unicode(__settings.value('database path',
QVariant(QString.fromUtf8(dbpath.encode('utf-8')))).toString())
cmdline = __settings.value('LRF conversion defaults', QVariant(QByteArray(''))).toByteArray().data()
_settings.set('database path', dbpath)
if cmdline:
cmdline = cPickle.loads(cmdline)
_settings.set('LRF conversion defaults', cmdline)
_settings.set('rationalized', True)
try:
os.unlink(unicode(__settings.fileName()))
except:
pass
_spat = re.compile(r'^the\s+|^a\s+|^an\s+', re.IGNORECASE)
def english_sort(x, y):

View File

@ -83,17 +83,12 @@ class TableView(QTableView):
def read_settings(self):
self.cw = str(Settings().value(self.__class__.__name__ + ' column widths', QVariant('')).toString())
try:
self.cw = tuple(int(i) for i in self.cw.split(','))
except ValueError:
self.cw = None
self.cw = Settings().get(self.__class__.__name__ + ' column widths')
def write_settings(self):
settings = Settings()
settings.setValue(self.__class__.__name__ + ' column widths',
QVariant(','.join(str(self.columnWidth(i))
for i in range(self.model().columnCount(None)))))
settings.set(self.__class__.__name__ + ' column widths',
tuple([int(self.columnWidth(i)) for i in range(self.model().columnCount(None))]))
def restore_column_widths(self):
if self.cw and len(self.cw):
@ -107,14 +102,10 @@ class TableView(QTableView):
is hidden, if True it is shown.
'''
if cols:
Settings().setValue(self.__class__.__name__ + ' visible columns',
QVariant(repr(cols)))
Settings().set(self.__class__.__name__ + ' visible columns', cols)
else:
cols = qstring_to_unicode(Settings().value(self.__class__.__name__ + ' visible columns',
QVariant('')).toString())
if cols:
cols = eval(cols)
else:
cols = Settings().get(self.__class__.__name__ + ' visible columns')
if not cols:
cols = [True for i in range(self.model().columnCount(self))]
for i in range(len(cols)):
@ -217,7 +208,7 @@ _sidebar_directories = []
def set_sidebar_directories(dirs):
global _sidebar_directories
if dirs is None:
dirs = Settings().value('frequently used directories', QVariant([])).toStringList()
dirs = Settings().get('frequently used directories', [])
_sidebar_directories = [QUrl.fromLocalFile(i) for i in dirs]
class FileDialog(QObject):
@ -251,7 +242,7 @@ class FileDialog(QObject):
self.fd.setModal(modal)
self.fd.setFilter(ftext)
self.fd.setWindowTitle(title)
state = settings.value(name, QVariant()).toByteArray()
state = settings.get(self.dialog_name, QByteArray())
if not self.fd.restoreState(state):
self.fd.setDirectory(os.path.expanduser('~'))
osu = [i for i in self.fd.sidebarUrls()]
@ -259,7 +250,7 @@ class FileDialog(QObject):
QObject.connect(self.fd, SIGNAL('accepted()'), self.save_dir)
self.accepted = self.fd.exec_() == QFileDialog.Accepted
else:
dir = settings.value(self.dialog_name, QVariant(os.path.expanduser('~'))).toString()
dir = settings.get(self.dialog_name, os.path.expanduser('~'))
self.selected_files = []
if mode == QFileDialog.AnyFile:
f = qstring_to_unicode(
@ -284,7 +275,7 @@ class FileDialog(QObject):
self.selected_files.append(f)
if self.selected_files:
self.selected_files = [qstring_to_unicode(q) for q in self.selected_files]
settings.setValue(self.dialog_name, QVariant(os.path.dirname(self.selected_files[0])))
settings.set(self.dialog_name, os.path.dirname(self.selected_files[0]))
self.accepted = bool(self.selected_files)
@ -299,7 +290,7 @@ class FileDialog(QObject):
def save_dir(self):
if self.fd:
settings = Settings()
settings.setValue(self.dialog_name, QVariant(self.fd.saveState()))
settings.set(self.dialog_name, self.fd.saveState())
def choose_dir(window, name, title):

View File

@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import os
from PyQt4.QtGui import QDialog, QMessageBox, QListWidgetItem, QIcon
from PyQt4.QtCore import QVariant, SIGNAL, QStringList, QTimer, Qt, QSize
from PyQt4.QtCore import SIGNAL, QTimer, Qt, QSize
from calibre import islinux, Settings
from calibre.gui2.dialogs.config_ui import Ui_Dialog
@ -24,18 +24,15 @@ class ConfigDialog(QDialog, Ui_Dialog):
self.db = db
self.current_cols = columns
settings = Settings()
path = qstring_to_unicode(\
settings.value("database path",
QVariant(os.path.join(os.path.expanduser('~'),'library1.db'))).toString())
path = settings.get('database path')
self.location.setText(os.path.dirname(path))
self.connect(self.browse_button, SIGNAL('clicked(bool)'), self.browse)
self.connect(self.compact_button, SIGNAL('clicked(bool)'), self.compact)
dirs = settings.value('frequently used directories', QVariant(QStringList())).toStringList()
rn = bool(settings.value('use roman numerals for series number',
QVariant(True)).toBool())
self.timeout.setValue(settings.value('network timeout', QVariant(5)).toInt()[0])
dirs = settings.get('frequently used directories', [])
rn = settings.get('use roman numerals for series number', True)
self.timeout.setValue(settings.get('network timeout', 5))
self.roman_numerals.setChecked(rn)
self.directory_list.addItems(dirs)
self.connect(self.add_button, SIGNAL('clicked(bool)'), self.add_dir)
@ -58,7 +55,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
self.filename_pattern = FilenamePattern(self)
self.metadata_box.layout().insertWidget(0, self.filename_pattern)
icons = settings.value('toolbar icon size', QVariant(self.ICON_SIZES[0])).toSize()
icons = settings.get('toolbar icon size', self.ICON_SIZES[0])
self.toolbar_button_size.setCurrentIndex(0 if icons == self.ICON_SIZES[0] else 1 if icons == self.ICON_SIZES[1] else 2)
self.show_toolbar_text.setChecked(settings.get('show text in toolbar', True))
@ -84,14 +81,14 @@ class ConfigDialog(QDialog, Ui_Dialog):
def accept(self):
settings = Settings()
settings.setValue('use roman numerals for series number', QVariant(self.roman_numerals.isChecked()))
settings.setValue('network timeout', QVariant(self.timeout.value()))
settings.set('use roman numerals for series number', bool(self.roman_numerals.isChecked()))
settings.set('network timeout', int(self.timeout.value()))
path = qstring_to_unicode(self.location.text())
self.final_columns = [self.columns.item(i).checkState() == Qt.Checked for i in range(self.columns.count())]
settings.setValue('toolbar icon size', QVariant(self.ICON_SIZES[self.toolbar_button_size.currentIndex()]))
settings.set('toolbar icon size', self.ICON_SIZES[self.toolbar_button_size.currentIndex()])
settings.set('show text in toolbar', bool(self.show_toolbar_text.isChecked()))
pattern = self.filename_pattern.commit()
settings.setValue('filename pattern', QVariant(pattern))
settings.set('filename pattern', pattern)
if not path or not os.path.exists(path) or not os.path.isdir(path):
d = error_dialog(self, _('Invalid database location'), _('Invalid database location ')+path+_('<br>Must be a directory.'))
@ -102,7 +99,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
else:
self.database_location = os.path.abspath(path)
self.directories = [qstring_to_unicode(self.directory_list.item(i).text()) for i in range(self.directory_list.count())]
settings.setValue('frequently used directories', QVariant(self.directories))
settings.set('frequently used directories', self.directories)
QDialog.accept(self)
class Vacuum(QMessageBox):

View File

@ -76,7 +76,7 @@ class FetchMetadata(QDialog, Ui_FetchMetadata):
self.timeout = timeout
QObject.connect(self.fetch, SIGNAL('clicked()'), self.fetch_metadata)
self.key.setText(Settings().value('isbndb.com key', QVariant('')).toString())
self.key.setText(Settings().get('isbndb.com key', ''))
self.setWindowTitle(title if title else 'Unknown')
self.tlabel.setText(self.tlabel.text().arg(title if title else 'Unknown'))
@ -106,7 +106,7 @@ class FetchMetadata(QDialog, Ui_FetchMetadata):
_('You must specify a valid access key for isbndb.com'))
return
else:
Settings().setValue('isbndb.com key', QVariant(self.key.text()))
Settings().set('isbndb.com key', str(self.key.text()))
args = ['isbndb']
if self.isbn:

View File

@ -106,9 +106,8 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
def load_saved_global_defaults(self):
cmdline = Settings().value('LRF conversion defaults', QVariant(QByteArray(''))).toByteArray().data()
cmdline = Settings().get('LRF conversion defaults')
if cmdline:
cmdline = cPickle.loads(cmdline)
self.set_options_from_cmdline(cmdline)
def set_options_from_cmdline(self, cmdline):
@ -382,7 +381,7 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
cmdline.extend([u'--cover', self.cover_file.name])
self.cmdline = [unicode(i) for i in cmdline]
else:
Settings().setValue('LRF conversion defaults', QVariant(QByteArray(cPickle.dumps(cmdline))))
Settings().set('LRF conversion defaults', cmdline)
QDialog.accept(self)
class LRFBulkDialog(LRFSingleDialog):

View File

@ -122,8 +122,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>622</width>
<height>454</height>
<width>642</width>
<height>458</height>
</rect>
</property>
<layout class="QHBoxLayout" >
@ -435,8 +435,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>622</width>
<height>454</height>
<width>642</width>
<height>458</height>
</rect>
</property>
<layout class="QGridLayout" >
@ -701,8 +701,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>622</width>
<height>454</height>
<width>642</width>
<height>458</height>
</rect>
</property>
<layout class="QGridLayout" >
@ -825,8 +825,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>622</width>
<height>454</height>
<width>642</width>
<height>458</height>
</rect>
</property>
<layout class="QVBoxLayout" >
@ -923,16 +923,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page_5" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
</rect>
</property>
</widget>
</widget>
</item>
<item row="1" column="0" >
@ -981,7 +971,7 @@
<string>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
p, li { white-space: pre-wrap; }
&lt;/style>&lt;/head>&lt;body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;">
&lt;/style>&lt;/head>&lt;body style=" font-family:'Candara'; font-size:11pt; font-weight:400; font-style:normal;">
&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;">&lt;/p>&lt;/body>&lt;/html></string>
</property>
</widget>

View File

@ -144,7 +144,7 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
self.edit_tags)
QObject.connect(self.remove_series_button, SIGNAL('clicked()'),
self.remove_unused_series)
self.timeout = float(Settings().value('network timeout', QVariant(5)).toInt()[0])
self.timeout = float(Settings().get('network timeout', 5))
self.title.setText(db.title(row))
isbn = db.isbn(self.id, index_is_id=True)
if not isbn:

View File

@ -16,8 +16,8 @@ class PasswordDialog(QDialog, Ui_Dialog):
self.setupUi(self)
settings = Settings()
un = settings.value(name+': un', QVariant('')).toString()
pw = settings.value(name+': pw', QVariant('')).toString()
un = settings.get(name+': un', u'')
pw = settings.get(name+': pw', u'')
self.gui_username.setText(un)
self.gui_password.setText(pw)
self.sname = name
@ -38,6 +38,6 @@ class PasswordDialog(QDialog, Ui_Dialog):
def accept(self):
settings = Settings()
settings.setValue(self.sname+': un', QVariant(self.gui_username.text()))
settings.setValue(self.sname+': pw', QVariant(self.gui_password.text()))
settings.set(self.sname+': un', unicode(self.gui_username.text()))
settings.set(self.sname+': pw', unicode(self.gui_password.text()))
QDialog.accept(self)

View File

@ -258,8 +258,7 @@ class JobManager(QAbstractTableModel):
desc = kwargs.pop('job_description', '')
if args and hasattr(args[0], 'append') and '--verbose' not in args[0]:
args[0].append('--verbose')
priority = self.PRIORITY[str(Settings().value('conversion job priority',
QVariant('Normal')).toString())]
priority = self.PRIORITY[Settings().get('conversion job priority', 'Normal')]
job = self.create_job(ConversionJob, desc, slot, priority,
callable, *args, **kwargs)
return job.id

View File

@ -5,6 +5,7 @@ from datetime import timedelta, datetime
from operator import attrgetter
from collections import deque
from math import cos, sin, pi
from itertools import repeat
from PyQt4.QtGui import QTableView, QProgressDialog, QAbstractItemView, QColor, \
QItemDelegate, QPainterPath, QLinearGradient, QBrush, \
QPen, QStyle, QPainter, QLineEdit, QApplication, \
@ -114,8 +115,7 @@ class BooksModel(QAbstractTableModel):
self.load_queue = deque()
def read_config(self):
self.use_roman_numbers = bool(Settings().value('use roman numerals for series number',
QVariant(True)).toBool())
self.use_roman_numbers = Settings().get('use roman numerals for series number', True)
def set_database(self, db):
@ -594,7 +594,7 @@ class DeviceBooksModel(BooksModel):
base = self.map if refinement else self.sorted_map
result = []
for i in base:
q = ['', self.db[i].title, self.db[i].authors, '', ', '.join(self.db[i].tags)] + ['' for j in range(10)]
q = ['', self.db[i].title, self.db[i].authors, '', ', '.join(self.db[i].tags)] + list(repeat('', 10))
if OR:
add = False
for token in tokens:

View File

@ -103,13 +103,13 @@ class Main(MainWindow, Ui_MainWindow):
def configure(self, triggered):
opts = cPickle.loads(str(Settings().value('ebook viewer options', QVariant(cPickle.dumps(self.opts))).toString()))
opts = Settings().get('LRF ebook viewer options', self.opts)
d = Config(self, opts)
d.exec_()
if d.result() == QDialog.Accepted:
opts.white_background = bool(d.white_background.isChecked())
opts.hyphenate = bool(d.hyphenate.isChecked())
Settings().setValue('ebook viewer options', QVariant(cPickle.dumps(opts)))
Settings().set('LRF ebook viewer options', opts)
def set_ebook(self, stream):
self.progress_bar.setMinimum(0)
@ -279,8 +279,7 @@ def option_parser():
return parser
def normalize_settings(parser, opts):
settings = Settings()
saved_opts = cPickle.loads(str(settings.value('ebook viewer options', QVariant(cPickle.dumps(opts))).toString()))
saved_opts = Settings().get('LRF ebook viewer options', opts)
for opt in parser.option_list:
if not opt.dest:
continue

View File

@ -4,7 +4,7 @@ import os, sys, textwrap, collections, traceback, shutil, time
from xml.parsers.expat import ExpatError
from functools import partial
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
QVariant, QThread, QString, QSize, QUrl
QVariant, QThread, QSize, QUrl
from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox, \
QToolButton, QDialog, QDesktopServices
from PyQt4.QtSvg import QSvgRenderer
@ -18,7 +18,7 @@ from calibre.devices.interface import Device
from calibre.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \
initialize_file_icon_provider, question_dialog,\
pixmap_to_data, choose_dir, ORG_NAME, \
qstring_to_unicode, set_sidebar_directories, \
set_sidebar_directories, \
SingleApplication, Application, available_height
from calibre.gui2.cover_flow import CoverFlow, DatabaseImages
from calibre.library.database import LibraryDatabase
@ -979,7 +979,7 @@ class Main(MainWindow, Ui_MainWindow):
newloc = self.database_path
self.database_path = newloc
settings = Settings()
settings.setValue("database path", QVariant(self.database_path))
settings.set('database path', self.database_path)
except Exception, err:
traceback.print_exc()
d = error_dialog(self, _('Could not move database'), unicode(err))
@ -1087,13 +1087,11 @@ class Main(MainWindow, Ui_MainWindow):
def read_settings(self):
settings = Settings()
settings.beginGroup("Main Window")
settings.beginGroup('Main Window')
geometry = settings.value('main window geometry', QVariant()).toByteArray()
self.restoreGeometry(geometry)
settings.endGroup()
dbpath = os.path.join(os.path.expanduser('~'), 'library1.db').decode(sys.getfilesystemencoding())
self.database_path = qstring_to_unicode(settings.value("database path",
QVariant(QString.fromUtf8(dbpath.encode('utf-8')))).toString())
self.database_path = settings.get('database path')
if not os.access(os.path.dirname(self.database_path), os.W_OK):
error_dialog(self, _('Database does not exist'), _('The directory in which the database should be: %s no longer exists. Please choose a new database location.')%self.database_path).exec_()
self.database_path = choose_dir(self, 'database path dialog', 'Choose new location for database')
@ -1102,10 +1100,10 @@ class Main(MainWindow, Ui_MainWindow):
if not os.path.exists(self.database_path):
os.makedirs(self.database_path)
self.database_path = os.path.join(self.database_path, 'library1.db')
settings.setValue('database path', QVariant(QString.fromUtf8(self.database_path.encode('utf-8'))))
settings.set('database path', self.database_path)
set_sidebar_directories(None)
set_filename_pat(qstring_to_unicode(settings.value('filename pattern', QVariant(get_filename_pat())).toString()))
self.tool_bar.setIconSize(settings.value('toolbar icon size', QVariant(QSize(48, 48))).toSize())
set_filename_pat(settings.get('filename pattern', get_filename_pat()))
self.tool_bar.setIconSize(settings.get('toolbar icon size', QSize(48, 48)))
self.tool_bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon if settings.get('show text in toolbar', True) else Qt.ToolButtonIconOnly)

View File

@ -330,7 +330,7 @@ For help on an individual command: %%prog command --help
return 1
command = eval('command_'+args[1])
dbpath = unicode(Settings().value('database path', QVariant(os.path.expanduser('~/library1.db'))).toString())
dbpath = Settings().get('database path')
return command(args[2:], dbpath)

View File

@ -1,11 +1,14 @@
#!/usr/bin/python
import tempfile
import sys, os, shutil, time
import sys, os, shutil, time, tempfile, socket
sys.path.append('src')
import subprocess
from subprocess import check_call as _check_call
from functools import partial
#from pyvix.vix import Host, VIX_SERVICEPROVIDER_VMWARE_WORKSTATION
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('google.com', 0))
HOST=s.getsockname()[0]
PROJECT=os.path.basename(os.getcwd())
from calibre import __version__, __appname__
@ -15,6 +18,15 @@ DOCS = PREFIX+"/htdocs/apidocs"
USER_MANUAL = PREFIX+'/htdocs/user_manual'
HTML2LRF = "src/calibre/ebooks/lrf/html/demo"
TXT2LRF = "src/calibre/ebooks/lrf/txt/demo"
BUILD_SCRIPT ='''\
#!/bin/bash
cd ~/build && \
rsync -avz --exclude docs --exclude .bzr --exclude .build --exclude build --exclude dist --exclude "*.pyc" --exclude "*.pyo" rsync://%(host)s/work/%(project)s . && \
cd %(project)s && \
mkdir -p build dist && \
rm -rf build/* dist/* && \
python %%s
'''%dict(host=HOST, project=PROJECT)
check_call = partial(_check_call, shell=True)
#h = Host(hostType=VIX_SERVICEPROVIDER_VMWARE_WORKSTATION)
@ -29,15 +41,23 @@ def installer_name(ext):
return 'dist/%s-%s.%s'%(__appname__, __version__, ext)
return 'dist/%s-%s-i686.%s'%(__appname__, __version__, ext)
def start_vm(vm, ssh_host, build_script, sleep):
vmware = ('vmware', '-q', '-x', '-n', vm)
subprocess.Popen(vmware)
t = tempfile.NamedTemporaryFile(suffix='.sh')
t.write(build_script)
t.flush()
print 'Waiting for VM to startup'
time.sleep(sleep)
print 'Trying to SSH into VM'
subprocess.check_call(('scp', t.name, ssh_host+':build-'+PROJECT))
def build_windows():
installer = installer_name('exe')
vm = '/vmware/Windows XP/Windows XP Professional.vmx'
vmware = ('vmware', '-q', '-x', '-n', vm)
subprocess.Popen(vmware)
print 'Waiting for Windows to boot up...'
time.sleep(75)
print 'Trying to ssh into the Windows SSH server'
subprocess.check_call(('ssh', 'windows', '/usr/local/bin/build-calibre', os.path.basename(os.getcwd())))
start_vm(vm, 'windows', BUILD_SCRIPT%'windows_installer.py', 75)
subprocess.check_call(('ssh', 'windows', '/bin/bash', '~/build-'+PROJECT))
subprocess.check_call(('scp', 'windows:build/%s/dist/*.exe'%PROJECT, 'dist'))
if not os.path.exists(installer):
raise Exception('Failed to build installer '+installer)
subprocess.Popen(('ssh', 'windows', 'shutdown', '-s', '-t', '0'))
@ -47,11 +67,9 @@ def build_osx():
installer = installer_name('dmg')
vm = '/vmware/Mac OSX/Mac OSX.vmx'
vmware = ('vmware', '-q', '-x', '-n', vm)
subprocess.Popen(vmware)
print 'Waiting for OS X to boot up...'
time.sleep(120)
print 'Trying to ssh into the OS X SSH server'
subprocess.check_call(('ssh', 'osx', '/Users/kovid/bin/build-calibre', os.path.basename(os.getcwd())))
start_vm(vm, 'osx', BUILD_SCRIPT%'osx_installer.py', 120)
subprocess.check_call(('ssh', 'osx', '/bin/bash', '~/build-'+PROJECT))
subprocess.check_call(('scp', 'windows:build/%s/dist/*.dmg'%PROJECT, 'dist'))
if not os.path.exists(installer):
raise Exception('Failed to build installer '+installer)
subprocess.Popen(('ssh', 'osx', 'sudo', '/sbin/shutdown', '-h', 'now'))
@ -62,9 +80,9 @@ def _build_linux():
tbz2 = os.path.join(cwd, installer_name('tar.bz2'))
SPEC="""\
import os
HOME = '%s'
HOME = '%(home)s'
PYINSTALLER = os.path.expanduser('~/build/pyinstaller')
CALIBREPREFIX = HOME+'/work/calibre'
CALIBREPREFIX = HOME+'/work/%(project)s'
CLIT = '/usr/bin/clit'
PDFTOHTML = '/usr/bin/pdftohtml'
LIBUNRAR = '/usr/lib/libunrar.so'
@ -180,12 +198,12 @@ for folder in EXTRAS:
subprocess.check_call('cp -rf %%s .'%%folder, shell=True)
print 'Building tarball...'
tf = tarfile.open('%s', 'w:bz2')
tf = tarfile.open('%(tarfile)s', 'w:bz2')
for f in os.listdir('.'):
tf.add(f)
"""%('/mnt/hgfs/giskard/', tbz2)
"""%dict(home='/mnt/hgfs/giskard/', tarfile=tbz2, project=PROJECT)
os.chdir(os.path.expanduser('~/build/pyinstaller'))
open('calibre/calibre.spec', 'wb').write(SPEC)
try:
@ -200,7 +218,7 @@ def build_linux():
subprocess.Popen(vmware)
print 'Waiting for linux to boot up...'
time.sleep(75)
check_call('ssh linux make -C /mnt/hgfs/giskard/work/calibre all egg linux_binary')
check_call('ssh linux make -C /mnt/hgfs/giskard/work/%s all egg linux_binary'%PROJECT)
check_call('ssh linux sudo poweroff')
def build_installers():

View File

@ -424,96 +424,6 @@ SectionEnd
else:
os.remove(path)
class WixInstaller(object):
'''
Make a .msi installer. Can't get the driver installation to play well with
an existing installation of the connect USB driver. Pick this up again when
libusb1.dll is released based on winusb.
'''
TEMPLATE=\
r'''<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
<Product Name='%(appname)s' Id='955DF7A2-8861-46A9-8710-56A4BDEA8E29'
Language='1033' Codepage='1252' Version='%(version)s' Manufacturer='Kovid Goyal'>
<Package Id='????????-????-????-????-????????????' Keywords='Installer'
Description="Ebook management software"
Manufacturer='Kovid Goyal'
InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
<Icon Id="appicon.ico" SourceFile="icons\library.ico" />
<Binary Id="devcon" SourceFile="C:\devcon\i386\devcon.exe" />
<Condition Message="You need to be an administrator to install this product.">
Privileged
</Condition>
<Property Id='ARPNOMODIFY'>1</Property>
<Property Id='ARPURLINFOABOUT'>http://calibre.kovidgoyal.net</Property>
<Property Id='ARPPRODUCTICON'>appicon.ico</Property>
<Media Id='1' Cabinet='%(appname)s.cab' EmbedCab='yes' />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='INSTALLDIR' Name='libprs' LongName='%(appname)s'>
%(py2exefiles)s
<Directory Id='driver' Name='driver' FileSource="C:\libusb-prs500">
<Component Id="usbdriver" DriverSequence="0" Guid="1169D502-DE59-4153-BC0D-712894C37FEF">
<File Id='libusb0.dll' Name='libusb0.dll' Vital='yes' Compressed='yes' DiskId="1" />
<File Id='libusb0.sys' Name='libusb0.sys' Vital='yes' Compressed='yes' DiskId="1" />
<File Id='libusb0_x64.dll' Name='a' LongName='libusb0_x64.dll' Vital='yes' Compressed='yes' DiskId="1" />
<File Id='libusb0_x64.sys' Name='b' LongName='libusb0_x64.sys' Vital='yes' Compressed='yes' DiskId="1" />
<File Id='prs500.inf' Name='prs500.inf' Vital='yes' Compressed='yes' DiskId="1" />
</Component>
</Directory>
</Directory>
</Directory>
<Component Id='misc' Guid=''>
<Environment Id='UpdatePath' Name='PATH' Action='create' System='yes'
Part='last' Value='[INSTALLDIR]' Permanent="no"/>
</Component>
</Directory>
<Feature Id='Complete' Title="%(appname)s" Description="The complete package">
<ComponentRef Id='py2exe' />
<ComponentRef Id='usbdriver' />
<ComponentRef Id='misc' />
</Feature>
</Product>
</Wix>
'''
CANDLE=r'C:\wix\candle.exe '
LIGHT=r'C:\wix\light.exe -out %s -loc C:\wix\WixUI_en-us.wxl %s c:\wix\wixui.wixlib "C:\Program Files\Driver Installation Tools 2.01\DIFxApp\English-US\WiXLib\x86\DIFxApp.wixlib"'
def __init__(self, py2exe_dir, dest_dir='dist'):
self.py2exe_dir = py2exe_dir
self.dest_dir = dest_dir
filelist = []
print self.py2exe_dir
for root, dirs, files in os.walk(self.py2exe_dir):
for name in files:
path = os.path.abspath(os.path.join(root, name))
filelist.append(path)
component = "<Component Id='py2exe' DiskId='1' Guid='0248CACF-FDF5-4E68-B898-227C16F1C7B8'>\n"
counter = 0
for path in filelist:
entry = '<File Id="file%d" Name="fn%d" Compressed="yes" Vital="yes" Source="%s" LongName="%s" />'%\
(counter, counter, path, os.path.basename(path))
component += entry + "\n"
counter += 1
component += '</Component>'
self.installer = self.TEMPLATE%dict(appname=APPNAME, version=VERSION,
py2exefiles=component)
def build(self):
f = open('installer.wxs', 'w')
f.write(self.installer)
f.close()
subprocess.check_call(self.CANDLE + ' ' + f.name, shell=True)
subprocess.check_call(self.LIGHT%(os.path.join(self.dest_dir, APPNAME + '-' + VERSION + '.msi'),
' installer.wixobj'), shell=True)
os.remove('installer.wxs')
os.remove('installer.wixobj')
class BuildEXE(build_exe):
manifest_resource_id = 0
@ -559,9 +469,9 @@ class BuildEXE(build_exe):
subprocess.check_call(['mingw32-make', '-f', 'Makefile'])
shutil.copyfile('pictureflow.pyd', os.path.join(dd, 'pictureflow.pyd'))
os.chdir('..')
shutil.rmtree('.build')
shutil.rmtree('.build', True)
os.chdir('..')
shutil.rmtree('.build')
shutil.rmtree('.build', True)
finally:
os.chdir(cwd)