diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py
index 062e4eeab9..19382219d0 100644
--- a/src/calibre/gui2/__init__.py
+++ b/src/calibre/gui2/__init__.py
@@ -19,8 +19,35 @@ from calibre.ebooks.metadata.meta import get_metadata, metadata_from_formats
from calibre.ebooks.metadata import MetaInformation
from calibre.utils.date import UNDEFINED_DATE
+# Setup gprefs {{{
gprefs = JSONConfig('gui')
+gprefs.defaults['action-layout-toolbar'] = (
+ 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View', None,
+ 'Choose Library', 'Donate', None, 'Fetch News', 'Save To Disk',
+ 'Connect Share', None, 'Remove Books', None, 'Help', 'Preferences',
+ )
+
+gprefs.defaults['action-layout-toolbar-device'] = (
+ 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View',
+ 'Send To Device', None, None, 'Location Manager', None, None,
+ 'Fetch News', 'Save To Disk', 'Connect Share', None,
+ 'Remove Books', None, 'Help', 'Preferences',
+ )
+
+gprefs.defaults['action-layout-context-menu'] = (
+ 'Edit Metadata', 'Send To Device', 'Save To Disk',
+ 'Connect Share', 'Copy To Library', None,
+ 'Convert Books', 'View', 'Open Folder', 'Show Book Details',
+ 'Similar Books', None, 'Remove Books',
+ )
+
+gprefs.defaults['action-layout-context-menu-device'] = (
+ 'View', 'Save To Disk', None, 'Remove Books', None,
+ 'Add To Library', 'Edit Collections',
+ )
+# }}}
+
NONE = QVariant() #: Null value to return from the data function of item models
UNDEFINED_QDATE = QDate(UNDEFINED_DATE)
diff --git a/src/calibre/gui2/actions/preferences.py b/src/calibre/gui2/actions/preferences.py
index d667e46b03..267cabf9f3 100644
--- a/src/calibre/gui2/actions/preferences.py
+++ b/src/calibre/gui2/actions/preferences.py
@@ -56,6 +56,8 @@ class PreferencesAction(InterfaceAction):
self.gui.tags_view.recount()
self.gui.create_device_menu()
self.gui.set_device_menu_items_state(bool(self.gui.device_connected))
+ self.gui.tool_bar.build_bar()
+ self.gui.build_context_menus()
self.gui.tool_bar.apply_settings()
diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py
index f183d0871b..fdaafd4762 100644
--- a/src/calibre/gui2/dialogs/config/__init__.py
+++ b/src/calibre/gui2/dialogs/config/__init__.py
@@ -14,6 +14,7 @@ from PyQt4.Qt import QDialog, QListWidgetItem, QIcon, \
from calibre.constants import iswindows, isosx
from calibre.gui2.dialogs.config.config_ui import Ui_Dialog
from calibre.gui2.dialogs.config.create_custom_column import CreateCustomColumn
+from calibre.gui2.dialogs.config.toolbar import ToolbarLayout
from calibre.gui2 import error_dialog, config, gprefs, \
open_url, open_local_file, \
ALL_COLUMNS, NONE, info_dialog, choose_files, \
@@ -524,6 +525,9 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
self.current_tweaks.setPlainText(curt.decode('utf-8'))
self.default_tweaks.setPlainText(deft.decode('utf-8'))
self.restore_tweaks_to_default_button.clicked.connect(self.restore_tweaks_to_default)
+ self.toolbar_cm_widget = ToolbarLayout(parent, parent)
+ self.toolbar_cm_tab.addTab(self.toolbar_cm_widget,
+ _('Toolbars/Context menus'))
self.category_view.setCurrentIndex(self.category_view.model().index_for_name(initial_category))
@@ -888,6 +892,7 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
wl = self.opt_worker_limit.value()
if wl%2 != 0:
wl += 1
+ self.toolbar_cm_widget.commit()
config['worker_limit'] = wl
config['use_roman_numerals_for_series_number'] = bool(self.roman_numerals.isChecked())
diff --git a/src/calibre/gui2/dialogs/config/config.ui b/src/calibre/gui2/dialogs/config/config.ui
index 79917760ab..640d93a564 100644
--- a/src/calibre/gui2/dialogs/config/config.ui
+++ b/src/calibre/gui2/dialogs/config/config.ui
@@ -109,7 +109,7 @@
0
- 0
+ 1
@@ -294,361 +294,371 @@
-
- -
-
-
- Use &Roman numerals for series number
+
+
-
+
+
+ 0
-
- true
-
-
-
- -
-
-
- Enable system &tray icon (needs restart)
-
-
-
- -
-
-
- Show ¬ifications in system tray
-
-
-
- -
-
-
- Show &splash screen at startup
-
-
-
- -
-
-
- Show cover &browser in a separate window (needs restart)
-
-
-
- -
-
-
- Show &average ratings in the tags browser
-
-
- true
-
-
-
- -
-
-
- Search as you type
-
-
- true
-
-
-
- -
-
-
- Automatically send downloaded &news to ebook reader
-
-
-
- -
-
-
- &Delete news from library when it is automatically sent to reader
-
-
-
- -
-
-
-
-
-
- &Number of covers to show in browse mode (needs restart):
-
-
- cover_browse
-
-
-
- -
-
-
-
-
- -
-
-
-
-
-
- Select visible &columns in library view
-
-
-
-
-
-
-
-
-
- true
+
+
+ &Miscellaneous
+
+
+
-
+
+
+ User Interface &layout (needs restart):
+
+
+ opt_gui_layout
+
+
+
+ -
+
+
+
+ 250
+ 16777215
+
+
+
+
+ -
+
+
+ &Number of covers to show in browse mode (needs restart):
+
+
+ cover_browse
+
+
+
+ -
+
+
+ -
+
+
+ Restriction to apply when the current library is opened:
+
+
+ opt_gui_restriction
+
+
+
+ -
+
+
+
+ 250
+ 16777215
+
+
+
+ Apply this restriction on calibre startup if the current library is being used. Also applied when switching to this library. Note that this setting is per library.
+
+
+ QComboBox::AdjustToMinimumContentsLengthWithIcon
+
+
+ 15
+
+
+
+ -
+
+
+ Use &Roman numerals for series number
+
+
+ true
+
+
+
+ -
+
+
+ Disable all animations. Useful if you have a slow/old computer.
+
+
+ Disable &animations
+
+
+
+ -
+
+
+ Enable system &tray icon (needs restart)
+
+
+
+ -
+
+
+ Show ¬ifications in system tray
+
+
+
+ -
+
+
+ Show &donate button (restart)
+
+
+
+ -
+
+
+ &Toolbar
+
+
+
-
+
+
+ -
+
+
+ &Icon size:
-
- QAbstractItemView::SelectRows
+
+ opt_toolbar_icon_size
- -
-
+
-
+
+
+ -
+
+
+ Show &text under icons:
+
+
+ opt_toolbar_text
+
+
+
+
+
+
+ -
+
+
+ &Delete news from library when it is automatically sent to reader
+
+
+
+ -
+
+
-
+
+
+ Select visible &columns in library view
+
+
-
-
-
- ...
-
-
-
- :/images/arrow-up.svg:/images/arrow-up.svg
-
-
+
+
-
+
+
+ true
+
+
+ QAbstractItemView::SelectRows
+
+
+
+ -
+
+
-
+
+
+ ...
+
+
+
+ :/images/arrow-up.svg:/images/arrow-up.svg
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Remove a user-defined column
+
+
+ ...
+
+
+
+ :/images/minus.svg:/images/minus.svg
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Add a user-defined column
+
+
+ ...
+
+
+
+ :/images/plus.svg:/images/plus.svg
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Edit settings of a user-defined column
+
+
+ ...
+
+
+
+ :/images/edit_input.svg:/images/edit_input.svg
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ ...
+
+
+
+ :/images/arrow-down.svg:/images/arrow-down.svg
+
+
+
+
+
+
- -
-
-
- Qt::Vertical
+
+
+
+ -
+
+
+ Use internal &viewer for:
+
+
+
-
+
+
+ true
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Remove a user-defined column
-
-
- ...
-
-
-
- :/images/minus.svg:/images/minus.svg
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Add a user-defined column
-
-
- ...
-
-
-
- :/images/plus.svg:/images/plus.svg
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Edit settings of a user-defined column
-
-
- ...
-
-
-
- :/images/edit_input.svg:/images/edit_input.svg
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- ...
-
-
-
- :/images/arrow-down.svg:/images/arrow-down.svg
+
+ QAbstractItemView::NoSelection
-
-
-
-
-
-
- -
-
-
- Use internal &viewer for:
-
-
-
-
-
-
- true
-
-
- QAbstractItemView::NoSelection
-
-
-
-
-
-
-
-
- -
-
-
- User Interface &layout (needs restart):
-
-
- opt_gui_layout
-
-
-
- -
-
-
-
- 250
- 16777215
-
-
-
-
- -
-
-
- Restriction to apply when the current library is opened:
-
-
- opt_gui_restriction
-
-
-
- -
-
-
-
- 250
- 16777215
-
-
-
- Apply this restriction on calibre startup if the current library is being used. Also applied when switching to this library. Note that this setting is per library.
-
-
- QComboBox::AdjustToMinimumContentsLengthWithIcon
-
-
- 20
-
-
-
- -
-
-
- Disable all animations. Useful if you have a slow/old computer.
-
-
- Disable &animations
-
-
-
- -
-
-
- Show &donate button (restart)
-
-
-
- -
-
-
- &Toolbar
-
-
-
-
-
-
- -
-
-
- &Icon size:
-
-
- opt_toolbar_icon_size
-
-
-
- -
-
-
- -
-
-
- Show &text under icons:
-
-
- opt_toolbar_text
-
-
-
-
+
+
+
+
+ -
+
+
+ Show &splash screen at startup
+
+
+
+ -
+
+
+ Automatically send downloaded &news to ebook reader
+
+
+
+ -
+
+
+ Search as you type
+
+
+ true
+
+
+
+ -
+
+
+ Show &average ratings in the tags browser
+
+
+ true
+
+
+
+ -
+
+
+ Show cover &browser in a separate window (needs restart)
+
+
+
+
+
diff --git a/src/calibre/gui2/dialogs/config/toolbar.py b/src/calibre/gui2/dialogs/config/toolbar.py
index 9b6de47c5e..5d5b0e1bfc 100644
--- a/src/calibre/gui2/dialogs/config/toolbar.py
+++ b/src/calibre/gui2/dialogs/config/toolbar.py
@@ -27,7 +27,9 @@ class BaseModel(QAbstractListModel):
def name_to_action(self, name, gui):
if name == 'Donate':
- return FakeAction(name, 'donate.svg')
+ return FakeAction(name, 'donate.svg',
+ dont_add_to=frozenset(['context-menu',
+ 'context-menu-device']))
if name == 'Location Manager':
return FakeAction(name, None,
_('Switch between library and device views'),
@@ -72,15 +74,19 @@ class AllModel(BaseModel):
def __init__(self, key, gui):
BaseModel.__init__(self)
- current = gprefs['action-layout-'+key]
- all = list(gui.iactions.keys()) + ['Donate']
- all = [x for x in all if x not in current] + [None]
- all = [self.name_to_action(x, gui) for x in all]
- all = [x for x in all if key not in x.dont_add_to]
- all.sort()
+ self.gprefs_name = 'action-layout-'+key
+ current = gprefs[self.gprefs_name]
self.gui = gui
+ self.key = key
+ self._data = self.get_all_actions(current)
- self._data = all
+ def get_all_actions(self, current):
+ all = list(self.gui.iactions.keys()) + ['Donate']
+ all = [x for x in all if x not in current] + [None]
+ all = [self.name_to_action(x, self.gui) for x in all]
+ all = [x for x in all if self.key not in x.dont_add_to]
+ all.sort()
+ return all
def add(self, names):
actions = []
@@ -106,12 +112,17 @@ class AllModel(BaseModel):
self._data = ndata
self.reset()
+ def restore_defaults(self):
+ current = gprefs.defaults[self.gprefs_name]
+ self._data = self.get_all_actions(current)
+ self.reset()
class CurrentModel(BaseModel):
def __init__(self, key, gui):
BaseModel.__init__(self)
- current = gprefs['action-layout-'+key]
+ self.gprefs_name = 'action-layout-'+key
+ current = gprefs[self.gprefs_name]
self._data = [self.name_to_action(x, gui) for x in current]
self.key = key
self.gui = gui
@@ -162,6 +173,27 @@ class CurrentModel(BaseModel):
self.reset()
return rejected
+ def commit(self):
+ old = gprefs[self.gprefs_name]
+ new = []
+ for x in self._data:
+ n = x.name
+ if n.startswith('---'):
+ n = None
+ new.append(n)
+ new = tuple(new)
+ if new != old:
+ defaults = gprefs.defaults[self.gprefs_name]
+ if defaults == new:
+ del gprefs[self.gprefs_name]
+ else:
+ gprefs[self.gprefs_name] = new
+
+ def restore_defaults(self):
+ current = gprefs.defaults[self.gprefs_name]
+ self._data = [self.name_to_action(x, self.gui) for x in current]
+ self.reset()
+
class ToolbarLayout(QWidget, Ui_Form):
@@ -190,6 +222,7 @@ class ToolbarLayout(QWidget, Ui_Form):
self.add_action_button.clicked.connect(self.add_action)
self.remove_action_button.clicked.connect(self.remove_action)
+ self.restore_defaults_button.clicked.connect(self.restore_defaults)
self.action_up_button.clicked.connect(partial(self.move, -1))
self.action_down_button.clicked.connect(partial(self.move, 1))
@@ -230,7 +263,6 @@ class ToolbarLayout(QWidget, Ui_Form):
','.join([a.action_spec[0] for a in not_removed]),
show=True)
-
def move(self, delta, *args):
ci = self.current_actions.currentIndex()
m = self.current_actions.model()
@@ -241,6 +273,16 @@ class ToolbarLayout(QWidget, Ui_Form):
self.current_actions.selectionModel().select(ni,
QItemSelectionModel.ClearAndSelect)
+ def commit(self):
+ for am, cm in self.models.values():
+ cm.commit()
+
+ def restore_defaults(self, *args):
+ for am, cm in self.models.values():
+ cm.restore_defaults()
+ am.restore_defaults()
+
+
if __name__ == '__main__':
from PyQt4.Qt import QApplication
from calibre.gui2.ui import Main
@@ -249,4 +291,5 @@ if __name__ == '__main__':
a = ToolbarLayout(m)
a.show()
app.exec_()
+ a.commit()
diff --git a/src/calibre/gui2/dialogs/config/toolbar.ui b/src/calibre/gui2/dialogs/config/toolbar.ui
index 7456f377bd..091f21c4ae 100644
--- a/src/calibre/gui2/dialogs/config/toolbar.ui
+++ b/src/calibre/gui2/dialogs/config/toolbar.ui
@@ -207,6 +207,13 @@
+ -
+
+
+ Restore to &default
+
+
+
diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py
index 9d8cd7de1c..c983e111d4 100644
--- a/src/calibre/gui2/init.py
+++ b/src/calibre/gui2/init.py
@@ -27,36 +27,10 @@ def partial(*args, **kwargs):
_keep_refs.append(ans)
return ans
-gprefs.defaults['action-layout-context-menu'] = (
- 'Edit Metadata', 'Send To Device', 'Save To Disk',
- 'Connect Share', 'Copy To Library', None,
- 'Convert Books', 'View', 'Open Folder', 'Show Book Details',
- 'Similar Books', None, 'Remove Books',
- )
-
-gprefs.defaults['action-layout-context-menu-device'] = (
- 'View', 'Save To Disk', None, 'Remove Books', None,
- 'Add To Library', 'Edit Collections',
- )
class LibraryViewMixin(object): # {{{
def __init__(self, db):
- lm = QMenu(self)
- def populate_menu(m, items):
- for what in items:
- if what is None:
- m.addSeparator()
- elif what in self.iactions:
- m.addAction(self.iactions[what].qaction)
- populate_menu(lm, gprefs['action-layout-context-menu'])
- dm = QMenu(self)
- populate_menu(dm, gprefs['action-layout-context-menu-device'])
- ec = self.iactions['Edit Collections'].qaction
- self.library_view.set_context_menu(lm, ec)
- for v in (self.memory_view, self.card_a_view, self.card_b_view):
- v.set_context_menu(dm, ec)
-
self.library_view.files_dropped.connect(self.iactions['Add Books'].files_dropped, type=Qt.QueuedConnection)
for func, args in [
('connect_to_search_box', (self.search,
@@ -86,6 +60,23 @@ class LibraryViewMixin(object): # {{{
view = getattr(self, view+'_view')
view.verticalHeader().sectionDoubleClicked.connect(self.iactions['View'].view_specific_book)
+ self.build_context_menus()
+
+ def build_context_menus(self):
+ lm = QMenu(self)
+ def populate_menu(m, items):
+ for what in items:
+ if what is None:
+ m.addSeparator()
+ elif what in self.iactions:
+ m.addAction(self.iactions[what].qaction)
+ populate_menu(lm, gprefs['action-layout-context-menu'])
+ dm = QMenu(self)
+ populate_menu(dm, gprefs['action-layout-context-menu-device'])
+ ec = self.iactions['Edit Collections'].qaction
+ self.library_view.set_context_menu(lm, ec)
+ for v in (self.memory_view, self.card_a_view, self.card_b_view):
+ v.set_context_menu(dm, ec)
def search_done(self, view, ok):
diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py
index 7b06119d13..e20ba61c99 100644
--- a/src/calibre/gui2/layout.py
+++ b/src/calibre/gui2/layout.py
@@ -19,19 +19,6 @@ from calibre.gui2 import config, gprefs
from calibre.gui2.widgets import ComboBoxWithHelp
from calibre import human_readable
-gprefs.defaults['action-layout-toolbar'] = (
- 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View', None,
- 'Choose Library', 'Donate', None, 'Fetch News', 'Save To Disk',
- 'Connect Share', None, 'Remove Books', None, 'Help', 'Preferences',
- )
-
-gprefs.defaults['action-layout-toolbar-device'] = (
- 'Add Books', 'Edit Metadata', None, 'Convert Books', 'View',
- 'Send To Device', None, None, 'Location Manager', None, None,
- 'Fetch News', 'Save To Disk', 'Connect Share', None,
- 'Remove Books', None, 'Help', 'Preferences',
- )
-
class LocationManager(QObject): # {{{
locations_changed = pyqtSignal()
diff --git a/src/calibre/utils/config.py b/src/calibre/utils/config.py
index 0cb9abe67b..9fd1315caa 100644
--- a/src/calibre/utils/config.py
+++ b/src/calibre/utils/config.py
@@ -621,8 +621,9 @@ class XMLConfig(dict):
self.__setitem__(key, val)
def __delitem__(self, key):
- dict.__delitem__(self, key)
- self.commit()
+ if dict.has_key(self, key):
+ dict.__delitem__(self, key)
+ self.commit()
def commit(self):
if hasattr(self, 'file_path') and self.file_path: