First cut at DB preferences

This commit is contained in:
Charles Haley 2010-07-19 09:50:29 +01:00
parent a3d8ce4850
commit 77ddc1fedf
8 changed files with 70 additions and 40 deletions

View File

@ -25,8 +25,8 @@ class SavedSearchEditor(QDialog, Ui_SavedSearchEditor):
self.current_search_name = None
self.searches = {}
self.searches_to_delete = []
for name in saved_searches.names():
self.searches[name] = saved_searches.lookup(name)
for name in saved_searches().names():
self.searches[name] = saved_searches().lookup(name)
self.populate_search_list()
if initial_search is not None and initial_search in self.searches:
@ -78,7 +78,7 @@ class SavedSearchEditor(QDialog, Ui_SavedSearchEditor):
if self.current_search_name:
self.searches[self.current_search_name] = unicode(self.search_text.toPlainText())
for name in self.searches_to_delete:
saved_searches.delete(name)
saved_searches().delete(name)
for name in self.searches:
saved_searches.add(name, self.searches[name])
saved_searches().add(name, self.searches[name])
QDialog.accept(self)

View File

@ -7,7 +7,6 @@ from PyQt4.QtCore import SIGNAL, Qt
from PyQt4.QtGui import QDialog, QIcon, QListWidgetItem
from calibre.gui2.dialogs.tag_categories_ui import Ui_TagCategories
from calibre.utils.config import prefs
from calibre.gui2.dialogs.confirm_delete import confirm
from calibre.constants import islinux
@ -63,7 +62,7 @@ class TagCategories(QDialog, Ui_TagCategories):
self.all_items.append(t)
self.all_items_dict[label+':'+n] = t
self.categories = dict.copy(prefs['user_categories'])
self.categories = dict.copy(db.prefs['user_categories'])
if self.categories is None:
self.categories = {}
for cat in self.categories:
@ -182,7 +181,7 @@ class TagCategories(QDialog, Ui_TagCategories):
def accept(self):
self.save_category()
prefs['user_categories'] = self.categories
self.db.prefs['user_categories'] = self.categories
QDialog.accept(self)
def save_category(self):

View File

@ -259,8 +259,7 @@ class SavedSearchBox(QComboBox):
self.setMinimumContentsLength(10)
self.tool_tip_text = self.toolTip()
def initialize(self, _saved_searches, _search_box, colorize=False, help_text=_('Search')):
self.saved_searches = _saved_searches
def initialize(self, _search_box, colorize=False, help_text=_('Search')):
self.search_box = _search_box
self.help_text = help_text
self.colorize = colorize
@ -302,11 +301,11 @@ class SavedSearchBox(QComboBox):
self.normalize_state()
self.search_box.set_search_string(u'search:"%s"' % qname)
self.setEditText(qname)
self.setToolTip(self.saved_searches.lookup(qname))
self.setToolTip(saved_searches().lookup(qname))
def initialize_saved_search_names(self):
self.clear()
qnames = self.saved_searches.names()
qnames = saved_searches().names()
self.addItems(qnames)
self.setCurrentIndex(-1)
@ -319,10 +318,10 @@ class SavedSearchBox(QComboBox):
idx = self.currentIndex
if idx < 0:
return
ss = self.saved_searches.lookup(unicode(self.currentText()))
ss = saved_searches().lookup(unicode(self.currentText()))
if ss is None:
return
self.saved_searches.delete(unicode(self.currentText()))
saved_searches().delete(unicode(self.currentText()))
self.clear_to_help()
self.search_box.clear_to_help()
self.emit(SIGNAL('changed()'))
@ -332,8 +331,8 @@ class SavedSearchBox(QComboBox):
name = unicode(self.currentText())
if self.help_state or not name.strip():
name = unicode(self.search_box.text()).replace('"', '')
self.saved_searches.delete(name)
self.saved_searches.add(name, unicode(self.search_box.text()))
saved_searches().delete(name)
saved_searches().add(name, unicode(self.search_box.text()))
# now go through an initialization cycle to ensure that the combobox has
# the new search in it, that it is selected, and that the search box
# references the new search instead of the text in the search.
@ -348,7 +347,7 @@ class SavedSearchBox(QComboBox):
idx = self.currentIndex();
if idx < 0:
return
self.search_box.set_search_string(self.saved_searches.lookup(unicode(self.currentText())))
self.search_box.set_search_string(saved_searches().lookup(unicode(self.currentText())))
class SearchBoxMixin(object):
@ -390,11 +389,12 @@ class SearchBoxMixin(object):
class SavedSearchBoxMixin(object):
def __init__(self):
def __init__(self, db):
self.db = db
self.connect(self.saved_search, SIGNAL('changed()'), self.saved_searches_changed)
self.saved_searches_changed()
self.connect(self.clear_button, SIGNAL('clicked()'), self.saved_search.clear_to_help)
self.saved_search.initialize(saved_searches, self.search, colorize=True,
self.saved_search.initialize(self.search, colorize=True,
help_text=_('Saved Searches'))
self.connect(self.save_search_button, SIGNAL('clicked()'),
self.saved_search.save_search_button_clicked)
@ -409,9 +409,12 @@ class SavedSearchBoxMixin(object):
b = getattr(self, x+'_search_button')
b.setStatusTip(b.toolTip())
def set_database(self, db):
self.db = db
self.saved_searches_changed()
def saved_searches_changed(self):
p = prefs['saved_searches'].keys()
p = saved_searches().names()
p.sort()
t = unicode(self.search_restriction.currentText())
self.search_restriction.clear() # rebuild the restrictions combobox using current saved searches

View File

@ -224,7 +224,7 @@ class TagsView(QTreeView): # {{{
# Always show the user categories editor
self.context_menu.addSeparator()
if category in prefs['user_categories'].keys():
if category in self.db.prefs['user_categories'].keys():
self.context_menu.addAction(_('Manage User Categories'),
partial(self.context_menu_handler, action='manage_categories',
category=category))
@ -426,10 +426,10 @@ class TagsModel(QAbstractItemModel): # {{{
for k in tb_cats.keys():
if tb_cats[k]['kind'] in ['user', 'search']:
del tb_cats[k]
for user_cat in sorted(prefs['user_categories'].keys()):
for user_cat in sorted(self.db.prefs['user_categories'].keys()):
cat_name = user_cat+':' # add the ':' to avoid name collision
tb_cats.add_user_category(label=cat_name, name=user_cat)
if len(saved_searches.names()):
if len(saved_searches().names()):
tb_cats.add_search_category(label='search', name=_('Searches'))
# Now get the categories
@ -507,11 +507,11 @@ class TagsModel(QAbstractItemModel): # {{{
if key not in self.db.field_metadata:
return
if key == 'search':
if val in saved_searches.names():
if val in saved_searches().names():
error_dialog(self.tags_view, _('Duplicate search name'),
_('The saved search name %s is already used.')%val).exec_()
return False
saved_searches.rename(unicode(item.data(role).toString()), val)
saved_searches().rename(unicode(item.data(role).toString()), val)
self.tags_view.search_item_renamed.emit()
else:
if key == 'series':

View File

@ -199,7 +199,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
UpdateMixin.__init__(self, opts)
####################### Search boxes ########################
SavedSearchBoxMixin.__init__(self)
SavedSearchBoxMixin.__init__(self, db)
SearchBoxMixin.__init__(self)
####################### Library view ########################
@ -392,6 +392,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
self.library_view.model().set_book_on_device_func(self.book_on_device)
self.status_bar.clear_message()
self.search.clear_to_help()
self.saved_search.clear_to_help()
self.book_details.reset_info()
self.library_view.model().count_changed()
self.scheduler.database_changed(db)

View File

@ -30,7 +30,7 @@ from calibre.customize.ui import run_plugins_on_import
from calibre.utils.filenames import ascii_filename
from calibre.utils.date import utcnow, now as nowf, utcfromtimestamp
from calibre.utils.config import prefs, tweaks
from calibre.utils.search_query_parser import saved_searches
from calibre.utils.search_query_parser import saved_searches, set_saved_searches
from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format
from calibre.utils.magick_draw import save_cover_data_to
@ -142,6 +142,24 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
def initialize_dynamic(self):
self.prefs = DBPrefs(self)
# Migrate saved search and user categories to db preference scheme
def migrate_preference(name):
ans = self.prefs.get(name, None)
if ans is None:
ans = prefs[name]
try:
del prefs[name]
except:
pass
if ans is not None:
self.prefs[name] = ans
migrate_preference('user_categories')
migrate_preference('saved_searches')
set_saved_searches(self, 'saved_searches')
self.conn.executescript('''
DROP TRIGGER IF EXISTS author_insert_trg;
CREATE TEMP TRIGGER author_insert_trg
@ -270,10 +288,10 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
for k in tb_cats.keys():
if tb_cats[k]['kind'] in ['user', 'search']:
del tb_cats[k]
for user_cat in sorted(prefs['user_categories'].keys()):
for user_cat in sorted(self.prefs['user_categories'].keys()):
cat_name = user_cat+':' # add the ':' to avoid name collision
tb_cats.add_user_category(label=cat_name, name=user_cat)
if len(saved_searches.names()):
if len(saved_searches().names()):
tb_cats.add_search_category(label='search', name=_('Searches'))
self.book_on_device_func = None
@ -845,7 +863,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
categories['formats'].sort(key = lambda x:x.name)
#### Now do the user-defined categories. ####
user_categories = prefs['user_categories']
user_categories = self.prefs['user_categories']
# We want to use same node in the user category as in the source
# category. To do that, we need to find the original Tag node. There is
@ -882,8 +900,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
icon = None
if icon_map and 'search' in icon_map:
icon = icon_map['search']
for srch in saved_searches.names():
items.append(Tag(srch, tooltip=saved_searches.lookup(srch), icon=icon))
for srch in saved_searches().names():
items.append(Tag(srch, tooltip=saved_searches().lookup(srch), icon=icon))
if len(items):
if icon_map is not None:
icon_map['search'] = icon_map['search']

View File

@ -397,4 +397,3 @@ class SchemaUpgrade(object):
UNIQUE(key));
'''
self.conn.executescript(script)

View File

@ -21,7 +21,6 @@ import sys, string, operator
from calibre.utils.pyparsing import Keyword, Group, Forward, CharsNotIn, Suppress, \
OneOrMore, oneOf, CaselessLiteral, Optional, NoMatch, ParseException
from calibre.constants import preferred_encoding
from calibre.utils.config import prefs
'''
This class manages access to the preference holding the saved search queries.
@ -32,9 +31,13 @@ class SavedSearchQueries(object):
queries = {}
opt_name = ''
def __init__(self, _opt_name):
def __init__(self, db, _opt_name):
self.opt_name = _opt_name;
self.queries = prefs[self.opt_name]
self.db = db
if db is not None:
self.queries = db.prefs[self.opt_name]
else:
self.queries = {}
def force_unicode(self, x):
if not isinstance(x, unicode):
@ -43,20 +46,20 @@ class SavedSearchQueries(object):
def add(self, name, value):
self.queries[self.force_unicode(name)] = self.force_unicode(value).strip()
prefs[self.opt_name] = self.queries
self.db.prefs[self.opt_name] = self.queries
def lookup(self, name):
return self.queries.get(self.force_unicode(name), None)
def delete(self, name):
self.queries.pop(self.force_unicode(name), False)
prefs[self.opt_name] = self.queries
self.db.prefs[self.opt_name] = self.queries
def rename(self, old_name, new_name):
self.queries[self.force_unicode(new_name)] = \
self.queries.get(self.force_unicode(old_name), None)
self.queries.pop(self.force_unicode(old_name), False)
prefs[self.opt_name] = self.queries
self.db.prefs[self.opt_name] = self.queries
def names(self):
return sorted(self.queries.keys(),
@ -66,8 +69,15 @@ class SavedSearchQueries(object):
Create a global instance of the saved searches. It is global so that the searches
are common across all instances of the parser (devices, library, etc).
'''
saved_searches = SavedSearchQueries('saved_searches')
ss = SavedSearchQueries(None, None)
def set_saved_searches(db, opt_name):
global ss
ss = SavedSearchQueries(db, opt_name)
def saved_searches():
global ss
return ss
class SearchQueryParser(object):
'''
@ -209,7 +219,7 @@ class SearchQueryParser(object):
raise ParseException(query, len(query), 'undefined saved search', self)
if self.recurse_level > 5:
self.searches_seen.add(query)
return self._parse(saved_searches.lookup(query))
return self._parse(saved_searches().lookup(query))
except: # convert all exceptions (e.g., missing key) to a parse error
raise ParseException(query, len(query), 'undefined saved search', self)
return self.get_matches(location, query)