From 2da413fa8133e4e285f199fbb992dc478ec4bd0e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 18 Jul 2010 14:04:13 -0600 Subject: [PATCH 1/2] ... --- src/calibre/utils/PythonMagickWand.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/calibre/utils/PythonMagickWand.py b/src/calibre/utils/PythonMagickWand.py index cf9b5d167f..69a17d2297 100644 --- a/src/calibre/utils/PythonMagickWand.py +++ b/src/calibre/utils/PythonMagickWand.py @@ -66,7 +66,7 @@ and save it to a new file. """ -import ctypes, sys, os +import ctypes, sys, os, glob from ctypes import util iswindows = 'win32' in sys.platform or 'win64' in sys.platform isosx = 'darwin' in sys.platform @@ -85,7 +85,8 @@ elif iswindows: _lib = flib if isfrozen else 'CORE_RL_wand_' else: if isfrozen: - _lib = os.path.join(sys.frozen_path, 'libMagickWand.so.2') + _lib = glob.glob(os.path.join(sys.frozen_path, + 'libMagickWand.so.*'))[-1] else: _lib = util.find_library('MagickWand') if _lib is None: From 115fa2e679c243eaa6246f6db0158317117c9608 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 18 Jul 2010 14:05:58 -0600 Subject: [PATCH 2/2] Store column layout per library --- src/calibre/gui2/library/views.py | 27 +++++++++++--- src/calibre/library/database2.py | 2 ++ src/calibre/library/prefs.py | 49 ++++++++++++++++++++++++++ src/calibre/library/schema_upgrades.py | 11 ++++++ src/calibre/utils/config.py | 40 ++++++++++++--------- 5 files changed, 108 insertions(+), 21 deletions(-) create mode 100644 src/calibre/library/prefs.py diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index c6c32f86f7..3efde4824d 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -218,9 +218,10 @@ class BooksView(QTableView): # {{{ # Only save if we have been initialized (set_database called) if len(self.column_map) > 0 and self.was_restored: state = self.get_state() + db = getattr(self.model(), 'db', None) name = unicode(self.objectName()) - if name: - gprefs.set(name + ' books view state', state) + if name and db is not None: + db.prefs.set(name + ' books view state', state) def cleanup_sort_history(self, sort_history): history = [] @@ -298,11 +299,27 @@ class BooksView(QTableView): # {{{ old_state['column_sizes'][name] += 12 return old_state - def restore_state(self): + def get_old_state(self): + ans = None name = unicode(self.objectName()) - old_state = None if name: - old_state = gprefs.get(name + ' books view state', None) + name += ' books view state' + db = getattr(self.model(), 'db', None) + if db is not None: + ans = db.prefs.get(name, None) + if ans is None: + ans = gprefs.get(name, None) + try: + del gprefs[name] + except: + pass + if ans is not None: + db.prefs[name] = ans + return ans + + + def restore_state(self): + old_state = self.get_old_state() if old_state is None: old_state = self.get_default_state() diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 85e951d4b0..1cf88d3750 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -19,6 +19,7 @@ from calibre.library.schema_upgrades import SchemaUpgrade from calibre.library.caches import ResultCache from calibre.library.custom_columns import CustomColumns from calibre.library.sqlite import connect, IntegrityError, DBThread +from calibre.library.prefs import DBPrefs from calibre.ebooks.metadata import string_to_authors, authors_to_string, \ MetaInformation from calibre.ebooks.metadata.meta import get_metadata, metadata_from_formats @@ -140,6 +141,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.initialize_dynamic() def initialize_dynamic(self): + self.prefs = DBPrefs(self) self.conn.executescript(''' DROP TRIGGER IF EXISTS author_insert_trg; CREATE TEMP TRIGGER author_insert_trg diff --git a/src/calibre/library/prefs.py b/src/calibre/library/prefs.py new file mode 100644 index 0000000000..ff9733aaa3 --- /dev/null +++ b/src/calibre/library/prefs.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import json + +from calibre.constants import preferred_encoding +from calibre.utils.config import to_json, from_json + +class DBPrefs(dict): + + def __init__(self, db): + dict.__init__(self) + self.db = db + for key, val in self.db.conn.get('SELECT key,val FROM preferences'): + val = self.raw_to_object(val) + dict.__setitem__(self, key, val) + + def raw_to_object(self, raw): + if not isinstance(raw, unicode): + raw = raw.decode(preferred_encoding) + return json.loads(raw, object_hook=from_json) + + def to_raw(self, val): + return json.dumps(val, indent=2, default=to_json) + + def __getitem__(self, key): + return dict.__getitem__(self, key) + + def __delitem__(self, key): + dict.__delitem__(self, key) + self.db.conn.execute('DELETE FROM preferences WHERE key=?', (key,)) + self.db.conn.commit() + + def __setitem__(self, key, val): + raw = self.to_raw(val) + self.db.conn.execute('DELETE FROM preferences WHERE key=?', (key,)) + self.db.conn.execute('INSERT INTO preferences (key,val) VALUES (?,?)', (key, + raw)) + self.db.conn.commit() + dict.__setitem__(self, key, val) + + def set(self, key, val): + self.__setitem__(key, val) + + diff --git a/src/calibre/library/schema_upgrades.py b/src/calibre/library/schema_upgrades.py index 1ba650f6fd..4d1b966107 100644 --- a/src/calibre/library/schema_upgrades.py +++ b/src/calibre/library/schema_upgrades.py @@ -387,3 +387,14 @@ class SchemaUpgrade(object): self.conn.execute('UPDATE authors SET sort=author_to_author_sort(name)') + def upgrade_version_12(self): + 'DB based preference store' + script = ''' + DROP TABLE IF EXISTS preferences; + CREATE TABLE preferences(id INTEGER PRIMARY KEY, + key TEXT NON NULL, + val TEXT NON NULL, + UNIQUE(key)); + ''' + self.conn.executescript(script) + diff --git a/src/calibre/utils/config.py b/src/calibre/utils/config.py index 5c4bd55644..91b1dc70cc 100644 --- a/src/calibre/utils/config.py +++ b/src/calibre/utils/config.py @@ -6,15 +6,16 @@ __docformat__ = 'restructuredtext en' ''' Manage application-wide preferences. ''' -import os, re, cPickle, textwrap, traceback, plistlib, json, base64 +import os, re, cPickle, textwrap, traceback, plistlib, json, base64, datetime from copy import deepcopy from functools import partial from optparse import OptionParser as _OptionParser from optparse import IndentedHelpFormatter +from collections import defaultdict + from calibre.constants import terminal_controller, iswindows, isosx, \ __appname__, __version__, __author__, plugins from calibre.utils.lock import LockError, ExclusiveFile -from collections import defaultdict if os.environ.has_key('CALIBRE_CONFIG_DIRECTORY'): config_dir = os.path.abspath(os.environ['CALIBRE_CONFIG_DIRECTORY']) @@ -632,27 +633,34 @@ class XMLConfig(dict): f.truncate() f.write(raw) +def to_json(obj): + if isinstance(obj, bytearray): + return {'__class__': 'bytearray', + '__value__': base64.standard_b64encode(bytes(obj))} + if isinstance(obj, datetime.datetime): + from calibre.utils.date import isoformat + return {'__class__': 'datetime.datetime', + '__value__': isoformat(obj, as_utc=True)} + raise TypeError(repr(obj) + ' is not JSON serializable') + +def from_json(obj): + if '__class__' in obj: + if obj['__class__'] == 'bytearray': + return bytearray(base64.standard_b64decode(obj['__value__'])) + if obj['__class__'] == 'datetime.datetime': + from calibre.utils.date import parse_date + return parse_date(obj['__value__'], assume_utc=True) + return obj + class JSONConfig(XMLConfig): EXTENSION = '.json' - def to_json(self, obj): - if isinstance(obj, bytearray): - return {'__class__': 'bytearray', - '__value__': base64.standard_b64encode(bytes(obj))} - raise TypeError(repr(obj) + ' is not JSON serializable') - - def from_json(self, obj): - if '__class__' in obj: - if obj['__class__'] == 'bytearray': - return bytearray(base64.standard_b64decode(obj['__value__'])) - return obj - def raw_to_object(self, raw): - return json.loads(raw.decode('utf-8'), object_hook=self.from_json) + return json.loads(raw.decode('utf-8'), object_hook=from_json) def to_raw(self): - return json.dumps(self, indent=2, default=self.to_json) + return json.dumps(self, indent=2, default=to_json) def __getitem__(self, key): return dict.__getitem__(self, key)