mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
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:
parent
8ead30992e
commit
65972716d4
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
</style></head><body style=" font-family:'Candara'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<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;"></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
54
upload.py
54
upload.py
@ -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():
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user