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 &notifications 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 &notifications 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: