CS: Implement switching of libraries

This commit is contained in:
Kovid Goyal 2016-02-18 18:16:12 +05:30
parent b44c770bfd
commit d83dc3fb94
7 changed files with 77 additions and 10 deletions

View File

@ -6,7 +6,7 @@
<meta name="robots" content="noindex"> <meta name="robots" content="noindex">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="favicon.png">
<script>window.calibre_entry_point = 'ENTRY_POINT';</script> <script>window.calibre_entry_point = 'ENTRY_POINT'; window.calibre_default_library = DEFAULT_LIBRARY;</script>
<script type="text/javascript" src="static/main.js"></script> <script type="text/javascript" src="static/main.js"></script>
<link rel="stylesheet" href="static/reset.css"></link> <link rel="stylesheet" href="static/reset.css"></link>
<link rel="stylesheet" href="static/font-awesome/fa.css"></link> <link rel="stylesheet" href="static/font-awesome/fa.css"></link>

View File

@ -7,7 +7,7 @@ from __future__ import (unicode_literals, division, absolute_import,
import re, hashlib, random, os import re, hashlib, random, os
from functools import partial from functools import partial
from threading import Lock from threading import Lock
from json import load as load_json_file from json import load as load_json_file, dumps as json_dumps
from calibre import prepare_string_for_xml, as_unicode from calibre import prepare_string_for_xml, as_unicode
from calibre.constants import config_dir from calibre.constants import config_dir
@ -53,9 +53,13 @@ def get_html(name, auto_reload_port, **replacements):
@endpoint('', auth_required=False) @endpoint('', auth_required=False)
def index(ctx, rd): def index(ctx, rd):
default_library = ctx.library_map[1]
return rd.generate_static_output('/', partial( return rd.generate_static_output('/', partial(
get_html, 'content-server/index.html', getattr(rd.opts, 'auto_reload_port', 0), get_html, 'content-server/index.html', getattr(rd.opts, 'auto_reload_port', 0),
ENTRY_POINT='book list', LOADING_MSG=prepare_string_for_xml(_('Loading library, please wait')))) ENTRY_POINT='book list',
LOADING_MSG=prepare_string_for_xml(_('Loading library, please wait')),
DEFAULT_LIBRARY=json_dumps(default_library)
))
def get_library_data(ctx, query): def get_library_data(ctx, query):
library_id = query.get('library_id') library_id = query.get('library_id')

View File

@ -77,7 +77,7 @@ class Boss:
sval = '' sval = ''
for field, order in zip(str.split(data.search_result.sort, ','), str.split(data.search_result.sort_order, ',')): for field, order in zip(str.split(data.search_result.sort, ','), str.split(data.search_result.sort_order, ',')):
sval += field + '.' + order + ',' sval += field + '.' + order + ','
get_session_data().set('sort', str.rstrip(sval, ',')) get_session_data().set_library_option(self.interface_data.library_id, 'sort', str.rstrip(sval, ','))
self.interface_data.metadata = data.metadata self.interface_data.metadata = data.metadata
self.interface_data.search_result = data.search_result self.interface_data.search_result = data.search_result
self.ui.refresh_books_view() self.ui.refresh_books_view()

View File

@ -1,7 +1,7 @@
# vim:fileencoding=utf-8 # vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
from book_list.globals import get_boss from book_list.globals import get_boss, get_session_data
from book_list.search import SearchPanel from book_list.search import SearchPanel
from book_list.top_bar import TopBar from book_list.top_bar import TopBar
from book_list.views import BooksView from book_list.views import BooksView
@ -10,6 +10,7 @@ from book_list.prefs import PrefsPanel
from book_list.book_details import BookDetailsPanel from book_list.book_details import BookDetailsPanel
from gettext import gettext as _ from gettext import gettext as _
from utils import debounce from utils import debounce
from modals import error_dialog, ajax_progress_dialog
class BarState: class BarState:
@ -70,6 +71,17 @@ def create_book_view_top_bar_state(books_view):
def random_book(): def random_book():
get_boss().ui.replace_panel('book-details', extra_query_data={'book-id':'0'}) get_boss().ui.replace_panel('book-details', extra_query_data={'book-id':'0'})
def change_library_actions():
boss = get_boss()
interface_data = boss.interface_data
ans = []
ans.subtitle = _('Currently showing the library: ') + interface_data.library_map[interface_data.library_id]
for lid in sorted(interface_data.library_map):
if lid != interface_data.library_id:
library_name = interface_data.library_map[lid]
ans.append({'title':library_name, 'action':boss.ui.change_library.bind(boss.ui, lid)})
return ans
class UI: class UI:
ROOT_PANEL = 'books' ROOT_PANEL = 'books'
@ -86,10 +98,18 @@ class UI:
self.current_panel = self.ROOT_PANEL self.current_panel = self.ROOT_PANEL
window.addEventListener('resize', debounce(self.on_resize.bind(self), 250)) window.addEventListener('resize', debounce(self.on_resize.bind(self), 250))
self.panel_map['more-actions-menu'] = UIState(ClosePanelBar(_('More actions')), panel_data=[ num_of_libraries = len(interface_data.library_map)
actions = [
create_item(_('Book List Mode'), replace_panel_action('booklist-mode-menu'), _('Change how the list of books is displayed')), create_item(_('Book List Mode'), replace_panel_action('booklist-mode-menu'), _('Change how the list of books is displayed')),
create_item(_('A Random Book'), random_book, _('Choose a random book from your library')), create_item(_('A Random Book'), random_book, _('Choose a random book from your library')),
]) ]
if num_of_libraries > 1:
actions.push(
create_item(_('Change Library'), replace_panel_action('booklist-change-library'), _('Choose a different library to display'))
)
self.panel_map['booklist-change-library'] = UIState(ClosePanelBar(_('Change Library')), panel_data=change_library_actions)
self.panel_map['more-actions-menu'] = UIState(ClosePanelBar(_('More actions')), panel_data=actions)
self.panel_map['booklist-mode-menu'] = UIState(ClosePanelBar(_('Book List Mode')), panel_data=[]) self.panel_map['booklist-mode-menu'] = UIState(ClosePanelBar(_('Book List Mode')), panel_data=[])
@ -164,3 +184,25 @@ class UI:
self.books_view.refresh() self.books_view.refresh()
if self.current_panel == self.ROOT_PANEL: if self.current_panel == self.ROOT_PANEL:
self.top_bar.refresh_left() self.top_bar.refresh_left()
def change_library(self, library_id):
data = {'search':'', 'sort':get_session_data().get_library_option(library_id, 'sort'), 'library_id':library_id}
ajax_progress_dialog('interface-data/get-books', self.library_changed.bind(self), _(
'Fetching data from server, please wait') + '…', query=data, extra_data_for_callback={'library_id':library_id})
def library_changed(self, end_type, xhr, ev):
if end_type == 'load':
boss = get_boss()
boss.interface_data.library_id = xhr.extra_data_for_callback.library_id
try:
data = JSON.parse(xhr.responseText)
boss.change_books(data)
except Exception as err:
return error_dialog(_('Could not change library'), err + '', details=err.stack)
self.show_panel(self.ROOT_PANEL)
window.scrollTo(0, 0)
elif end_type != 'abort':
msg = xhr.error_html
error_dialog(_('Could not change library'), msg)

View File

@ -240,7 +240,7 @@ class BooksView:
self.abort_get_more_books() self.abort_get_more_books()
query = query or '' query = query or ''
sd = get_session_data() sd = get_session_data()
data = {'search':query, 'sort':sd.get('sort'), 'library_id':self.interface_data.library_id} data = {'search':query, 'sort':sd.get_library_option(self.interface_data.library_id, 'sort'), 'library_id':self.interface_data.library_id}
ajax_progress_dialog('interface-data/get-books', self.search_change_completed.bind(self), _( ajax_progress_dialog('interface-data/get-books', self.search_change_completed.bind(self), _(
'Fetching data from server, please wait') + '…', query=data, extra_data_for_callback={'push_state':push_state, 'panel_to_show': panel_to_show}) 'Fetching data from server, please wait') + '…', query=data, extra_data_for_callback={'push_state':push_state, 'panel_to_show': panel_to_show})

View File

@ -128,6 +128,14 @@ class UserSessionData(SessionData):
defval = defaults[key] defval = defaults[key]
return SessionData.get(self, (self.prefix + key), defval) return SessionData.get(self, (self.prefix + key), defval)
def get_library_option(self, library_id, key, defval):
if not library_id:
return self.get(key, defval)
lkey = key + '-||-' + library_id
if defval is undefined:
defval = defaults[key]
return self.get(lkey, defval)
def set(self, key, value): def set(self, key, value):
if self.echo_changes and self.has_user: if self.echo_changes and self.has_user:
self.changes[key] = value self.changes[key] = value
@ -137,6 +145,11 @@ class UserSessionData(SessionData):
self.push_timer_id = setTimeout(self.push_to_server.bind(self), 1000) self.push_timer_id = setTimeout(self.push_to_server.bind(self), 1000)
return SessionData.set(self, (self.prefix + key), value) return SessionData.set(self, (self.prefix + key), value)
def set_library_option(self, library_id, key, value):
if library_id:
key = key + '-||-' + library_id
return self.set(key, value)
def push_to_server(self): def push_to_server(self):
if self.has_changes: if self.has_changes:
ajax_send('interface-data/set-session-data', self.changes, def(end_type, xhr, ev): ajax_send('interface-data/set-session-data', self.changes, def(end_type, xhr, ev):

View File

@ -33,14 +33,22 @@ def on_library_load_progress(loaded, total):
def load_book_list(): def load_book_list():
temp = UserSessionData(None, {}) # So that settings for anonymous users are preserved temp = UserSessionData(None, {}) # So that settings for anonymous users are preserved
query = {k:temp.get(k) for k in str.split('library_id sort')} query = {}
default_lib = window.calibre_default_library
v'delete window.calibre_default_library'
query.sort = temp.get_library_option(default_lib, 'sort')
library_id = temp.get('library_id')
if library_id:
query.library_id = library_id
url_query = parse_url_params() url_query = parse_url_params()
for key in url_query: for key in url_query:
query[key] = url_query[key] query[key] = url_query[key]
ajax('interface-data/init', on_library_loaded, on_library_load_progress, query=query).send() ajax('interface-data/init', on_library_loaded, on_library_load_progress, query=query).send()
def on_load(): def on_load():
if window.calibre_entry_point == 'book list': ep = window.calibre_entry_point
v'delete window.calibre_entry_point'
if ep == 'book list':
print('calibre loaded at:', Date().toString()) print('calibre loaded at:', Date().toString())
load_book_list() load_book_list()