diff --git a/src/calibre/gui2/preferences/__init__.py b/src/calibre/gui2/preferences/__init__.py index 92689d62f687..26bca987a5ff 100644 --- a/src/calibre/gui2/preferences/__init__.py +++ b/src/calibre/gui2/preferences/__init__.py @@ -114,6 +114,13 @@ def initial_tab_changed(self): def do_on_child_tabs(self, method, *args): r = False for t in self.child_tabs: + lazy_init_called = getattr(t, 'lazy_init_called', True) + if method in ('commit', 'refresh_gui') and not lazy_init_called: + continue + if method == 'restore_defaults' and not lazy_init_called: + if hasattr(t, 'lazy_initialize'): + t.lazy_initialize() + t.lazy_init_called = True r = r | bool(getattr(t, method)(*args)) return r @@ -291,7 +298,7 @@ def __init__(self, parent=None): self.settings = {} self.child_tabs = [] for v in self.__dict__.values(): - if isinstance(v, ConfigTabWidget): + if isinstance(v, LazyConfigWidgetBase): self.child_tabs.append(v) def register(self, name, config_obj, gui_name=None, choices=None, @@ -349,11 +356,30 @@ def get_plugin(category, name): (category, name)) -class ConfigTabWidget(ConfigWidgetBase): +class LazyConfigWidgetBase(ConfigWidgetBase): + ''' + Use this for dialogs that are tabs, accessed either from the left or on the + top. It directly replaces ConfigWidgetBase, supporting the lazy operations. + ''' + + def __init__(self, parent=None): + super().__init__(parent) + self.lazy_init_called = False def set_changed_signal(self, changed_signal): self.changed_signal.connect(changed_signal) + def showEvent(self, event): + # called when the widget is actually displays. We can't do something like + # lazy_genesis because Qt does "things" before showEvent() is called. In + # particular, the register function doesn't work with combo boxes if + # genesis isn't called before everythign else. Why is a mystery. + if not self.lazy_init_called: + if hasattr(self, 'lazy_initialize'): + self.lazy_initialize() + self.lazy_init_called = True + super().showEvent(event) + class ConfigDialog(QDialog): diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index 496296127d91..264bebd0e0ec 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -44,7 +44,6 @@ from calibre import human_readable from calibre.constants import ismacos, iswindows -from calibre.db.categories import is_standard_category from calibre.ebooks.metadata.book.render import DEFAULT_AUTHOR_LINK from calibre.ebooks.metadata.sources.prefs import msprefs from calibre.gui2 import ( @@ -59,13 +58,20 @@ qt_app, question_dialog, ) -from calibre.gui2.actions.show_quickview import get_quickview_action_plugin + from calibre.gui2.custom_column_widgets import get_field_list as em_get_field_list from calibre.gui2.dialogs.quickview import get_qv_field_list from calibre.gui2.library.alternate_views import CM_TO_INCH, auto_height from calibre.gui2.preferences import ConfigWidgetBase, Setting, set_help_tips, test_widget from calibre.gui2.preferences.coloring import EditRules -from calibre.gui2.preferences.look_feel_tabs import DisplayedFields, move_field_down, move_field_up +from calibre.gui2.preferences.look_feel_tabs import ( + DisplayedFields, + export_layout, + import_layout, + move_field_down, + move_field_up, + reset_layout, +) from calibre.gui2.preferences.look_feel_ui import Ui_Form from calibre.gui2.widgets import BusyCursor from calibre.gui2.widgets2 import Dialog @@ -481,12 +487,6 @@ def genesis(self, gui): r('show_sb_all_actions_button', gprefs) # r('show_sb_preference_button', gprefs) r('row_numbers_in_book_list', gprefs) - r('tag_browser_old_look', gprefs) - r('tag_browser_hide_empty_categories', gprefs) - r('tag_browser_always_autocollapse', gprefs) - r('tag_browser_restore_tree_expansion', gprefs) - r('tag_browser_show_tooltips', gprefs) - r('tag_browser_allow_keyboard_focus', gprefs) r('bd_show_cover', gprefs) r('bd_overlay_cover_size', gprefs) r('cover_corner_radius', gprefs) @@ -497,13 +497,6 @@ def genesis(self, gui): r('cover_grid_disk_cache_size', gprefs) r('cover_grid_spacing', gprefs) r('cover_grid_show_title', gprefs) - r('tag_browser_show_counts', gprefs) - r('tag_browser_item_padding', gprefs) - - r('qv_respects_vls', gprefs) - r('qv_dclick_changes_column', gprefs) - r('qv_retkey_changes_column', gprefs) - r('qv_follows_column', gprefs) r('emblem_size', gprefs) r('emblem_position', gprefs, choices=[ @@ -536,10 +529,6 @@ def get_esc_lang(l): choices.insert(1, ((get_language(lul), lul))) r('language', prefs, choices=choices, restart_required=True, setting=LanguageSetting) - r('show_avg_rating', config) - r('show_links_in_tag_browser', gprefs) - r('show_notes_in_tag_browser', gprefs) - r('icons_on_right_in_tag_browser', gprefs) r('disable_animations', config) r('systray_icon', config, restart_required=True) r('show_splash_screen', gprefs) @@ -554,12 +543,6 @@ def get_esc_lang(l): (_('Never'), 'never')] r('toolbar_text', gprefs, choices=choices) - choices = [(_('Disabled'), 'disable'), (_('By first letter'), 'first letter'), - (_('Partitioned'), 'partition')] - r('tags_browser_partition_method', gprefs, choices=choices) - r('tags_browser_collapse_at', gprefs) - r('tags_browser_collapse_fl_at', gprefs) - fm = db.field_metadata choices = sorted(((fm[k]['name'], k) for k in fm.displayable_field_keys() if fm[k]['name']), key=lambda x:sort_key(x[0])) @@ -583,15 +566,6 @@ def get_esc_lang(l): self.current_font = self.initial_font = None self.change_font_button.clicked.connect(self.change_font) - self.display_model = DisplayedFields(self.gui.current_db, self.field_display_order) - self.display_model.dataChanged.connect(self.changed_signal) - self.field_display_order.setModel(self.display_model) - mu = partial(move_field_up, self.field_display_order, self.display_model) - md = partial(move_field_down, self.field_display_order, self.display_model) - self.df_up_button.clicked.connect(mu) - self.df_down_button.clicked.connect(md) - self.field_display_order.set_movement_functions(mu, md) - self.em_display_model = EMDisplayedFields(self.gui.current_db, self.em_display_order) self.em_display_model.dataChanged.connect(self.changed_signal) self.em_display_order.setModel(self.em_display_model) @@ -600,41 +574,9 @@ def get_esc_lang(l): self.em_display_order.set_movement_functions(mu, md) self.em_up_button.clicked.connect(mu) self.em_down_button.clicked.connect(md) - self.em_export_layout_button.clicked.connect(partial(self.export_layout, model=self.em_display_model)) - self.em_import_layout_button.clicked.connect(partial(self.import_layout, model=self.em_display_model)) - self.em_reset_layout_button.clicked.connect(partial(self.reset_layout, model=self.em_display_model)) - - self.qv_display_model = QVDisplayedFields(self.gui.current_db, self.qv_display_order) - self.qv_display_model.dataChanged.connect(self.changed_signal) - self.qv_display_order.setModel(self.qv_display_model) - mu = partial(move_field_up, self.qv_display_order, self.qv_display_model) - md = partial(move_field_down, self.qv_display_order, self.qv_display_model) - self.qv_display_order.set_movement_functions(mu, md) - self.qv_up_button.clicked.connect(mu) - self.qv_down_button.clicked.connect(md) - - self.tb_display_model = TBDisplayedFields(self.gui.current_db, self.tb_display_order, - category_icons=self.gui.tags_view.model().category_custom_icons) - self.tb_display_model.dataChanged.connect(self.changed_signal) - self.tb_display_order.setModel(self.tb_display_model) - self.tb_reset_layout_button.clicked.connect(partial(self.reset_layout, model=self.tb_display_model)) - self.tb_export_layout_button.clicked.connect(partial(self.export_layout, model=self.tb_display_model)) - self.tb_import_layout_button.clicked.connect(partial(self.import_layout, model=self.tb_display_model)) - self.tb_up_button.clicked.connect(self.tb_up_button_clicked) - self.tb_down_button.clicked.connect(self.tb_down_button_clicked) - self.tb_display_order.set_movement_functions(self.tb_up_button_clicked, self.tb_down_button_clicked) - - self.tb_categories_to_part_model = TBPartitionedFields(self.gui.current_db, - self.tb_cats_to_partition, - category_icons=self.gui.tags_view.model().category_custom_icons) - self.tb_categories_to_part_model.dataChanged.connect(self.changed_signal) - self.tb_cats_to_partition.setModel(self.tb_categories_to_part_model) - self.tb_partition_reset_button.clicked.connect(partial(self.reset_layout, - model=self.tb_categories_to_part_model)) - self.tb_partition_export_layout_button.clicked.connect(partial(self.export_layout, - model=self.tb_categories_to_part_model)) - self.tb_partition_import_layout_button.clicked.connect(partial(self.import_layout, - model=self.tb_categories_to_part_model)) + self.em_export_layout_button.clicked.connect(partial(export_layout, self, model=self.em_display_model)) + self.em_import_layout_button.clicked.connect(partial(import_layout, self, model=self.em_display_model)) + self.em_reset_layout_button.clicked.connect(partial(reset_layout, model=self.em_display_model)) self.bd_vertical_cats_model = BDVerticalCats(self.gui.current_db, self.tb_hierarchy_tab.tb_hierarchical_cats) self.bd_vertical_cats_model.dataChanged.connect(self.changed_signal) @@ -690,16 +632,8 @@ def get_esc_lang(l): self.css_highlighter = get_highlighter('css')() self.css_highlighter.apply_theme(get_theme(None)) self.css_highlighter.set_document(self.opt_book_details_css.document()) - self.lazy_tabs = {} for i in range(self.tabWidget.count()): self.sections_view.addItem(QListWidgetItem(self.tabWidget.tabIcon(i), self.tabWidget.tabText(i).replace('&', ''))) - # retrieve tabs and subtabs of look & feel to load their content later when clicking of them - w = self.tabWidget.widget(i).widget() - self.lazy_tabs[(i, None)] = w - if isinstance(w, QTabWidget): - w.currentChanged.connect(partial(self.lazy_tab_operations, i)) - for ii in range(w.count()): - self.lazy_tabs[(i, ii)] = w.widget(ii) self.sections_view.setCurrentRow(self.tabWidget.currentIndex()) self.sections_view.currentRowChanged.connect(self.tabWidget.setCurrentIndex) self.sections_view.setMaximumWidth(self.sections_view.sizeHintForColumn(0) + 16) @@ -728,59 +662,6 @@ def update_color_palette_state(self): enabled = self.opt_ui_style.currentData() == 'calibre' self.button_adjust_colors.setEnabled(enabled) - def export_layout(self, model=None): - filename = choose_save_file(self, 'em_import_export_field_list', - _('Save column list to file'), - filters=[(_('Column list'), ['json'])]) - if filename: - try: - with open(filename, 'w') as f: - json.dump(model.fields, f, indent=1) - except Exception as err: - error_dialog(self, _('Export field layout'), - _('

Could not write field list. Error:
%s')%err, show=True) - - def import_layout(self, model=None): - filename = choose_files(self, 'em_import_export_field_list', - _('Load column list from file'), - filters=[(_('Column list'), ['json'])]) - if filename: - try: - with open(filename[0]) as f: - fields = json.load(f) - model.initialize(pref_data_override=fields) - self.changed_signal.emit() - except Exception as err: - error_dialog(self, _('Import layout'), - _('

Could not read field list. Error:
%s')%err, show=True) - - def reset_layout(self, model=None): - model.initialize(use_defaults=True) - self.changed_signal.emit() - - def tb_down_button_clicked(self): - idx = self.tb_display_order.currentIndex() - if idx.isValid(): - row = idx.row() - model = self.tb_display_model - fields = model.fields - key = fields[row][0] - if not is_standard_category(key): - return - if row < len(fields) and is_standard_category(fields[row+1][0]): - move_field_down(self.tb_display_order, model) - - def tb_up_button_clicked(self): - idx = self.tb_display_order.currentIndex() - if idx.isValid(): - row = idx.row() - model = self.tb_display_model - fields = model.fields - key = fields[row][0] - if not is_standard_category(key): - return - move_field_up(self.tb_display_order, model) - def choose_icon_theme(self): from calibre.gui2.icon_theme import ChooseTheme d = ChooseTheme(self) @@ -833,11 +714,7 @@ def initialize(self): font.append(gprefs.get('font_stretch', QFont.Stretch.Unstretched)) self.current_font = self.initial_font = font self.update_font_display() - self.display_model.initialize() self.em_display_model.initialize() - self.qv_display_model.initialize() - self.tb_display_model.initialize() - self.tb_categories_to_part_model.initialize() self.bd_vertical_cats_model.initialize() db = self.gui.current_db mi = [] @@ -857,10 +734,8 @@ def initialize(self): self.opt_book_details_css.blockSignals(True) self.opt_book_details_css.setPlainText(P('templates/book_details.css', data=True).decode('utf-8')) self.opt_book_details_css.blockSignals(False) - self.tb_focus_label.setVisible(self.opt_tag_browser_allow_keyboard_focus.isChecked()) self.update_color_palette_state() self.opt_gui_layout.setCurrentIndex(0 if self.gui.layout_container.is_wide else 1) - self.lazy_tab_operations(self.tabWidget.currentIndex(), None) def open_cg_cache(self): open_local_file(self.gui.grid_view.thumbnail_cache.location) @@ -870,20 +745,9 @@ def update_cg_cache_size(self, size): _('Current space used: %s') % human_readable(size)) def tab_changed(self, index): - self.lazy_tab_operations(index, None) if self.tabWidget.currentWidget() is self.cover_grid_tab: self.show_current_cache_usage() - def lazy_tab_operations(self, idx_section, idx_subtab): - ''' - Check if the tab has lazy operations. - Perfom the lazy operations only once, the first time the tab is selected. - ''' - tab = self.lazy_tabs.get((idx_section, idx_subtab), None) - if hasattr(tab, 'lazy_populate_content'): - tab.lazy_populate_content() - self.lazy_tabs.pop((idx_section, idx_subtab), None) - def show_current_cache_usage(self): t = Thread(target=self.calc_cache_size) t.daemon = True @@ -912,9 +776,7 @@ def restore_defaults(self): if ofont is not None: self.changed_signal.emit() self.update_font_display() - self.display_model.restore_defaults() self.em_display_model.restore_defaults() - self.qv_display_model.restore_defaults() self.bd_vertical_cats_model.restore_defaults() gprefs.set('tb_search_order', gprefs.defaults['tb_search_order']) self.edit_rules.clear() @@ -986,11 +848,7 @@ def commit(self, *args): is not None else QFont.Stretch.Unstretched) QApplication.setFont(self.font_display.font()) rr = True - self.display_model.commit() self.em_display_model.commit() - self.qv_display_model.commit() - self.tb_display_model.commit() - self.tb_categories_to_part_model.commit() self.bd_vertical_cats_model.commit() self.edit_rules.commit(self.gui.current_db.prefs) self.icon_rules.commit(self.gui.current_db.prefs) @@ -1027,9 +885,6 @@ def refresh_gui(self, gui): gui.library_view.refresh_row_sizing() gui.grid_view.refresh_settings() gui.update_auto_scroll_timeout() - qv = get_quickview_action_plugin() - if qv: - qv.refill_quickview() gui.sb_all_gui_actions_button.setVisible(gprefs['show_sb_all_actions_button']) # gui.sb_preferences_button.setVisible(gprefs['show_sb_preference_button']) diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index 3a88668f44d6..c55a609c8458 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -1307,487 +1307,15 @@ columns". Editing with mouse clicks and the Tab key will be disabled.</p &Tag browser - + Di&splay - - - - - User categories and Saved searches cannot be moved - - - Select the categories to display in the Tag browser, and their &order - - - tb_display_order - - - - - - - - 0 - 200 - - - - true - - - - - - - Move up. User categories and Saved searches cannot be moved. Keyboard shortcut: Ctrl-Up arrow - - - - :/images/arrow-up.png:/images/arrow-up.png - - - - - - - Qt::Vertical - - - - 50 - 40 - - - - - - - - Move down. User categories and Saved searches cannot be moved. Keyboard shortcut: Ctrl-Down arrow - - - - :/images/arrow-down.png:/images/arrow-down.png - - - - - - - - - Click this button to reset the list to its default order. - - - Reset list - - - - - - - <p>Click this button to set the list to one -previously exported. This could be useful if you have several libraries with -similar structure and you want to use the same column order for each one. Columns -in the imported list that aren't in the current library are ignored. Columns in -the library that are not in the imported list are put at the end and marked -as displayable.</p> - - - Import list - - - - - - - <p>Click this button to write the current display -settings to a file. This could be useful if you have several libraries with similar -structure and you want to use the same column order for each one.</p> - - - Export list - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Show the average rating per item indication in the Tag browser - - - Show &average ratings - - - true - - - - - - - Show an icon if the item has an attached link - - - Show &links icons - - - true - - - - - - - Show &tooltips - - - - - - - <p>Show counts for items in the Tag browser. Such as the number of books -by each author, the number of authors, etc. If you turn it off, you can still -see the counts by hovering your mouse over any item.</p> - - - Show &counts - - - - - - - Show an icon if the item has an attached note - - - Show &notes icons - - - true - - - - - - - Use &alternating row colors - - - - - - - <p>When checked, calibre will automatically hide any category -(a column, custom or standard) that has no items to show. For example, some -categories might not have values when using Virtual libraries. Checking this -box will cause these empty categories to be hidden.</p> - - - Hide empt&y categories (columns) - - - - - - - If checked the notes and links icons will be placed at the right, after -the count and in columns. If unchecked, the icons will be placed immediately after the text, -to the left of the count and not in columns. - - - Place icons on the &right, in columns - - - true - - - - - - - <p>When checked, Find in the Tag browser will show all items -that match the search instead of the first one. If Hide empty categories is -also checked then only categories containing a matched item will be shown.</p> - - - Find &shows all items that match - - - - - - - <p>Ensure the last "used" item in the Tag browser is visible when opening a library. -An item is "used" when it is expanded, collapsed, or clicked.</p> - - - Expand tr&ee to show last used item - - - - - - - - - - - <p>When checked, the Tag browser can get keyboard focus, allowing -use of the keyboard to navigate the tree using the arrow keys. The Enter key simulates -a click on the selected item. The keyboard shortcut 'Tag browser / -Give the Tag browser keyboard focus' changes the keyboard focus without -using the mouse.</p> - - - Allow the Tag browser to have keyboard &focus - - - - - - - margin-left: 1.5em - - - <p style="text-indent: 2em; font-size:smaller"> -If you enable this option then you should set a keyboard shortcut to -focus the Tag browser under -<code>Preferences-&gt;Shortcuts-&gt;Tag browser-&gt;Give -the Tag browser keyboard focus</code></p> - - - true - - - - - - - - - QFormLayout::ExpandingFieldsGrow - - - - - Spacing between &items: - - - opt_tag_browser_item_padding - - - - - - - <p>The spacing between consecutive items in the Tag browser. -In units of (ex) which is the approximate height of the letter 'x' in the -currently used font.</p> - - - ex - - - 1 - - - -1.000000000000000 - - - 2.000000000000000 - - - 0.100000000000000 - - - - - - - + &Partitioning and collapsing - - - - - - - QFormLayout::ExpandingFieldsGrow - - - - - &Category partitioning method: - - - opt_tags_browser_partition_method - - - - - - - <p>Choose how Tag browser subcategories are displayed when -there are more items than the limit. Select by first -letter to see an A, B, C list. Choose partitioned to -have a list of fixed-sized groups. Set to disabled -if you never want subcategories</p> - - - - - - - Combine letters &when fewer items than: - - - opt_tags_browser_collapse_fl_at - - - - - - - <p>If collapsing by first letter, combine adjacent letters together if -there are fewer items under a letter than specified here. If the partition method is -not set to first letter, this value is ignored. Set to zero to disable.</p> - - - 10000 - - - - - - - Co&llapse when more items than: - - - opt_tags_browser_collapse_at - - - - - - - <p>If a Tag browser category has more than this number of items, it is divided -up into subcategories. If the partition method is set to disable, this value is ignored.</p> - - - 10000 - - - - - - - - - <p>Check the box for categories that are to -be partitioned using the criteria above. Uncheck the box if you don't want to -partition a category even if the number of items is larger than -the value shown above. This option can be used to -avoid collapsing hierarchical categories that have only -a few top-level elements.</p> - - - Select categories to &partition: - - - tb_cats_to_partition - - - - - - - - 0 - 200 - - - - true - - - - - - - - - Click this button to reset the list to its default order. - - - Reset list - - - - - - - <p>Click this button to set the list to one -previously exported. This could be useful if you have several libraries with -similar structure and you want to use the same for each one.</p> - - - Import list - - - - - - - <p>Click this button to write the current display -settings to a file. This could be useful if you have several libraries with similar -structure and you want to use the same for each one.</p> - - - Export list - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - @@ -1800,7 +1328,7 @@ structure and you want to use the same for each one.</p> - + :/images/cover_flow.png:/images/cover_flow.png @@ -1808,13 +1336,8 @@ structure and you want to use the same for each one.</p> Cover &browser - - - - - - + :/images/quickview.png:/images/quickview.png @@ -1822,108 +1345,6 @@ structure and you want to use the same for each one.</p> &Quickview - - - - - - - <p>Check this box to make Quickview show books only in the -current Virtual library. If unchecked, Quickview ignores Virtual libraries. If -unchecked then only row changes are taken into account.</p> - - - &Apply Virtual libraries - - - - - - - <p>Check this box to make Quickview change the column being examined -when the column in the book list is changed using the cursor arrow keys</p> - - - &Change Quickview item when book list column changes - - - - - - - <p>Pressing Enter in a cell changes both the book and the -column being examined (the left-hand panel)</p> - - - &Pressing Enter changes the examined column - - - - - - - <p>Double-clicking in a cell changes both the book and the -column being examined (the left-hand panel)</p> - - - &Double click changes examined column - - - - - - - - - Select columns to display - - - - - - Move up. Keyboard shortcut: Ctrl-Up arrow - - - - :/images/arrow-up.png:/images/arrow-up.png - - - - - - - Move down. Keyboard shortcut: Ctrl-Down arrow - - - - :/images/arrow-down.png:/images/arrow-down.png - - - - - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - @@ -1961,6 +1382,16 @@ column being examined (the left-hand panel)</p> QWidget

calibre/gui2/preferences/look_feel.h
+ + TbDisplayTab + ConfigWidget +
calibre/gui2/preferences/look_feel_tabs.tb_display.h
+
+ + TbPartitioningTab + ConfigWidget +
calibre/gui2/preferences/look_feel_tabs.tb_partitioning.h
+
TbIconRulesTab ConfigWidget @@ -1976,6 +1407,11 @@ column being examined (the left-hand panel)</p> ConfigWidget
calibre/gui2/preferences/look_feel_tabs.cover_view.h
+ + QuickviewTab + ConfigWidget +
calibre/gui2/preferences/look_feel_tabs.tb_quickview.h
+
@@ -1997,21 +1433,5 @@ column being examined (the left-hand panel)</p> - - opt_tag_browser_allow_keyboard_focus - toggled(bool) - tb_focus_label - setVisible(bool) - - - 275 - 528 - - - 358 - 555 - - - diff --git a/src/calibre/gui2/preferences/look_feel_tabs/__init__.py b/src/calibre/gui2/preferences/look_feel_tabs/__init__.py index 6cae188d2a4e..4ad4a9560ff2 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/__init__.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/__init__.py @@ -5,9 +5,17 @@ __copyright__ = '2011, Kovid Goyal ' __docformat__ = 'restructuredtext en' +import json from qt.core import QAbstractListModel, QIcon, QItemSelectionModel, Qt +from calibre.gui2 import ( + choose_files, + choose_save_file, + config, + error_dialog, + gprefs, +) from calibre.gui2.book_details import get_field_list @@ -100,6 +108,36 @@ def move(self, idx, delta): self.changed = True return idx +def export_layout(in_widget, model=None): + filename = choose_save_file(in_widget, 'look_feel_prefs_import_export_field_list', + _('Save column list to file'), + filters=[(_('Column list'), ['json'])]) + if filename: + try: + with open(filename, 'w') as f: + json.dump(model.fields, f, indent=1) + except Exception as err: + error_dialog(in_widget, _('Export field layout'), + _('

Could not write field list. Error:
%s')%err, show=True) + +def import_layout(in_widget, model=None): + filename = choose_files(in_widget, 'look_feel_prefs_import_export_field_list', + _('Load column list from file'), + filters=[(_('Column list'), ['json'])]) + if filename: + try: + with open(filename[0]) as f: + fields = json.load(f) + model.initialize(pref_data_override=fields) + in_widget.changed_signal.emit() + except Exception as err: + error_dialog(in_widget, _('Import layout'), + _('

Could not read field list. Error:
%s')%err, show=True) + +def reset_layout(in_widget, model=None): + model.initialize(use_defaults=True) + in_widget.changed_signal.emit() + def move_field_up(widget, model): idx = widget.currentIndex() diff --git a/src/calibre/gui2/preferences/look_feel_tabs/cover_view.py b/src/calibre/gui2/preferences/look_feel_tabs/cover_view.py index 16e35bd0102c..606e849bf163 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/cover_view.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/cover_view.py @@ -2,7 +2,7 @@ __license__ = 'GPL v3' -__copyright__ = '2010, Kovid Goyal ' +__copyright__ = '2025, Kovid Goyal ' __docformat__ = 'restructuredtext en' @@ -10,15 +10,15 @@ from calibre.gui2 import config, gprefs from calibre.gui2.dialogs.template_dialog import TemplateDialog -from calibre.gui2.preferences import ConfigTabWidget, ConfigWidgetBase, set_help_tips +from calibre.gui2.preferences import LazyConfigWidgetBase, ConfigWidgetBase, set_help_tips from calibre.gui2.preferences.look_feel_tabs.cover_view_ui import Ui_Form -class CoverView(ConfigTabWidget, Ui_Form): +class CoverView(LazyConfigWidgetBase, Ui_Form): def genesis(self, gui): self.gui = gui - db = gui.library_view.model().db + db = self.gui.library_view.model().db r = self.register r('books_autoscroll_time', gprefs) @@ -41,7 +41,7 @@ def genesis(self, gui): self.fs_help_msg.setText(self.fs_help_msg.text()%( QKeySequence(QKeySequence.StandardKey.FullScreen).toString(QKeySequence.SequenceFormat.NativeText))) - def initialize(self): + def lazy_initialize(self): ConfigWidgetBase.initialize(self) set_help_tips(self.opt_cover_browser_narrow_view_position, _( 'This option controls the position of the cover browser when using the Narrow user ' @@ -51,11 +51,25 @@ def initialize(self): 'list. This option has no effect when using the Wide user interface layout.')) def edit_cb_title_template(self): - t = TemplateDialog(self, self.opt_cover_browser_title_template.text(), fm=self.gui.current_db.field_metadata) + rows = self.gui.library_view.selectionModel().selectedRows() + mi = None + db = self.gui.current_db.new_api + if rows: + ids = list(map(self.gui.library_view.model().id, rows)) + mi = [] + for bk in ids[0:min(10, len(ids))]: + mi.append(db.get_proxy_metadata(bk)) + t = TemplateDialog(self, self.opt_cover_browser_title_template.text(), mi=mi, fm=db.field_metadata) t.setWindowTitle(_('Edit template for caption')) if t.exec(): self.opt_cover_browser_title_template.setText(t.rule[1]) + def commit(self): + return ConfigWidgetBase.commit(self) + + def restore_defaults(self): + ConfigWidgetBase.restore_defaults(self) + def refresh_gui(self, gui): gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections']) gui.cover_flow.setPreserveAspectRatio(gprefs['cb_preserve_aspect_ratio']) diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_display.py b/src/calibre/gui2/preferences/look_feel_tabs/tb_display.py new file mode 100644 index 000000000000..70345d89d2ad --- /dev/null +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_display.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + + +__license__ = 'GPL v3' +__copyright__ = '2025, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from functools import partial + +from calibre.db.categories import is_standard_category +from calibre.gui2 import config, gprefs +from calibre.gui2.preferences import ConfigWidgetBase, LazyConfigWidgetBase +from calibre.gui2.preferences.look_feel_tabs import ( + DisplayedFields, + import_layout, + export_layout, + move_field_down, + move_field_up, + reset_layout + ) +from calibre.gui2.preferences.look_feel_tabs.tb_display_ui import Ui_Form + +class TBDisplayedFields(DisplayedFields): # {{{ + # The code in this class depends on the fact that the tag browser is + # initialized before this class is instantiated. + + def __init__(self, db, parent=None, category_icons=None): + DisplayedFields.__init__(self, db, parent, category_icons=category_icons) + from calibre.gui2.ui import get_gui + self.gui = get_gui() + + def initialize(self, use_defaults=False, pref_data_override=None): + tv = self.gui.tags_view + cat_ord = tv.model().get_ordered_categories(use_defaults=use_defaults, + pref_data_override=pref_data_override) + if use_defaults: + hc = [] + self.changed = True + elif pref_data_override: + hc = [k for k,v in pref_data_override if not v] + self.changed = True + else: + hc = tv.hidden_categories + + self.beginResetModel() + self.fields = [[x, x not in hc] for x in cat_ord] + self.endResetModel() + + def commit(self): + if self.changed: + self.db.prefs.set('tag_browser_hidden_categories', [k for k,v in self.fields if not v]) + self.db.prefs.set('tag_browser_category_order', [k for k,v in self.fields]) +# }}} + + +class TbDisplayTab(LazyConfigWidgetBase, Ui_Form): + + def genesis(self, gui): + self.gui = gui + r = self.register + r('tag_browser_old_look', gprefs) + r('tag_browser_hide_empty_categories', gprefs) + r('tag_browser_always_autocollapse', gprefs) + r('tag_browser_restore_tree_expansion', gprefs) + r('tag_browser_show_tooltips', gprefs) + r('tag_browser_allow_keyboard_focus', gprefs) + r('tag_browser_show_counts', gprefs) + r('tag_browser_item_padding', gprefs) + r('show_avg_rating', config) + r('show_links_in_tag_browser', gprefs) + r('show_notes_in_tag_browser', gprefs) + r('icons_on_right_in_tag_browser', gprefs) + + self.tb_display_model = TBDisplayedFields(self.gui.current_db, self.tb_display_order, + category_icons=self.gui.tags_view.model().category_custom_icons) + self.tb_display_model.dataChanged.connect(self.changed_signal) + self.tb_display_order.setModel(self.tb_display_model) + self.tb_reset_layout_button.clicked.connect(partial(reset_layout, self, model=self.tb_display_model)) + self.tb_export_layout_button.clicked.connect(partial(export_layout, self, model=self.tb_display_model)) + self.tb_import_layout_button.clicked.connect(partial(import_layout, self, model=self.tb_display_model)) + self.tb_up_button.clicked.connect(self.tb_up_button_clicked) + self.tb_down_button.clicked.connect(self.tb_down_button_clicked) + self.tb_display_order.set_movement_functions(self.tb_up_button_clicked, self.tb_down_button_clicked) + + def lazy_initialize(self): + self.tb_display_model.initialize() + self.tb_focus_label.setVisible(self.opt_tag_browser_allow_keyboard_focus.isChecked()) + + def tb_down_button_clicked(self): + idx = self.tb_display_order.currentIndex() + if idx.isValid(): + row = idx.row() + model = self.tb_display_model + fields = model.fields + key = fields[row][0] + if not is_standard_category(key): + return + if row < len(fields) and is_standard_category(fields[row+1][0]): + move_field_down(self.tb_display_order, model) + + def tb_up_button_clicked(self): + idx = self.tb_display_order.currentIndex() + if idx.isValid(): + row = idx.row() + model = self.tb_display_model + fields = model.fields + key = fields[row][0] + if not is_standard_category(key): + return + move_field_up(self.tb_display_order, model) + + def restore_defaults(self): + ConfigWidgetBase.restore_defaults(self) + self.tb_display_model.restore_defaults() + + def commit(self): + self.tb_display_model.commit() + return ConfigWidgetBase.commit(self) diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_display.ui b/src/calibre/gui2/preferences/look_feel_tabs/tb_display.ui new file mode 100644 index 000000000000..893b1f93bb50 --- /dev/null +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_display.ui @@ -0,0 +1,360 @@ + + + Form + + + + 0 + 0 + 1096 + 791 + + + + Form + + + + + + User categories and Saved searches cannot be moved + + + Select the categories to display in the Tag browser, and their &order + + + tb_display_order + + + + + + + + 0 + 200 + + + + true + + + + + + + Move up. User categories and Saved searches cannot be moved. Keyboard shortcut: Ctrl-Up arrow + + + + :/images/arrow-up.png:/images/arrow-up.png + + + + + + + Qt::Vertical + + + + 50 + 40 + + + + + + + + Move down. User categories and Saved searches cannot be moved. Keyboard shortcut: Ctrl-Down arrow + + + + :/images/arrow-down.png:/images/arrow-down.png + + + + + + + + + Click this button to reset the list to its default order. + + + Reset list + + + + + + + <p>Click this button to set the list to one +previously exported. This could be useful if you have several libraries with +similar structure and you want to use the same column order for each one. Columns +in the imported list that aren't in the current library are ignored. Columns in +the library that are not in the imported list are put at the end and marked +as displayable.</p> + + + Import list + + + + + + + <p>Click this button to write the current display +settings to a file. This could be useful if you have several libraries with similar +structure and you want to use the same column order for each one.</p> + + + Export list + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Show the average rating per item indication in the Tag browser + + + Show &average ratings + + + true + + + + + + + Show an icon if the item has an attached link + + + Show &links icons + + + true + + + + + + + Show &tooltips + + + + + + + <p>Show counts for items in the Tag browser. Such as the number of books +by each author, the number of authors, etc. If you turn it off, you can still +see the counts by hovering your mouse over any item.</p> + + + Show &counts + + + + + + + Show an icon if the item has an attached note + + + Show &notes icons + + + true + + + + + + + Use &alternating row colors + + + + + + + <p>When checked, calibre will automatically hide any category +(a column, custom or standard) that has no items to show. For example, some +categories might not have values when using Virtual libraries. Checking this +box will cause these empty categories to be hidden.</p> + + + Hide empt&y categories (columns) + + + + + + + If checked the notes and links icons will be placed at the right, after +the count and in columns. If unchecked, the icons will be placed immediately after the text, +to the left of the count and not in columns. + + + Place icons on the &right, in columns + + + true + + + + + + + <p>When checked, Find in the Tag browser will show all items +that match the search instead of the first one. If Hide empty categories is +also checked then only categories containing a matched item will be shown.</p> + + + Find &shows all items that match + + + + + + + <p>Ensure the last "used" item in the Tag browser is visible when opening a library. +An item is "used" when it is expanded, collapsed, or clicked.</p> + + + Expand tr&ee to show last used item + + + + + + + + + + + <p>When checked, the Tag browser can get keyboard focus, allowing +use of the keyboard to navigate the tree using the arrow keys. The Enter key simulates +a click on the selected item. The keyboard shortcut 'Tag browser / +Give the Tag browser keyboard focus' changes the keyboard focus without +using the mouse.</p> + + + Allow the Tag browser to have keyboard &focus + + + + + + + margin-left: 1.5em + + + <p style="text-indent: 2em; font-size:smaller"> +If you enable this option then you should set a keyboard shortcut to +focus the Tag browser under +<code>Preferences-&gt;Shortcuts-&gt;Tag browser-&gt;Give +the Tag browser keyboard focus</code></p> + + + true + + + + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + Spacing between &items: + + + opt_tag_browser_item_padding + + + + + + + <p>The spacing between consecutive items in the Tag browser. +In units of (ex) which is the approximate height of the letter 'x' in the +currently used font.</p> + + + ex + + + 1 + + + -1.000000000000000 + + + 2.000000000000000 + + + 0.100000000000000 + + + + + + + + + + ListViewWithMoveByKeyPress + QListView +

calibre/gui2/preferences.h
+ + + ListWidgetWithMoveByKeyPress + QListWidget +
calibre/gui2/preferences.h
+
+ + + + opt_tag_browser_allow_keyboard_focus + toggled(bool) + tb_focus_label + setVisible(bool) + + + 275 + 528 + + + 358 + 555 + + + + + diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_hierarchy.py b/src/calibre/gui2/preferences/look_feel_tabs/tb_hierarchy.py index 2f91c0aa47a0..ff1b40d22fa8 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/tb_hierarchy.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_hierarchy.py @@ -11,7 +11,7 @@ from qt.core import QListWidgetItem, Qt from calibre.gui2 import choose_files, choose_save_file, error_dialog, gprefs -from calibre.gui2.preferences import ConfigTabWidget +from calibre.gui2.preferences import LazyConfigWidgetBase from calibre.gui2.preferences.look_feel_tabs import DisplayedFields from calibre.gui2.preferences.look_feel_tabs.tb_hierarchy_ui import Ui_Form @@ -54,18 +54,16 @@ def commit(self): # }}} -class TbHierarchyTab(ConfigTabWidget, Ui_Form): +class TbHierarchyTab(LazyConfigWidgetBase, Ui_Form): def genesis(self, gui): self.gui = gui - self.tab_opened = False self.tb_search_order_up_button.clicked.connect(self.move_tb_search_up) self.tb_search_order_down_button.clicked.connect(self.move_tb_search_down) self.tb_search_order.set_movement_functions(self.move_tb_search_up, self.move_tb_search_down) self.tb_search_order_reset_button.clicked.connect(self.reset_tb_search_order) - def lazy_populate_content(self): - self.tab_opened = True + def lazy_initialize(self): self.fill_tb_search_order_box() self.tb_hierarchical_cats_model = TBHierarchicalFields(self.gui.current_db, self.tb_hierarchical_cats, @@ -170,7 +168,10 @@ def import_layout(self, model=None): error_dialog(self, _('Import layout'), _('

Could not read field list. Error:
%s')%err, show=True) + def restore_defaults(self): + self.tb_hierarchical_cats_model.restore_defaults() + self.reset_tb_search_order() + def commit(self): - if self.tab_opened: - self.tb_search_order_commit() - self.tb_hierarchical_cats_model.commit() + self.tb_search_order_commit() + self.tb_hierarchical_cats_model.commit() diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_icon_rules.py b/src/calibre/gui2/preferences/look_feel_tabs/tb_icon_rules.py index 5b9f7bed8538..f8b836172c07 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/tb_icon_rules.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_icon_rules.py @@ -2,7 +2,7 @@ __license__ = 'GPL v3' -__copyright__ = '2010, Kovid Goyal ' +__copyright__ = '2025, Kovid Goyal ' __docformat__ = 'restructuredtext en' import copy @@ -14,7 +14,7 @@ from calibre.constants import config_dir from calibre.db.constants import TEMPLATE_ICON_INDICATOR from calibre.gui2 import gprefs -from calibre.gui2.preferences import ConfigTabWidget, ConfigWidgetBase +from calibre.gui2.preferences import ConfigWidgetBase, LazyConfigWidgetBase from calibre.gui2.preferences.look_feel_tabs.tb_icon_rules_ui import Ui_Form DELETED_COLUMN = 0 @@ -98,7 +98,7 @@ def __init__(self, txt, for_child): self.setIcon(QIcon.cached_icon(icon)) -class TbIconRulesTab(ConfigTabWidget, Ui_Form): +class TbIconRulesTab(LazyConfigWidgetBase, Ui_Form): def genesis(self, gui): self.gui = gui @@ -147,7 +147,7 @@ def genesis(self, gui): except Exception: pass - def lazy_populate_content(self): + def lazy_initialize(self): field_metadata = self.gui.current_db.field_metadata category_icons = self.gui.tags_view.model().category_custom_icons v = gprefs['tags_browser_value_icons'] @@ -256,7 +256,6 @@ def do_sort(self, section): self.rules_table.sortByColumn(FOR_CHILDREN_COLUMN, Qt.SortOrder(self.for_children_order)) def commit(self): - rr = ConfigWidgetBase.commit(self) v = copy.deepcopy(gprefs['tags_browser_value_icons']) for r in range(self.rules_table.rowCount()): cat_item = self.rules_table.item(r, CATEGORY_COLUMN) @@ -275,4 +274,4 @@ def commit(self): if len(v[category]) == 0: v.pop(category, None) gprefs['tags_browser_value_icons'] = v - return rr + return ConfigWidgetBase.commit(self) diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_partitioning.py b/src/calibre/gui2/preferences/look_feel_tabs/tb_partitioning.py new file mode 100644 index 000000000000..73a3691b3b0d --- /dev/null +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_partitioning.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python + + +__license__ = 'GPL v3' +__copyright__ = '2025, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + + +from functools import partial + +from calibre.gui2 import gprefs +from calibre.gui2.preferences import ConfigWidgetBase, LazyConfigWidgetBase +from calibre.gui2.preferences.look_feel_tabs import DisplayedFields, export_layout, import_layout, reset_layout +from calibre.gui2.preferences.look_feel_tabs.tb_partitioning_ui import Ui_Form + + +class TBPartitionedFields(DisplayedFields): # {{{ + # The code in this class depends on the fact that the tag browser is + # initialized before this class is instantiated. + + def __init__(self, db, parent=None, category_icons=None): + DisplayedFields.__init__(self, db, parent, category_icons=category_icons) + from calibre.gui2.ui import get_gui + self.gui = get_gui() + + def filter_user_categories(self, tv): + cats = tv.model().categories + answer = {} + filtered = set() + for key,name in cats.items(): + if key.startswith('@'): + key = key.partition('.')[0] + name = key[1:] + if key not in filtered: + answer[key] = name + filtered.add(key) + return answer + + def initialize(self, use_defaults=False, pref_data_override=None): + tv = self.gui.tags_view + cats = self.filter_user_categories(tv) + ans = [] + if use_defaults: + ans = [[k, True] for k in cats.keys()] + self.changed = True + elif pref_data_override: + po = {k:v for k,v in pref_data_override} + ans = [[k, po.get(k, True)] for k in cats.keys()] + self.changed = True + else: + # Check if setting not migrated yet + cats_to_partition = frozenset(self.db.prefs.get('tag_browser_dont_collapse', gprefs.get('tag_browser_dont_collapse')) or ()) + for key in cats: + ans.append([key, key not in cats_to_partition]) + self.beginResetModel() + self.fields = ans + self.endResetModel() + + def commit(self): + if self.changed: + # Migrate to a per-library setting + self.db.prefs.set('tag_browser_dont_collapse', [k for k,v in self.fields if not v]) +# }}} + + +class TbPartitioningTab(LazyConfigWidgetBase, Ui_Form): + + def genesis(self, gui): + self.gui = gui + r = self.register + + choices = [(_('Disabled'), 'disable'), (_('By first letter'), 'first letter'), + (_('Partitioned'), 'partition')] + r('tags_browser_partition_method', gprefs, choices=choices) + r('tags_browser_collapse_at', gprefs) + r('tags_browser_collapse_fl_at', gprefs) + + self.tb_categories_to_part_model = TBPartitionedFields(self.gui.current_db, + self.tb_cats_to_partition, + category_icons=self.gui.tags_view.model().category_custom_icons) + self.tb_categories_to_part_model.dataChanged.connect(self.changed_signal) + self.tb_cats_to_partition.setModel(self.tb_categories_to_part_model) + self.tb_partition_reset_button.clicked.connect(partial(reset_layout, self, + model=self.tb_categories_to_part_model)) + self.tb_partition_export_layout_button.clicked.connect(partial(export_layout, self, + model=self.tb_categories_to_part_model)) + self.tb_partition_import_layout_button.clicked.connect(partial(import_layout, self, + model=self.tb_categories_to_part_model)) + + def lazy_initialize(self): + self.tb_categories_to_part_model.initialize() + + def commit(self): + self.tb_categories_to_part_model.commit() + return ConfigWidgetBase.commit(self) + + + diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_partitioning.ui b/src/calibre/gui2/preferences/look_feel_tabs/tb_partitioning.ui new file mode 100644 index 000000000000..e93be6e29c87 --- /dev/null +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_partitioning.ui @@ -0,0 +1,176 @@ + + + Form + + + + 0 + 0 + 1035 + 547 + + + + Form + + + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + &Category partitioning method: + + + opt_tags_browser_partition_method + + + + + + + <p>Choose how Tag browser subcategories are displayed when +there are more items than the limit. Select by first +letter to see an A, B, C list. Choose partitioned to +have a list of fixed-sized groups. Set to disabled +if you never want subcategories</p> + + + + + + + Combine letters &when fewer items than: + + + opt_tags_browser_collapse_fl_at + + + + + + + <p>If collapsing by first letter, combine adjacent letters together if +there are fewer items under a letter than specified here. If the partition method is +not set to first letter, this value is ignored. Set to zero to disable.</p> + + + 10000 + + + + + + + Co&llapse when more items than: + + + opt_tags_browser_collapse_at + + + + + + + <p>If a Tag browser category has more than this number of items, it is divided +up into subcategories. If the partition method is set to disable, this value is ignored.</p> + + + 10000 + + + + + + + + + <p>Check the box for categories that are to +be partitioned using the criteria above. Uncheck the box if you don't want to +partition a category even if the number of items is larger than +the value shown above. This option can be used to +avoid collapsing hierarchical categories that have only +a few top-level elements.</p> + + + Select categories to &partition: + + + tb_cats_to_partition + + + + + + + + 0 + 200 + + + + true + + + + + + + + + Click this button to reset the list to its default order. + + + Reset list + + + + + + + <p>Click this button to set the list to one +previously exported. This could be useful if you have several libraries with +similar structure and you want to use the same for each one.</p> + + + Import list + + + + + + + <p>Click this button to write the current display +settings to a file. This could be useful if you have several libraries with similar +structure and you want to use the same for each one.</p> + + + Export list + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + \ No newline at end of file diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_quickview.py b/src/calibre/gui2/preferences/look_feel_tabs/tb_quickview.py new file mode 100644 index 000000000000..17dc7f4f0358 --- /dev/null +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_quickview.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + + +__license__ = 'GPL v3' +__copyright__ = '2025, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from functools import partial + +from calibre.gui2 import gprefs +from calibre.gui2.actions.show_quickview import get_quickview_action_plugin +from calibre.gui2.dialogs.quickview import get_qv_field_list +from calibre.gui2.preferences import LazyConfigWidgetBase, ConfigWidgetBase +from calibre.gui2.preferences.look_feel_tabs import DisplayedFields, move_field_down, move_field_up +from calibre.gui2.preferences.look_feel_tabs.tb_quickview_ui import Ui_Form + +class QVDisplayedFields(DisplayedFields): # {{{ + + def __init__(self, db, parent=None): + DisplayedFields.__init__(self, db, parent) + + def initialize(self, use_defaults=False): + self.beginResetModel() + self.fields = [[x[0], x[1]] for x in + get_qv_field_list(self.db.field_metadata, use_defaults=use_defaults)] + self.endResetModel() + self.changed = True + + def commit(self): + if self.changed: + self.db.new_api.set_pref('qv_display_fields', self.fields) + +# }}} + + +class QuickviewTab(LazyConfigWidgetBase, Ui_Form): + + def genesis(self, gui): + self.gui = gui + r = self.register + + r('qv_respects_vls', gprefs) + r('qv_dclick_changes_column', gprefs) + r('qv_retkey_changes_column', gprefs) + r('qv_follows_column', gprefs) + + self.qv_display_model = QVDisplayedFields(self.gui.current_db, self.qv_display_order) + self.qv_display_model.dataChanged.connect(self.changed_signal) + self.qv_display_order.setModel(self.qv_display_model) + + mu = partial(move_field_up, self.qv_display_order, self.qv_display_model) + md = partial(move_field_down, self.qv_display_order, self.qv_display_model) + self.qv_display_order.set_movement_functions(mu, md) + self.qv_up_button.clicked.connect(mu) + self.qv_down_button.clicked.connect(md) + + def lazy_initialize(self): + self.qv_display_model.initialize() + + def restore_defaults(self): + ConfigWidgetBase.restore_defaults(self) + self.qv_display_model.restore_defaults() + + def refresh_gui(self, gui): + qv = get_quickview_action_plugin() + if qv: + qv.refill_quickview() + + def commit(self, *args): + rr = ConfigWidgetBase.commit(self, *args) + self.qv_display_model.commit() + return rr + + diff --git a/src/calibre/gui2/preferences/look_feel_tabs/tb_quickview.ui b/src/calibre/gui2/preferences/look_feel_tabs/tb_quickview.ui new file mode 100644 index 000000000000..cf4a3174ec7d --- /dev/null +++ b/src/calibre/gui2/preferences/look_feel_tabs/tb_quickview.ui @@ -0,0 +1,125 @@ + + + Form + + + + :/images/cover_flow.png:/images/cover_flow.png + + + + + + + + <p>Check this box to make Quickview show books only in the +current Virtual library. If unchecked, Quickview ignores Virtual libraries. If +unchecked then only row changes are taken into account.</p> + + + &Apply Virtual libraries + + + + + + + <p>Check this box to make Quickview change the column being examined +when the column in the book list is changed using the cursor arrow keys</p> + + + &Change Quickview item when book list column changes + + + + + + + <p>Pressing Enter in a cell changes both the book and the +column being examined (the left-hand panel)</p> + + + &Pressing Enter changes the examined column + + + + + + + <p>Double-clicking in a cell changes both the book and the +column being examined (the left-hand panel)</p> + + + &Double click changes examined column + + + + + + + + + Select columns to display + + + + + + Move up. Keyboard shortcut: Ctrl-Up arrow + + + + :/images/arrow-up.png:/images/arrow-up.png + + + + + + + Move down. Keyboard shortcut: Ctrl-Down arrow + + + + :/images/arrow-down.png:/images/arrow-down.png + + + + + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + ListViewWithMoveByKeyPress + QListView +

calibre/gui2/preferences.h
+ + + ListWidgetWithMoveByKeyPress + QListWidget +
calibre/gui2/preferences.h
+
+ + + \ No newline at end of file diff --git a/src/calibre/gui2/preferences/main.py b/src/calibre/gui2/preferences/main.py index caf6d121e7a0..91ee4407a8ef 100644 --- a/src/calibre/gui2/preferences/main.py +++ b/src/calibre/gui2/preferences/main.py @@ -418,6 +418,7 @@ def commit(self, *args): return self.close_after_initial or (must_restart and rc) or do_restart def restore_defaults(self, *args): + self.showing_widget.do_on_child_tabs('restore_defaults') self.showing_widget.restore_defaults() def on_shutdown(self):