Exemple #1
0
class ConfigWidget(ConfigWidgetBase, Ui_Form):

    size_calculated = pyqtSignal(object)

    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r('gui_layout', config, restart_required=True, choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('ui_style', gprefs, restart_required=True, choices=[(_('System default'), 'system'), (_('Calibre style'),
                    'calibre')])
        r('book_list_tooltips', gprefs)
        r('tag_browser_old_look', gprefs, restart_required=True)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size', gprefs)
        r('cover_grid_disk_cache_size', gprefs)
        r('cover_grid_spacing', gprefs)
        r('cover_grid_show_title', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('show_rating_in_cover_browser', gprefs)
        r('emblem_size', gprefs)
        r('emblem_position', gprefs, choices=[
            (_('Left'), 'left'), (_('Top'), 'top'), (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        if islinux or isbsd:
            self.opt_systray_icon.setEnabled(False)
            self.opt_systray_icon.setText(_('System tray icon is disabled because of bugs in Qt 5'))
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
            (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'), (_('Always'), 'always'),
            (_('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('default_author_link', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        self.search_library_for_author_button.clicked.connect(
            lambda : self.opt_default_author_link.setText('search-calibre'))

        choices = set([k for k in db.field_metadata.all_field_keys()
                if (db.field_metadata[k]['is_category'] and
                   (db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']) and
                    not db.field_metadata[k]['display'].get('is_names', False))
                  or
                   (db.field_metadata[k]['datatype'] in ['composite'] and
                    db.field_metadata[k]['display'].get('make_category', False))])
        choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        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]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                QIcon(I('format-fill-color.png')), _('Column coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules,
                QIcon(I('icon_choose.png')), _('Column icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence(
            'Ctrl+Shift+F', QKeySequence.PortableText)]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
            _(' or ').join(keys)))
        self.size_calculated.connect(self.update_cg_cache_size, type=Qt.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(_('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(_('Restore &default appearance'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        self.cover_grid_smaller_cover.clicked.connect(partial(self.resize_cover, True))
        self.cover_grid_larger_cover.clicked.connect(partial(self.resize_cover, False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(self.update_aspect_ratio)

    @property
    def current_cover_size(self):
        cval = self.opt_cover_grid_height.value()
        wval = self.opt_cover_grid_width.value()
        if cval < 0.1:
            dpi = self.opt_cover_grid_height.logicalDpiY()
            cval = auto_height(self.opt_cover_grid_height) / dpi / CM_TO_INCH
        if wval < 0.1:
            wval = 0.75 * cval
        return wval, cval

    def update_aspect_ratio(self, *args):
        width, height = self.current_cover_size
        ar = width / height
        self.cover_grid_aspect_ratio.setText(_('Current aspect ratio (width/height): %.2g') % ar)

    def resize_cover(self, smaller):
        wval, cval = self.current_cover_size
        ar = wval / cval
        delta = 0.2 * (-1 if smaller else 1)
        cval += delta
        cval = max(0, cval)
        self.opt_cover_grid_height.setValue(cval)
        self.opt_cover_grid_width.setValue(cval * ar)

    def cg_reset_size(self):
        self.opt_cover_grid_width.setValue(0)
        self.opt_cover_grid_height.setValue(0)

    def initialize(self):
        ConfigWidgetBase.initialize(self)
        font = gprefs['font']
        if font is not None:
            font = list(font)
            font.append(gprefs.get('font_stretch', QFont.Unstretched))
        self.current_font = self.initial_font = font
        self.update_font_display()
        self.display_model.initialize()
        db = self.gui.current_db
        try:
            idx = self.gui.library_view.currentIndex().row()
            mi = db.get_metadata(idx, index_is_id=False)
        except:
            mi=None
        self.edit_rules.initialize(db.field_metadata, db.prefs, mi, 'column_color_rules')
        self.icon_rules.initialize(db.field_metadata, db.prefs, mi, 'column_icon_rules')
        self.grid_rules.initialize(db.field_metadata, db.prefs, mi, 'cover_grid_icon_rules')
        self.set_cg_color(gprefs['cover_grid_color'])
        self.set_cg_texture(gprefs['cover_grid_texture'])
        self.update_aspect_ratio()

    def open_cg_cache(self):
        open_local_file(self.gui.grid_view.thumbnail_cache.location)

    def update_cg_cache_size(self, size):
        self.cover_grid_current_disk_cache.setText(
            _('Current space used: %s') % human_readable(size))

    def tab_changed(self, index):
        if self.tabWidget.currentWidget() is self.cover_grid_tab:
            self.show_current_cache_usage()

    def show_current_cache_usage(self):
        t = Thread(target=self.calc_cache_size)
        t.daemon = True
        t.start()

    def calc_cache_size(self):
        self.size_calculated.emit(self.gui.grid_view.thumbnail_cache.current_size)

    def set_cg_color(self, val):
        self.cg_bg_widget.bcol = QColor(*val)
        self.cg_bg_widget.update_brush()

    def set_cg_texture(self, val):
        self.cg_bg_widget.btex = val
        self.cg_bg_widget.update_brush()

    def empty_cache(self):
        self.gui.grid_view.thumbnail_cache.empty()
        self.calc_cache_size()

    def restore_defaults(self):
        ConfigWidgetBase.restore_defaults(self)
        ofont = self.current_font
        self.current_font = None
        if ofont is not None:
            self.changed_signal.emit()
            self.update_font_display()
        self.display_model.restore_defaults()
        self.edit_rules.clear()
        self.icon_rules.clear()
        self.grid_rules.clear()
        self.changed_signal.emit()
        self.set_cg_color(gprefs.defaults['cover_grid_color'])
        self.set_cg_texture(gprefs.defaults['cover_grid_texture'])

    def change_cover_grid_color(self):
        col = QColorDialog.getColor(self.cg_bg_widget.bcol,
                              self.gui, _('Choose background color for cover grid'))
        if col.isValid():
            col = tuple(col.getRgb())[:3]
            self.set_cg_color(col)
            self.changed_signal.emit()
            if self.cg_bg_widget.btex:
                if question_dialog(
                    self, _('Remove background image?'),
                    _('There is currently a background image set, so the color'
                      ' you have chosen will not be visible. Remove the background image?')):
                    self.set_cg_texture(None)

    def change_cover_grid_texture(self):
        from calibre.gui2.preferences.texture_chooser import TextureChooser
        d = TextureChooser(parent=self, initial=self.cg_bg_widget.btex)
        if d.exec_() == d.Accepted:
            self.set_cg_texture(d.texture)
            self.changed_signal.emit()

    def restore_cover_grid_appearance(self):
        self.set_cg_color(gprefs.defaults['cover_grid_color'])
        self.set_cg_texture(gprefs.defaults['cover_grid_texture'])
        self.changed_signal.emit()

    def build_font_obj(self):
        font_info = qt_app.original_font if self.current_font is None else self.current_font
        font = QFont(*(font_info[:4]))
        font.setStretch(font_info[4])
        return font

    def update_font_display(self):
        font = self.build_font_obj()
        fi = QFontInfo(font)
        name = unicode(fi.family())

        self.font_display.setFont(font)
        self.font_display.setText(name +
                ' [%dpt]'%fi.pointSize())

    def move_df_up(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, -1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def move_df_down(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, 1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def change_font(self, *args):
        fd = QFontDialog(self.build_font_obj(), self)
        if fd.exec_() == fd.Accepted:
            font = fd.selectedFont()
            fi = QFontInfo(font)
            self.current_font = [unicode(fi.family()), fi.pointSize(),
                    fi.weight(), fi.italic(), font.stretch()]
            self.update_font_display()
            self.changed_signal.emit()

    def commit(self, *args):
        rr = ConfigWidgetBase.commit(self, *args)
        if self.current_font != self.initial_font:
            gprefs['font'] = (self.current_font[:4] if self.current_font else
                    None)
            gprefs['font_stretch'] = (self.current_font[4] if self.current_font
                    is not None else QFont.Unstretched)
            QApplication.setFont(self.font_display.font())
            rr = True
        self.display_model.commit()
        self.edit_rules.commit(self.gui.current_db.prefs)
        self.icon_rules.commit(self.gui.current_db.prefs)
        self.grid_rules.commit(self.gui.current_db.prefs)
        gprefs['cover_grid_color'] = tuple(self.cg_bg_widget.bcol.getRgb())[:3]
        gprefs['cover_grid_texture'] = self.cg_bg_widget.btex
        return rr

    def refresh_gui(self, gui):
        m = gui.library_view.model()
        m.beginResetModel(), m.endResetModel()
        self.update_font_display()
        gui.tags_view.reread_collapse_parameters()
        gui.library_view.refresh_book_details()
        if hasattr(gui.cover_flow, 'setShowReflections'):
            gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections'])
            gui.cover_flow.setPreserveAspectRatio(gprefs['cb_preserve_aspect_ratio'])
        gui.library_view.refresh_row_sizing()
        gui.grid_view.refresh_settings()
Exemple #2
0
    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r('gui_layout', config, restart_required=True, choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('ui_style', gprefs, restart_required=True, choices=[(_('System default'), 'system'), (_('Calibre style'),
                    'calibre')])
        r('book_list_tooltips', gprefs)
        r('tag_browser_old_look', gprefs, restart_required=True)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size', gprefs)
        r('cover_grid_disk_cache_size', gprefs)
        r('cover_grid_spacing', gprefs)
        r('cover_grid_show_title', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('show_rating_in_cover_browser', gprefs)
        r('emblem_size', gprefs)
        r('emblem_position', gprefs, choices=[
            (_('Left'), 'left'), (_('Top'), 'top'), (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        if islinux or isbsd:
            self.opt_systray_icon.setEnabled(False)
            self.opt_systray_icon.setText(_('System tray icon is disabled because of bugs in Qt 5'))
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
            (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'), (_('Always'), 'always'),
            (_('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('default_author_link', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        self.search_library_for_author_button.clicked.connect(
            lambda : self.opt_default_author_link.setText('search-calibre'))

        choices = set([k for k in db.field_metadata.all_field_keys()
                if (db.field_metadata[k]['is_category'] and
                   (db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']) and
                    not db.field_metadata[k]['display'].get('is_names', False))
                  or
                   (db.field_metadata[k]['datatype'] in ['composite'] and
                    db.field_metadata[k]['display'].get('make_category', False))])
        choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        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]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                QIcon(I('format-fill-color.png')), _('Column coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules,
                QIcon(I('icon_choose.png')), _('Column icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence(
            'Ctrl+Shift+F', QKeySequence.PortableText)]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
            _(' or ').join(keys)))
        self.size_calculated.connect(self.update_cg_cache_size, type=Qt.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(_('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(_('Restore &default appearance'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        self.cover_grid_smaller_cover.clicked.connect(partial(self.resize_cover, True))
        self.cover_grid_larger_cover.clicked.connect(partial(self.resize_cover, False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(self.update_aspect_ratio)
Exemple #3
0
class ConfigWidget(ConfigWidgetBase, Ui_Form):

    size_calculated = pyqtSignal(object)

    def genesis(self, gui):
        self.gui = gui
        if not ismacos and not iswindows:
            self.label_widget_style.setVisible(False)
            self.opt_ui_style.setVisible(False)

        db = gui.library_view.model().db

        r = self.register

        try:
            self.icon_theme_title = json.loads(I('icon-theme.json',
                                                 data=True))['name']
        except Exception:
            self.icon_theme_title = _('Default icons')
        self.icon_theme.setText(
            _('Icon theme: <b>%s</b>') % self.icon_theme_title)
        self.commit_icon_theme = None
        self.icon_theme_button.clicked.connect(self.choose_icon_theme)
        self.default_author_link = DefaultAuthorLink(
            self.default_author_link_container)
        self.default_author_link.changed_signal.connect(self.changed_signal)
        r('gui_layout',
          config,
          restart_required=True,
          choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('hidpi',
          gprefs,
          restart_required=True,
          choices=[(_('Automatic'), 'auto'), (_('On'), 'on'),
                   (_('Off'), 'off')])
        if ismacos:
            self.opt_hidpi.setVisible(False), self.label_hidpi.setVisible(
                False)
        r('ui_style',
          gprefs,
          restart_required=True,
          choices=[(_('System default'), 'system'),
                   (_('calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('dnd_merge', gprefs)
        r('wrap_toolbar_text', gprefs, restart_required=True)
        r('show_layout_buttons', gprefs, restart_required=True)
        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_show_tooltips', gprefs)
        r('tag_browser_allow_keyboard_focus', gprefs)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size_multiple', gprefs)
        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('books_autoscroll_time', gprefs)

        r('qv_respects_vls', gprefs)
        r('qv_dclick_changes_column', gprefs)
        r('qv_retkey_changes_column', gprefs)
        r('qv_follows_column', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('cover_browser_title_template', db.prefs)
        fm = db.field_metadata
        r('cover_browser_subtitle_field',
          db.prefs,
          choices=[(_('No subtitle'), 'none')] + sorted(
              (fm[k].get('name'), k)
              for k in fm.all_field_keys() if fm[k].get('name')))
        r('emblem_size', gprefs)
        r('emblem_position',
          gprefs,
          choices=[(_('Left'), 'left'), (_('Top'), 'top'),
                   (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)
        r('booklist_grid', gprefs)
        r('book_details_comments_heading_pos',
          gprefs,
          choices=[(_('Never'), 'hide'), (_('Above text'), 'above'),
                   (_('Beside text'), 'side')])
        self.cover_browser_title_template_button.clicked.connect(
            self.edit_cb_title_template)
        self.id_links_button.clicked.connect(self.edit_id_link_rules)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(key=lambda x: x[1].lower())
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)
        r('cb_double_click_to_activate', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
                   (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'),
                   (_('Always'), 'always'), (_('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)

        choices = {
            k
            for k in db.field_metadata.all_field_keys()
            if (db.field_metadata[k]['is_category'] and
                (db.field_metadata[k]['datatype'] in
                 ['text', 'series', 'enumeration'])
                and not db.field_metadata[k]['display'].get('is_names', False))
            or (db.field_metadata[k]['datatype'] in ['composite'] and
                db.field_metadata[k]['display'].get('make_category', False))
        }
        choices |= {'search'}
        r('tag_browser_dont_collapse',
          gprefs,
          setting=CommaSeparatedList,
          choices=sorted(choices, key=sort_key))

        choices -= {'authors', 'publisher', 'formats', 'news', 'identifiers'}
        r('categories_using_hierarchy',
          db.prefs,
          setting=CommaSeparatedList,
          choices=sorted(choices, key=sort_key))

        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]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        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)
        connect_lambda(
            self.df_up_button.clicked, self, lambda self: move_field_up(
                self.field_display_order, self.display_model))
        connect_lambda(
            self.df_down_button.clicked, self, lambda self: move_field_down(
                self.field_display_order, self.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)
        connect_lambda(
            self.qv_up_button.clicked, self, lambda self: move_field_up(
                self.qv_display_order, self.qv_display_model))
        connect_lambda(
            self.qv_down_button.clicked, self, lambda self: move_field_down(
                self.qv_display_order, self.qv_display_model))

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                              QIcon(I('format-fill-color.png')),
                              _('Column &coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules, QIcon(I('icon_choose.png')),
                              _('Column &icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [
            QKeySequence('F11', QKeySequence.SequenceFormat.PortableText),
            QKeySequence('Ctrl+Shift+F',
                         QKeySequence.SequenceFormat.PortableText)
        ]
        keys = [
            str(x.toString(QKeySequence.SequenceFormat.NativeText))
            for x in keys
        ]
        self.fs_help_msg.setText(
            self.fs_help_msg.text() %
            (QKeySequence(QKeySequence.StandardKey.FullScreen).toString(
                QKeySequence.SequenceFormat.NativeText)))
        self.size_calculated.connect(self.update_cg_cache_size,
                                     type=Qt.ConnectionType.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'),
                                                       self)
        b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(
            _('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(
            _('Restore default &appearance'), self)
        b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        connect_lambda(self.cover_grid_smaller_cover.clicked, self,
                       lambda self: self.resize_cover(True))
        connect_lambda(self.cover_grid_larger_cover.clicked, self,
                       lambda self: self.resize_cover(False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(
            self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(
            self.update_aspect_ratio)
        self.opt_book_details_css.textChanged.connect(self.changed_signal)
        from calibre.gui2.tweak_book.editor.text import get_highlighter, get_theme
        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())

    def choose_icon_theme(self):
        from calibre.gui2.icon_theme import ChooseTheme
        d = ChooseTheme(self)
        if d.exec_() == QDialog.DialogCode.Accepted:
            self.commit_icon_theme = d.commit_changes
            self.icon_theme_title = d.new_theme_title or _('Default icons')
            self.icon_theme.setText(
                _('Icon theme: <b>%s</b>') % self.icon_theme_title)
            self.changed_signal.emit()

    def edit_id_link_rules(self):
        if IdLinksEditor(self).exec_() == QDialog.DialogCode.Accepted:
            self.changed_signal.emit()

    @property
    def current_cover_size(self):
        cval = self.opt_cover_grid_height.value()
        wval = self.opt_cover_grid_width.value()
        if cval < 0.1:
            dpi = self.opt_cover_grid_height.logicalDpiY()
            cval = auto_height(self.opt_cover_grid_height) / dpi / CM_TO_INCH
        if wval < 0.1:
            wval = 0.75 * cval
        return wval, cval

    def update_aspect_ratio(self, *args):
        width, height = self.current_cover_size
        ar = width / height
        self.cover_grid_aspect_ratio.setText(
            _('Current aspect ratio (width/height): %.2g') % ar)

    def resize_cover(self, smaller):
        wval, cval = self.current_cover_size
        ar = wval / cval
        delta = 0.2 * (-1 if smaller else 1)
        cval += delta
        cval = max(0, cval)
        self.opt_cover_grid_height.setValue(cval)
        self.opt_cover_grid_width.setValue(cval * ar)

    def cg_reset_size(self):
        self.opt_cover_grid_width.setValue(0)
        self.opt_cover_grid_height.setValue(0)

    def edit_cb_title_template(self):
        t = TemplateDialog(self,
                           self.opt_cover_browser_title_template.text(),
                           fm=self.gui.current_db.field_metadata)
        t.setWindowTitle(_('Edit template for caption'))
        if t.exec_():
            self.opt_cover_browser_title_template.setText(t.rule[1])

    def initialize(self):
        ConfigWidgetBase.initialize(self)
        self.default_author_link.value = default_author_link()
        font = gprefs['font']
        if font is not None:
            font = list(font)
            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.qv_display_model.initialize()
        db = self.gui.current_db
        try:
            idx = self.gui.library_view.currentIndex().row()
            mi = db.get_metadata(idx, index_is_id=False)
        except:
            mi = None
        self.edit_rules.initialize(db.field_metadata, db.prefs, mi,
                                   'column_color_rules')
        self.icon_rules.initialize(db.field_metadata, db.prefs, mi,
                                   'column_icon_rules')
        self.grid_rules.initialize(db.field_metadata, db.prefs, mi,
                                   'cover_grid_icon_rules')
        self.set_cg_color(gprefs['cover_grid_color'])
        self.set_cg_texture(gprefs['cover_grid_texture'])
        self.update_aspect_ratio()
        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())

    def open_cg_cache(self):
        open_local_file(self.gui.grid_view.thumbnail_cache.location)

    def update_cg_cache_size(self, size):
        self.cover_grid_current_disk_cache.setText(
            _('Current space used: %s') % human_readable(size))

    def tab_changed(self, index):
        if self.tabWidget.currentWidget() is self.cover_grid_tab:
            self.show_current_cache_usage()

    def show_current_cache_usage(self):
        t = Thread(target=self.calc_cache_size)
        t.daemon = True
        t.start()

    def calc_cache_size(self):
        self.size_calculated.emit(
            self.gui.grid_view.thumbnail_cache.current_size)

    def set_cg_color(self, val):
        self.cg_bg_widget.bcol = QColor(*val)
        self.cg_bg_widget.update_brush()

    def set_cg_texture(self, val):
        self.cg_bg_widget.btex = val
        self.cg_bg_widget.update_brush()

    def empty_cache(self):
        self.gui.grid_view.thumbnail_cache.empty()
        self.calc_cache_size()

    def restore_defaults(self):
        ConfigWidgetBase.restore_defaults(self)
        self.default_author_link.value = DEFAULT_AUTHOR_LINK
        ofont = self.current_font
        self.current_font = None
        if ofont is not None:
            self.changed_signal.emit()
            self.update_font_display()
        self.display_model.restore_defaults()
        self.qv_display_model.restore_defaults()
        self.edit_rules.clear()
        self.icon_rules.clear()
        self.grid_rules.clear()
        self.changed_signal.emit()
        self.set_cg_color(gprefs.defaults['cover_grid_color'])
        self.set_cg_texture(gprefs.defaults['cover_grid_texture'])
        self.opt_book_details_css.setPlainText(
            P('templates/book_details.css',
              allow_user_override=False,
              data=True).decode('utf-8'))

    def change_cover_grid_color(self):
        col = QColorDialog.getColor(
            self.cg_bg_widget.bcol, self.gui,
            _('Choose background color for the Cover grid'))
        if col.isValid():
            col = tuple(col.getRgb())[:3]
            self.set_cg_color(col)
            self.changed_signal.emit()
            if self.cg_bg_widget.btex:
                if question_dialog(
                        self, _('Remove background image?'),
                        _('There is currently a background image set, so the color'
                          ' you have chosen will not be visible. Remove the background image?'
                          )):
                    self.set_cg_texture(None)

    def change_cover_grid_texture(self):
        from calibre.gui2.preferences.texture_chooser import TextureChooser
        d = TextureChooser(parent=self, initial=self.cg_bg_widget.btex)
        if d.exec_() == QDialog.DialogCode.Accepted:
            self.set_cg_texture(d.texture)
            self.changed_signal.emit()

    def restore_cover_grid_appearance(self):
        self.set_cg_color(gprefs.defaults['cover_grid_color'])
        self.set_cg_texture(gprefs.defaults['cover_grid_texture'])
        self.changed_signal.emit()

    def build_font_obj(self):
        font_info = qt_app.original_font if self.current_font is None else self.current_font
        font = QFont(*(font_info[:4]))
        font.setStretch(font_info[4])
        return font

    def update_font_display(self):
        font = self.build_font_obj()
        fi = QFontInfo(font)
        name = str(fi.family())

        self.font_display.setFont(font)
        self.font_display.setText(name + ' [%dpt]' % fi.pointSize())

    def change_font(self, *args):
        fd = QFontDialog(self.build_font_obj(), self)
        if fd.exec_() == QDialog.DialogCode.Accepted:
            font = fd.selectedFont()
            fi = QFontInfo(font)
            self.current_font = [
                str(fi.family()),
                fi.pointSize(),
                fi.weight(),
                fi.italic(),
                font.stretch()
            ]
            self.update_font_display()
            self.changed_signal.emit()

    def commit(self, *args):
        with BusyCursor():
            rr = ConfigWidgetBase.commit(self, *args)
            if self.current_font != self.initial_font:
                gprefs['font'] = (self.current_font[:4]
                                  if self.current_font else None)
                gprefs['font_stretch'] = (self.current_font[4]
                                          if self.current_font is not None else
                                          QFont.Stretch.Unstretched)
                QApplication.setFont(self.font_display.font())
                rr = True
            self.display_model.commit()
            self.qv_display_model.commit()
            self.edit_rules.commit(self.gui.current_db.prefs)
            self.icon_rules.commit(self.gui.current_db.prefs)
            self.grid_rules.commit(self.gui.current_db.prefs)
            gprefs['cover_grid_color'] = tuple(
                self.cg_bg_widget.bcol.getRgb())[:3]
            gprefs['cover_grid_texture'] = self.cg_bg_widget.btex
            if self.commit_icon_theme is not None:
                self.commit_icon_theme()
                rr = True
            gprefs['default_author_link'] = self.default_author_link.value
            bcss = self.opt_book_details_css.toPlainText().encode('utf-8')
            defcss = P('templates/book_details.css',
                       data=True,
                       allow_user_override=False)
            if defcss == bcss:
                bcss = None
            set_data('templates/book_details.css', bcss)

        return rr

    def refresh_gui(self, gui):
        gui.book_details.book_info.refresh_css()
        m = gui.library_view.model()
        m.beginResetModel(), m.endResetModel()
        self.update_font_display()
        gui.tags_view.set_look_and_feel()
        gui.tags_view.reread_collapse_parameters()
        gui.library_view.refresh_book_details(force=True)
        gui.library_view.refresh_grid()
        gui.library_view.set_row_header_visibility()
        gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections'])
        gui.cover_flow.setPreserveAspectRatio(
            gprefs['cb_preserve_aspect_ratio'])
        gui.cover_flow.setActivateOnDoubleClick(
            gprefs['cb_double_click_to_activate'])
        gui.update_cover_flow_subtitle_font()
        gui.cover_flow.template_inited = False
        for view in 'library memory card_a card_b'.split():
            getattr(gui, view + '_view').set_row_header_visibility()
        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()
Exemple #4
0
    def genesis(self, gui):
        self.gui = gui
        if not ismacos and not iswindows:
            self.label_widget_style.setVisible(False)
            self.opt_ui_style.setVisible(False)

        db = gui.library_view.model().db

        r = self.register

        try:
            self.icon_theme_title = json.loads(I('icon-theme.json',
                                                 data=True))['name']
        except Exception:
            self.icon_theme_title = _('Default icons')
        self.icon_theme.setText(
            _('Icon theme: <b>%s</b>') % self.icon_theme_title)
        self.commit_icon_theme = None
        self.icon_theme_button.clicked.connect(self.choose_icon_theme)
        self.default_author_link = DefaultAuthorLink(
            self.default_author_link_container)
        self.default_author_link.changed_signal.connect(self.changed_signal)
        r('gui_layout',
          config,
          restart_required=True,
          choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('hidpi',
          gprefs,
          restart_required=True,
          choices=[(_('Automatic'), 'auto'), (_('On'), 'on'),
                   (_('Off'), 'off')])
        if ismacos:
            self.opt_hidpi.setVisible(False), self.label_hidpi.setVisible(
                False)
        r('ui_style',
          gprefs,
          restart_required=True,
          choices=[(_('System default'), 'system'),
                   (_('calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('dnd_merge', gprefs)
        r('wrap_toolbar_text', gprefs, restart_required=True)
        r('show_layout_buttons', gprefs, restart_required=True)
        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_show_tooltips', gprefs)
        r('tag_browser_allow_keyboard_focus', gprefs)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size_multiple', gprefs)
        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('books_autoscroll_time', gprefs)

        r('qv_respects_vls', gprefs)
        r('qv_dclick_changes_column', gprefs)
        r('qv_retkey_changes_column', gprefs)
        r('qv_follows_column', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('cover_browser_title_template', db.prefs)
        fm = db.field_metadata
        r('cover_browser_subtitle_field',
          db.prefs,
          choices=[(_('No subtitle'), 'none')] + sorted(
              (fm[k].get('name'), k)
              for k in fm.all_field_keys() if fm[k].get('name')))
        r('emblem_size', gprefs)
        r('emblem_position',
          gprefs,
          choices=[(_('Left'), 'left'), (_('Top'), 'top'),
                   (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)
        r('booklist_grid', gprefs)
        r('book_details_comments_heading_pos',
          gprefs,
          choices=[(_('Never'), 'hide'), (_('Above text'), 'above'),
                   (_('Beside text'), 'side')])
        self.cover_browser_title_template_button.clicked.connect(
            self.edit_cb_title_template)
        self.id_links_button.clicked.connect(self.edit_id_link_rules)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(key=lambda x: x[1].lower())
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)
        r('cb_double_click_to_activate', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
                   (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'),
                   (_('Always'), 'always'), (_('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)

        choices = {
            k
            for k in db.field_metadata.all_field_keys()
            if (db.field_metadata[k]['is_category'] and
                (db.field_metadata[k]['datatype'] in
                 ['text', 'series', 'enumeration'])
                and not db.field_metadata[k]['display'].get('is_names', False))
            or (db.field_metadata[k]['datatype'] in ['composite'] and
                db.field_metadata[k]['display'].get('make_category', False))
        }
        choices |= {'search'}
        r('tag_browser_dont_collapse',
          gprefs,
          setting=CommaSeparatedList,
          choices=sorted(choices, key=sort_key))

        choices -= {'authors', 'publisher', 'formats', 'news', 'identifiers'}
        r('categories_using_hierarchy',
          db.prefs,
          setting=CommaSeparatedList,
          choices=sorted(choices, key=sort_key))

        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]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        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)
        connect_lambda(
            self.df_up_button.clicked, self, lambda self: move_field_up(
                self.field_display_order, self.display_model))
        connect_lambda(
            self.df_down_button.clicked, self, lambda self: move_field_down(
                self.field_display_order, self.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)
        connect_lambda(
            self.qv_up_button.clicked, self, lambda self: move_field_up(
                self.qv_display_order, self.qv_display_model))
        connect_lambda(
            self.qv_down_button.clicked, self, lambda self: move_field_down(
                self.qv_display_order, self.qv_display_model))

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                              QIcon(I('format-fill-color.png')),
                              _('Column &coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules, QIcon(I('icon_choose.png')),
                              _('Column &icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [
            QKeySequence('F11', QKeySequence.SequenceFormat.PortableText),
            QKeySequence('Ctrl+Shift+F',
                         QKeySequence.SequenceFormat.PortableText)
        ]
        keys = [
            str(x.toString(QKeySequence.SequenceFormat.NativeText))
            for x in keys
        ]
        self.fs_help_msg.setText(
            self.fs_help_msg.text() %
            (QKeySequence(QKeySequence.StandardKey.FullScreen).toString(
                QKeySequence.SequenceFormat.NativeText)))
        self.size_calculated.connect(self.update_cg_cache_size,
                                     type=Qt.ConnectionType.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'),
                                                       self)
        b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(
            _('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(
            _('Restore default &appearance'), self)
        b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        connect_lambda(self.cover_grid_smaller_cover.clicked, self,
                       lambda self: self.resize_cover(True))
        connect_lambda(self.cover_grid_larger_cover.clicked, self,
                       lambda self: self.resize_cover(False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(
            self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(
            self.update_aspect_ratio)
        self.opt_book_details_css.textChanged.connect(self.changed_signal)
        from calibre.gui2.tweak_book.editor.text import get_highlighter, get_theme
        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())
Exemple #5
0
class ConfigWidget(ConfigWidgetBase, Ui_Form):

    size_calculated = pyqtSignal(object)

    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r('gui_layout',
          config,
          restart_required=True,
          choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('ui_style',
          gprefs,
          restart_required=True,
          choices=[(_('System default'), 'system'),
                   (_('Calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('tag_browser_old_look', gprefs, restart_required=True)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size_multiple', gprefs)
        r('cover_grid_disk_cache_size', gprefs)
        r('cover_grid_spacing', gprefs)
        r('cover_grid_show_title', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('show_rating_in_cover_browser', gprefs)
        r('emblem_size', gprefs)
        r('emblem_position',
          gprefs,
          choices=[(_('Left'), 'left'), (_('Top'), 'top'),
                   (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
                   (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'),
                   (_('Always'), 'always'), (_('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('default_author_link', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        self.search_library_for_author_button.clicked.connect(
            lambda: self.opt_default_author_link.setText('search-calibre'))

        choices = set([
            k for k in db.field_metadata.all_field_keys()
            if (db.field_metadata[k]['is_category'] and
                (db.field_metadata[k]['datatype'] in
                 ['text', 'series', 'enumeration'])
                and not db.field_metadata[k]['display'].get('is_names', False))
            or (db.field_metadata[k]['datatype'] in ['composite'] and
                db.field_metadata[k]['display'].get('make_category', False))
        ])
        choices -= set(
            ['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy',
          db.prefs,
          setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        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]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                              QIcon(I('format-fill-color.png')),
                              _('Column coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules, QIcon(I('icon_choose.png')),
                              _('Column icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [
            QKeySequence('F11', QKeySequence.PortableText),
            QKeySequence('Ctrl+Shift+F', QKeySequence.PortableText)
        ]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(
            unicode(self.fs_help_msg.text()) % (_(' or ').join(keys)))
        self.size_calculated.connect(self.update_cg_cache_size,
                                     type=Qt.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'),
                                                       self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(
            _('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(
            _('Restore &default appearance'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        self.cover_grid_smaller_cover.clicked.connect(
            partial(self.resize_cover, True))
        self.cover_grid_larger_cover.clicked.connect(
            partial(self.resize_cover, False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(
            self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(
            self.update_aspect_ratio)

    @property
    def current_cover_size(self):
        cval = self.opt_cover_grid_height.value()
        wval = self.opt_cover_grid_width.value()
        if cval < 0.1:
            dpi = self.opt_cover_grid_height.logicalDpiY()
            cval = auto_height(self.opt_cover_grid_height) / dpi / CM_TO_INCH
        if wval < 0.1:
            wval = 0.75 * cval
        return wval, cval

    def update_aspect_ratio(self, *args):
        width, height = self.current_cover_size
        ar = width / height
        self.cover_grid_aspect_ratio.setText(
            _('Current aspect ratio (width/height): %.2g') % ar)

    def resize_cover(self, smaller):
        wval, cval = self.current_cover_size
        ar = wval / cval
        delta = 0.2 * (-1 if smaller else 1)
        cval += delta
        cval = max(0, cval)
        self.opt_cover_grid_height.setValue(cval)
        self.opt_cover_grid_width.setValue(cval * ar)

    def cg_reset_size(self):
        self.opt_cover_grid_width.setValue(0)
        self.opt_cover_grid_height.setValue(0)

    def initialize(self):
        ConfigWidgetBase.initialize(self)
        font = gprefs['font']
        if font is not None:
            font = list(font)
            font.append(gprefs.get('font_stretch', QFont.Unstretched))
        self.current_font = self.initial_font = font
        self.update_font_display()
        self.display_model.initialize()
        db = self.gui.current_db
        try:
            idx = self.gui.library_view.currentIndex().row()
            mi = db.get_metadata(idx, index_is_id=False)
        except:
            mi = None
        self.edit_rules.initialize(db.field_metadata, db.prefs, mi,
                                   'column_color_rules')
        self.icon_rules.initialize(db.field_metadata, db.prefs, mi,
                                   'column_icon_rules')
        self.grid_rules.initialize(db.field_metadata, db.prefs, mi,
                                   'cover_grid_icon_rules')
        self.set_cg_color(gprefs['cover_grid_color'])
        self.set_cg_texture(gprefs['cover_grid_texture'])
        self.update_aspect_ratio()

    def open_cg_cache(self):
        open_local_file(self.gui.grid_view.thumbnail_cache.location)

    def update_cg_cache_size(self, size):
        self.cover_grid_current_disk_cache.setText(
            _('Current space used: %s') % human_readable(size))

    def tab_changed(self, index):
        if self.tabWidget.currentWidget() is self.cover_grid_tab:
            self.show_current_cache_usage()

    def show_current_cache_usage(self):
        t = Thread(target=self.calc_cache_size)
        t.daemon = True
        t.start()

    def calc_cache_size(self):
        self.size_calculated.emit(
            self.gui.grid_view.thumbnail_cache.current_size)

    def set_cg_color(self, val):
        self.cg_bg_widget.bcol = QColor(*val)
        self.cg_bg_widget.update_brush()

    def set_cg_texture(self, val):
        self.cg_bg_widget.btex = val
        self.cg_bg_widget.update_brush()

    def empty_cache(self):
        self.gui.grid_view.thumbnail_cache.empty()
        self.calc_cache_size()

    def restore_defaults(self):
        ConfigWidgetBase.restore_defaults(self)
        ofont = self.current_font
        self.current_font = None
        if ofont is not None:
            self.changed_signal.emit()
            self.update_font_display()
        self.display_model.restore_defaults()
        self.edit_rules.clear()
        self.icon_rules.clear()
        self.grid_rules.clear()
        self.changed_signal.emit()
        self.set_cg_color(gprefs.defaults['cover_grid_color'])
        self.set_cg_texture(gprefs.defaults['cover_grid_texture'])

    def change_cover_grid_color(self):
        col = QColorDialog.getColor(
            self.cg_bg_widget.bcol, self.gui,
            _('Choose background color for cover grid'))
        if col.isValid():
            col = tuple(col.getRgb())[:3]
            self.set_cg_color(col)
            self.changed_signal.emit()
            if self.cg_bg_widget.btex:
                if question_dialog(
                        self, _('Remove background image?'),
                        _('There is currently a background image set, so the color'
                          ' you have chosen will not be visible. Remove the background image?'
                          )):
                    self.set_cg_texture(None)

    def change_cover_grid_texture(self):
        from calibre.gui2.preferences.texture_chooser import TextureChooser
        d = TextureChooser(parent=self, initial=self.cg_bg_widget.btex)
        if d.exec_() == d.Accepted:
            self.set_cg_texture(d.texture)
            self.changed_signal.emit()

    def restore_cover_grid_appearance(self):
        self.set_cg_color(gprefs.defaults['cover_grid_color'])
        self.set_cg_texture(gprefs.defaults['cover_grid_texture'])
        self.changed_signal.emit()

    def build_font_obj(self):
        font_info = qt_app.original_font if self.current_font is None else self.current_font
        font = QFont(*(font_info[:4]))
        font.setStretch(font_info[4])
        return font

    def update_font_display(self):
        font = self.build_font_obj()
        fi = QFontInfo(font)
        name = unicode(fi.family())

        self.font_display.setFont(font)
        self.font_display.setText(name + ' [%dpt]' % fi.pointSize())

    def move_df_up(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, -1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def move_df_down(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, 1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def change_font(self, *args):
        fd = QFontDialog(self.build_font_obj(), self)
        if fd.exec_() == fd.Accepted:
            font = fd.selectedFont()
            fi = QFontInfo(font)
            self.current_font = [
                unicode(fi.family()),
                fi.pointSize(),
                fi.weight(),
                fi.italic(),
                font.stretch()
            ]
            self.update_font_display()
            self.changed_signal.emit()

    def commit(self, *args):
        rr = ConfigWidgetBase.commit(self, *args)
        if self.current_font != self.initial_font:
            gprefs['font'] = (self.current_font[:4]
                              if self.current_font else None)
            gprefs['font_stretch'] = (self.current_font[4] if self.current_font
                                      is not None else QFont.Unstretched)
            QApplication.setFont(self.font_display.font())
            rr = True
        self.display_model.commit()
        self.edit_rules.commit(self.gui.current_db.prefs)
        self.icon_rules.commit(self.gui.current_db.prefs)
        self.grid_rules.commit(self.gui.current_db.prefs)
        gprefs['cover_grid_color'] = tuple(self.cg_bg_widget.bcol.getRgb())[:3]
        gprefs['cover_grid_texture'] = self.cg_bg_widget.btex
        return rr

    def refresh_gui(self, gui):
        m = gui.library_view.model()
        m.beginResetModel(), m.endResetModel()
        self.update_font_display()
        gui.tags_view.reread_collapse_parameters()
        gui.library_view.refresh_book_details()
        if hasattr(gui.cover_flow, 'setShowReflections'):
            gui.cover_flow.setShowReflections(
                gprefs['cover_browser_reflections'])
            gui.cover_flow.setPreserveAspectRatio(
                gprefs['cb_preserve_aspect_ratio'])
        gui.library_view.refresh_row_sizing()
        gui.grid_view.refresh_settings()
Exemple #6
0
    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r('gui_layout',
          config,
          restart_required=True,
          choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('ui_style',
          gprefs,
          restart_required=True,
          choices=[(_('System default'), 'system'),
                   (_('Calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('tag_browser_old_look', gprefs, restart_required=True)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size_multiple', gprefs)
        r('cover_grid_disk_cache_size', gprefs)
        r('cover_grid_spacing', gprefs)
        r('cover_grid_show_title', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('show_rating_in_cover_browser', gprefs)
        r('emblem_size', gprefs)
        r('emblem_position',
          gprefs,
          choices=[(_('Left'), 'left'), (_('Top'), 'top'),
                   (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
                   (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'),
                   (_('Always'), 'always'), (_('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('default_author_link', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        self.search_library_for_author_button.clicked.connect(
            lambda: self.opt_default_author_link.setText('search-calibre'))

        choices = set([
            k for k in db.field_metadata.all_field_keys()
            if (db.field_metadata[k]['is_category'] and
                (db.field_metadata[k]['datatype'] in
                 ['text', 'series', 'enumeration'])
                and not db.field_metadata[k]['display'].get('is_names', False))
            or (db.field_metadata[k]['datatype'] in ['composite'] and
                db.field_metadata[k]['display'].get('make_category', False))
        ])
        choices -= set(
            ['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy',
          db.prefs,
          setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        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]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                              QIcon(I('format-fill-color.png')),
                              _('Column coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules, QIcon(I('icon_choose.png')),
                              _('Column icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [
            QKeySequence('F11', QKeySequence.PortableText),
            QKeySequence('Ctrl+Shift+F', QKeySequence.PortableText)
        ]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(
            unicode(self.fs_help_msg.text()) % (_(' or ').join(keys)))
        self.size_calculated.connect(self.update_cg_cache_size,
                                     type=Qt.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'),
                                                       self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(
            _('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(
            _('Restore &default appearance'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        self.cover_grid_smaller_cover.clicked.connect(
            partial(self.resize_cover, True))
        self.cover_grid_larger_cover.clicked.connect(
            partial(self.resize_cover, False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(
            self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(
            self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(
            self.update_aspect_ratio)
Exemple #7
0
    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r("gui_layout", config, restart_required=True, choices=[(_("Wide"), "wide"), (_("Narrow"), "narrow")])
        r(
            "ui_style",
            gprefs,
            restart_required=True,
            choices=[(_("System default"), "system"), (_("Calibre style"), "calibre")],
        )
        r("book_list_tooltips", gprefs)
        r("tag_browser_old_look", gprefs, restart_required=True)
        r("bd_show_cover", gprefs)
        r("bd_overlay_cover_size", gprefs)
        r("cover_grid_width", gprefs)
        r("cover_grid_height", gprefs)
        r("cover_grid_cache_size", gprefs)
        r("cover_grid_spacing", gprefs)
        r("cover_grid_show_title", gprefs)

        r("cover_flow_queue_length", config, restart_required=True)
        r("cover_browser_reflections", gprefs)
        r("extra_row_spacing", gprefs)

        def get_esc_lang(l):
            if l == "en":
                return "English"
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = "en"
        items = [(l, get_esc_lang(l)) for l in available_translations() if l != lang]
        if lang != "en":
            items.append(("en", get_esc_lang("en")))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r("language", prefs, choices=choices, restart_required=True)

        r("show_avg_rating", config)
        r("disable_animations", config)
        r("systray_icon", config, restart_required=True)
        r("show_splash_screen", gprefs)
        r("disable_tray_notification", config)
        r("use_roman_numerals_for_series_number", config)
        r("separate_cover_flow", config, restart_required=True)
        r("cb_fullscreen", gprefs)

        choices = [(_("Off"), "off"), (_("Small"), "small"), (_("Medium"), "medium"), (_("Large"), "large")]
        r("toolbar_icon_size", gprefs, choices=choices)

        choices = [(_("If there is enough room"), "auto"), (_("Always"), "always"), (_("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("default_author_link", gprefs)
        r("tag_browser_dont_collapse", gprefs, setting=CommaSeparatedList)

        choices = set(
            [
                k
                for k in db.field_metadata.all_field_keys()
                if (
                    db.field_metadata[k]["is_category"]
                    and (db.field_metadata[k]["datatype"] in ["text", "series", "enumeration"])
                    and not db.field_metadata[k]["display"].get("is_names", False)
                )
                or (
                    db.field_metadata[k]["datatype"] in ["composite"]
                    and db.field_metadata[k]["display"].get("make_category", False)
                )
            ]
        )
        choices -= set(["authors", "publisher", "formats", "news", "identifiers"])
        choices |= set(["search"])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r(
            "categories_using_hierarchy",
            db.prefs,
            setting=CommaSeparatedList,
            choices=sorted(list(choices), key=sort_key),
        )

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules, QIcon(I("format-fill-color.png")), _("Column coloring"))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules, QIcon(I("icon_choose.png")), _("Column icons"))

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence("F11", QKeySequence.PortableText), QKeySequence("Ctrl+Shift+F", QKeySequence.PortableText)]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode(self.fs_help_msg.text()) % (_(" or ").join(keys)))
        self.cover_grid_color_button.clicked.connect(self.change_cover_grid_color)
        if not tweaks.get("use_new_db", False):
            for i in range(self.tabWidget.count()):
                if self.tabWidget.widget(i) is self.cover_grid_tab:
                    self.tabWidget.removeTab(i)
Exemple #8
0
    def genesis(self, gui):
        self.gui = gui
        if not isosx and not iswindows:
            self.label_widget_style.setVisible(False)
            self.opt_ui_style.setVisible(False)

        db = gui.library_view.model().db

        r = self.register

        try:
            self.icon_theme_title = json.loads(I('icon-theme.json', data=True))['name']
        except Exception:
            self.icon_theme_title = _('Default icons')
        self.icon_theme.setText(_('Icon theme: <b>%s</b>') % self.icon_theme_title)
        self.commit_icon_theme = None
        self.icon_theme_button.clicked.connect(self.choose_icon_theme)
        self.default_author_link = DefaultAuthorLink(self.default_author_link_container)
        self.default_author_link.changed_signal.connect(self.changed_signal)
        r('gui_layout', config, restart_required=True, choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('hidpi', gprefs, restart_required=True, choices=[(_('Automatic'), 'auto'), (_('On'), 'on'), (_('Off'), 'off')])
        if isosx:
            self.opt_hidpi.setVisible(False), self.label_hidpi.setVisible(False)
        r('ui_style', gprefs, restart_required=True, choices=[(_('System default'), 'system'), (_('calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('show_layout_buttons', gprefs, restart_required=True)
        r('row_numbers_in_book_list', gprefs)
        r('tag_browser_old_look', gprefs)
        r('tag_browser_hide_empty_categories', gprefs)
        r('tag_browser_show_tooltips', gprefs)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size_multiple', gprefs)
        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('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('cover_browser_title_template', db.prefs)
        fm = db.field_metadata
        r('cover_browser_subtitle_field', db.prefs, choices=[(_('No subtitle'), 'none')] + sorted(
            (fm[k].get('name'), k) for k in fm.all_field_keys() if fm[k].get('name')
        ))
        r('emblem_size', gprefs)
        r('emblem_position', gprefs, choices=[
            (_('Left'), 'left'), (_('Top'), 'top'), (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)
        r('book_details_narrow_comments_layout', gprefs, choices=[(_('Float'), 'float'), (_('Columns'), 'columns')])
        self.opt_book_details_narrow_comments_layout.setToolTip(textwrap.fill(_(
            'Choose how the text is laid out when using the "Narrow" user interface layout.'
            ' A value of "Float" means that the comments text will wrap around'
            ' the other metadata fields, while a value of "Columns" means that'
            ' the comments will be in a separate fixed width column.')))
        self.cover_browser_title_template_button.clicked.connect(self.edit_cb_title_template)
        self.id_links_button.clicked.connect(self.edit_id_link_rules)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
            (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'), (_('Always'), 'always'),
            (_('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('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        choices = set([k for k in db.field_metadata.all_field_keys()
                if (db.field_metadata[k]['is_category'] and
                   (db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']) and
                    not db.field_metadata[k]['display'].get('is_names', False)) or
                   (db.field_metadata[k]['datatype'] in ['composite'] and
                    db.field_metadata[k]['display'].get('make_category', False))])
        choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        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]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        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)
        self.df_up_button.clicked.connect(partial(move_field_up,
                                  self.field_display_order, self.display_model))
        self.df_down_button.clicked.connect(partial(move_field_down,
                                  self.field_display_order, self.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)
        self.qv_up_button.clicked.connect(partial(move_field_up,
                                  self.qv_display_order, self.qv_display_model))
        self.qv_down_button.clicked.connect(partial(move_field_down,
                                  self.qv_display_order, self.qv_display_model))

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                QIcon(I('format-fill-color.png')), _('Column &coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules,
                QIcon(I('icon_choose.png')), _('Column &icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence(
            'Ctrl+Shift+F', QKeySequence.PortableText)]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
            _(' or ').join(keys)))
        self.size_calculated.connect(self.update_cg_cache_size, type=Qt.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(_('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(_('Restore &default appearance'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        self.cover_grid_smaller_cover.clicked.connect(partial(self.resize_cover, True))
        self.cover_grid_larger_cover.clicked.connect(partial(self.resize_cover, False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(self.update_aspect_ratio)
Exemple #9
0
class ConfigWidget(ConfigWidgetBase, Ui_Form):

    size_calculated = pyqtSignal(object)

    def genesis(self, gui):
        self.gui = gui
        if not isosx and not iswindows:
            self.label_widget_style.setVisible(False)
            self.opt_ui_style.setVisible(False)

        db = gui.library_view.model().db

        r = self.register

        try:
            self.icon_theme_title = json.loads(I('icon-theme.json', data=True))['name']
        except Exception:
            self.icon_theme_title = _('Default icons')
        self.icon_theme.setText(_('Icon theme: <b>%s</b>') % self.icon_theme_title)
        self.commit_icon_theme = None
        self.icon_theme_button.clicked.connect(self.choose_icon_theme)
        self.default_author_link = DefaultAuthorLink(self.default_author_link_container)
        self.default_author_link.changed_signal.connect(self.changed_signal)
        r('gui_layout', config, restart_required=True, choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('hidpi', gprefs, restart_required=True, choices=[(_('Automatic'), 'auto'), (_('On'), 'on'), (_('Off'), 'off')])
        if isosx:
            self.opt_hidpi.setVisible(False), self.label_hidpi.setVisible(False)
        r('ui_style', gprefs, restart_required=True, choices=[(_('System default'), 'system'), (_('calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('dnd_merge', gprefs)
        r('wrap_toolbar_text', gprefs, restart_required=True)
        r('show_layout_buttons', gprefs, restart_required=True)
        r('row_numbers_in_book_list', gprefs)
        r('tag_browser_old_look', gprefs)
        r('tag_browser_hide_empty_categories', gprefs)
        r('tag_browser_show_tooltips', gprefs)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)
        r('cover_grid_width', gprefs)
        r('cover_grid_height', gprefs)
        r('cover_grid_cache_size_multiple', gprefs)
        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('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)
        r('cover_browser_title_template', db.prefs)
        fm = db.field_metadata
        r('cover_browser_subtitle_field', db.prefs, choices=[(_('No subtitle'), 'none')] + sorted(
            (fm[k].get('name'), k) for k in fm.all_field_keys() if fm[k].get('name')
        ))
        r('emblem_size', gprefs)
        r('emblem_position', gprefs, choices=[
            (_('Left'), 'left'), (_('Top'), 'top'), (_('Right'), 'right'), (_('Bottom'), 'bottom')])
        r('book_list_extra_row_spacing', gprefs)
        r('booklist_grid', gprefs)
        r('book_details_narrow_comments_layout', gprefs, choices=[(_('Float'), 'float'), (_('Columns'), 'columns')])
        self.opt_book_details_narrow_comments_layout.setToolTip(textwrap.fill(_(
            'Choose how the text is laid out when using the "Narrow" user interface layout.'
            ' A value of "Float" means that the comments text will wrap around'
            ' the other metadata fields, while a value of "Columns" means that'
            ' the comments will be in a separate fixed width column.')))
        self.cover_browser_title_template_button.clicked.connect(self.edit_cb_title_template)
        self.id_links_button.clicked.connect(self.edit_id_link_rules)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations()
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(key=lambda x: x[1].lower())
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)
        r('cb_preserve_aspect_ratio', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
            (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'), (_('Always'), 'always'),
            (_('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('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        choices = {k for k in db.field_metadata.all_field_keys()
                if (db.field_metadata[k]['is_category'] and (
                    db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration'
                    ]) and not db.field_metadata[k]['display'].get('is_names', False)) or (
                    db.field_metadata[k]['datatype'] in ['composite'
                    ] and db.field_metadata[k]['display'].get('make_category', False))}
        choices -= {'authors', 'publisher', 'formats', 'news', 'identifiers'}
        choices |= {'search'}
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        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]))
        r('field_under_covers_in_grid', db.prefs, choices=choices)

        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)
        connect_lambda(self.df_up_button.clicked, self,
                lambda self: move_field_up(self.field_display_order, self.display_model))
        connect_lambda(self.df_down_button.clicked, self,
                lambda self: move_field_down(self.field_display_order, self.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)
        connect_lambda(self.qv_up_button.clicked, self,
                lambda self: move_field_up(self.qv_display_order, self.qv_display_model))
        connect_lambda(self.qv_down_button.clicked, self,
                lambda self: move_field_down(self.qv_display_order, self.qv_display_model))

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                QIcon(I('format-fill-color.png')), _('Column &coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules,
                QIcon(I('icon_choose.png')), _('Column &icons'))

        self.grid_rules = EditRules(self.emblems_tab)
        self.grid_rules.changed.connect(self.changed_signal)
        self.emblems_tab.setLayout(QVBoxLayout())
        self.emblems_tab.layout().addWidget(self.grid_rules)

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence(
            'Ctrl+Shift+F', QKeySequence.PortableText)]
        keys = [unicode_type(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode_type(self.fs_help_msg.text())%(
            _(' or ').join(keys)))
        self.size_calculated.connect(self.update_cg_cache_size, type=Qt.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_('Change &color'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(_('Change &background image'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(_('Restore &default appearance'), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        connect_lambda(self.cover_grid_smaller_cover.clicked, self, lambda self: self.resize_cover(True))
        connect_lambda(self.cover_grid_larger_cover.clicked, self, lambda self: self.resize_cover(False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(self.update_aspect_ratio)

    def choose_icon_theme(self):
        from calibre.gui2.icon_theme import ChooseTheme
        d = ChooseTheme(self)
        if d.exec_() == d.Accepted:
            self.commit_icon_theme = d.commit_changes
            self.icon_theme_title = d.new_theme_title or _('Default icons')
            self.icon_theme.setText(_('Icon theme: <b>%s</b>') % self.icon_theme_title)
            self.changed_signal.emit()

    def edit_id_link_rules(self):
        if IdLinksEditor(self).exec_() == Dialog.Accepted:
            self.changed_signal.emit()

    @property
    def current_cover_size(self):
        cval = self.opt_cover_grid_height.value()
        wval = self.opt_cover_grid_width.value()
        if cval < 0.1:
            dpi = self.opt_cover_grid_height.logicalDpiY()
            cval = auto_height(self.opt_cover_grid_height) / dpi / CM_TO_INCH
        if wval < 0.1:
            wval = 0.75 * cval
        return wval, cval

    def update_aspect_ratio(self, *args):
        width, height = self.current_cover_size
        ar = width / height
        self.cover_grid_aspect_ratio.setText(_('Current aspect ratio (width/height): %.2g') % ar)

    def resize_cover(self, smaller):
        wval, cval = self.current_cover_size
        ar = wval / cval
        delta = 0.2 * (-1 if smaller else 1)
        cval += delta
        cval = max(0, cval)
        self.opt_cover_grid_height.setValue(cval)
        self.opt_cover_grid_width.setValue(cval * ar)

    def cg_reset_size(self):
        self.opt_cover_grid_width.setValue(0)
        self.opt_cover_grid_height.setValue(0)

    def edit_cb_title_template(self):
        t = TemplateDialog(self, self.opt_cover_browser_title_template.text(), fm=self.gui.current_db.field_metadata)
        t.setWindowTitle(_('Edit template for caption'))
        if t.exec_():
            self.opt_cover_browser_title_template.setText(t.rule[1])

    def initialize(self):
        ConfigWidgetBase.initialize(self)
        self.default_author_link.value = default_author_link()
        font = gprefs['font']
        if font is not None:
            font = list(font)
            font.append(gprefs.get('font_stretch', QFont.Unstretched))
        self.current_font = self.initial_font = font
        self.update_font_display()
        self.display_model.initialize()
        self.qv_display_model.initialize()
        db = self.gui.current_db
        try:
            idx = self.gui.library_view.currentIndex().row()
            mi = db.get_metadata(idx, index_is_id=False)
        except:
            mi=None
        self.edit_rules.initialize(db.field_metadata, db.prefs, mi, 'column_color_rules')
        self.icon_rules.initialize(db.field_metadata, db.prefs, mi, 'column_icon_rules')
        self.grid_rules.initialize(db.field_metadata, db.prefs, mi, 'cover_grid_icon_rules')
        self.set_cg_color(gprefs['cover_grid_color'])
        self.set_cg_texture(gprefs['cover_grid_texture'])
        self.update_aspect_ratio()

    def open_cg_cache(self):
        open_local_file(self.gui.grid_view.thumbnail_cache.location)

    def update_cg_cache_size(self, size):
        self.cover_grid_current_disk_cache.setText(
            _('Current space used: %s') % human_readable(size))

    def tab_changed(self, index):
        if self.tabWidget.currentWidget() is self.cover_grid_tab:
            self.show_current_cache_usage()

    def show_current_cache_usage(self):
        t = Thread(target=self.calc_cache_size)
        t.daemon = True
        t.start()

    def calc_cache_size(self):
        self.size_calculated.emit(self.gui.grid_view.thumbnail_cache.current_size)

    def set_cg_color(self, val):
        self.cg_bg_widget.bcol = QColor(*val)
        self.cg_bg_widget.update_brush()

    def set_cg_texture(self, val):
        self.cg_bg_widget.btex = val
        self.cg_bg_widget.update_brush()

    def empty_cache(self):
        self.gui.grid_view.thumbnail_cache.empty()
        self.calc_cache_size()

    def restore_defaults(self):
        ConfigWidgetBase.restore_defaults(self)
        self.default_author_link.value = DEFAULT_AUTHOR_LINK
        ofont = self.current_font
        self.current_font = None
        if ofont is not None:
            self.changed_signal.emit()
            self.update_font_display()
        self.display_model.restore_defaults()
        self.qv_display_model.restore_defaults()
        self.edit_rules.clear()
        self.icon_rules.clear()
        self.grid_rules.clear()
        self.changed_signal.emit()
        self.set_cg_color(gprefs.defaults['cover_grid_color'])
        self.set_cg_texture(gprefs.defaults['cover_grid_texture'])

    def change_cover_grid_color(self):
        col = QColorDialog.getColor(self.cg_bg_widget.bcol,
                              self.gui, _('Choose background color for the Cover grid'))
        if col.isValid():
            col = tuple(col.getRgb())[:3]
            self.set_cg_color(col)
            self.changed_signal.emit()
            if self.cg_bg_widget.btex:
                if question_dialog(
                    self, _('Remove background image?'),
                    _('There is currently a background image set, so the color'
                      ' you have chosen will not be visible. Remove the background image?')):
                    self.set_cg_texture(None)

    def change_cover_grid_texture(self):
        from calibre.gui2.preferences.texture_chooser import TextureChooser
        d = TextureChooser(parent=self, initial=self.cg_bg_widget.btex)
        if d.exec_() == d.Accepted:
            self.set_cg_texture(d.texture)
            self.changed_signal.emit()

    def restore_cover_grid_appearance(self):
        self.set_cg_color(gprefs.defaults['cover_grid_color'])
        self.set_cg_texture(gprefs.defaults['cover_grid_texture'])
        self.changed_signal.emit()

    def build_font_obj(self):
        font_info = qt_app.original_font if self.current_font is None else self.current_font
        font = QFont(*(font_info[:4]))
        font.setStretch(font_info[4])
        return font

    def update_font_display(self):
        font = self.build_font_obj()
        fi = QFontInfo(font)
        name = unicode_type(fi.family())

        self.font_display.setFont(font)
        self.font_display.setText(name + ' [%dpt]'%fi.pointSize())

    def change_font(self, *args):
        fd = QFontDialog(self.build_font_obj(), self)
        if fd.exec_() == fd.Accepted:
            font = fd.selectedFont()
            fi = QFontInfo(font)
            self.current_font = [unicode_type(fi.family()), fi.pointSize(),
                    fi.weight(), fi.italic(), font.stretch()]
            self.update_font_display()
            self.changed_signal.emit()

    def commit(self, *args):
        with BusyCursor():
            rr = ConfigWidgetBase.commit(self, *args)
            if self.current_font != self.initial_font:
                gprefs['font'] = (self.current_font[:4] if self.current_font else
                        None)
                gprefs['font_stretch'] = (self.current_font[4] if self.current_font
                        is not None else QFont.Unstretched)
                QApplication.setFont(self.font_display.font())
                rr = True
            self.display_model.commit()
            self.qv_display_model.commit()
            self.edit_rules.commit(self.gui.current_db.prefs)
            self.icon_rules.commit(self.gui.current_db.prefs)
            self.grid_rules.commit(self.gui.current_db.prefs)
            gprefs['cover_grid_color'] = tuple(self.cg_bg_widget.bcol.getRgb())[:3]
            gprefs['cover_grid_texture'] = self.cg_bg_widget.btex
            if self.commit_icon_theme is not None:
                self.commit_icon_theme()
                rr = True
            gprefs['default_author_link'] = self.default_author_link.value
        return rr

    def refresh_gui(self, gui):
        m = gui.library_view.model()
        m.beginResetModel(), m.endResetModel()
        self.update_font_display()
        gui.tags_view.set_look_and_feel()
        gui.tags_view.reread_collapse_parameters()
        gui.library_view.refresh_book_details()
        gui.library_view.refresh_grid()
        gui.library_view.set_row_header_visibility()
        gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections'])
        gui.cover_flow.setPreserveAspectRatio(gprefs['cb_preserve_aspect_ratio'])
        gui.update_cover_flow_subtitle_font()
        gui.cover_flow.template_inited = False
        for view in 'library memory card_a card_b'.split():
            getattr(gui, view + '_view').set_row_header_visibility()
        gui.library_view.refresh_row_sizing()
        gui.grid_view.refresh_settings()
        qv = get_quickview_action_plugin()
        if qv:
            qv.refill_quickview()
Exemple #10
0
class ConfigWidget(ConfigWidgetBase, Ui_Form):
    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r("gui_layout", config, restart_required=True, choices=[(_("Wide"), "wide"), (_("Narrow"), "narrow")])
        r(
            "ui_style",
            gprefs,
            restart_required=True,
            choices=[(_("System default"), "system"), (_("Calibre style"), "calibre")],
        )
        r("book_list_tooltips", gprefs)
        r("tag_browser_old_look", gprefs, restart_required=True)
        r("bd_show_cover", gprefs)
        r("bd_overlay_cover_size", gprefs)
        r("cover_grid_width", gprefs)
        r("cover_grid_height", gprefs)
        r("cover_grid_cache_size", gprefs)
        r("cover_grid_spacing", gprefs)
        r("cover_grid_show_title", gprefs)

        r("cover_flow_queue_length", config, restart_required=True)
        r("cover_browser_reflections", gprefs)
        r("extra_row_spacing", gprefs)

        def get_esc_lang(l):
            if l == "en":
                return "English"
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = "en"
        items = [(l, get_esc_lang(l)) for l in available_translations() if l != lang]
        if lang != "en":
            items.append(("en", get_esc_lang("en")))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r("language", prefs, choices=choices, restart_required=True)

        r("show_avg_rating", config)
        r("disable_animations", config)
        r("systray_icon", config, restart_required=True)
        r("show_splash_screen", gprefs)
        r("disable_tray_notification", config)
        r("use_roman_numerals_for_series_number", config)
        r("separate_cover_flow", config, restart_required=True)
        r("cb_fullscreen", gprefs)

        choices = [(_("Off"), "off"), (_("Small"), "small"), (_("Medium"), "medium"), (_("Large"), "large")]
        r("toolbar_icon_size", gprefs, choices=choices)

        choices = [(_("If there is enough room"), "auto"), (_("Always"), "always"), (_("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("default_author_link", gprefs)
        r("tag_browser_dont_collapse", gprefs, setting=CommaSeparatedList)

        choices = set(
            [
                k
                for k in db.field_metadata.all_field_keys()
                if (
                    db.field_metadata[k]["is_category"]
                    and (db.field_metadata[k]["datatype"] in ["text", "series", "enumeration"])
                    and not db.field_metadata[k]["display"].get("is_names", False)
                )
                or (
                    db.field_metadata[k]["datatype"] in ["composite"]
                    and db.field_metadata[k]["display"].get("make_category", False)
                )
            ]
        )
        choices -= set(["authors", "publisher", "formats", "news", "identifiers"])
        choices |= set(["search"])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r(
            "categories_using_hierarchy",
            db.prefs,
            setting=CommaSeparatedList,
            choices=sorted(list(choices), key=sort_key),
        )

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules, QIcon(I("format-fill-color.png")), _("Column coloring"))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules, QIcon(I("icon_choose.png")), _("Column icons"))

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence("F11", QKeySequence.PortableText), QKeySequence("Ctrl+Shift+F", QKeySequence.PortableText)]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode(self.fs_help_msg.text()) % (_(" or ").join(keys)))
        self.cover_grid_color_button.clicked.connect(self.change_cover_grid_color)
        if not tweaks.get("use_new_db", False):
            for i in range(self.tabWidget.count()):
                if self.tabWidget.widget(i) is self.cover_grid_tab:
                    self.tabWidget.removeTab(i)

    def initialize(self):
        ConfigWidgetBase.initialize(self)
        font = gprefs["font"]
        if font is not None:
            font = list(font)
            font.append(gprefs.get("font_stretch", QFont.Unstretched))
        self.current_font = self.initial_font = font
        self.update_font_display()
        self.display_model.initialize()
        db = self.gui.current_db
        try:
            idx = self.gui.library_view.currentIndex().row()
            mi = db.get_metadata(idx, index_is_id=False)
        except:
            mi = None
        self.edit_rules.initialize(db.field_metadata, db.prefs, mi, "column_color_rules")
        self.icon_rules.initialize(db.field_metadata, db.prefs, mi, "column_icon_rules")
        self.set_cg_color(gprefs["cover_grid_color"])

    def set_cg_color(self, val):
        pal = QPalette()
        pal.setColor(QPalette.Window, QColor(*val))
        self.cover_grid_color_label.setPalette(pal)

    def restore_defaults(self):
        ConfigWidgetBase.restore_defaults(self)
        ofont = self.current_font
        self.current_font = None
        if ofont is not None:
            self.changed_signal.emit()
            self.update_font_display()
        self.display_model.restore_defaults()
        self.edit_rules.clear()
        self.icon_rules.clear()
        self.changed_signal.emit()
        self.set_cg_color(gprefs.defaults["cover_grid_color"])

    def change_cover_grid_color(self):
        col = QColorDialog.getColor(
            self.cover_grid_color_label.palette().color(QPalette.Window),
            self.gui,
            _("Choose background color for cover grid"),
        )
        if col.isValid():
            col = tuple(col.getRgb())[:3]
            self.set_cg_color(col)
            self.changed_signal.emit()

    def build_font_obj(self):
        font_info = self.current_font
        if font_info is not None:
            font = QFont(*(font_info[:4]))
            font.setStretch(font_info[4])
        else:
            font = qt_app.original_font
        return font

    def update_font_display(self):
        font = self.build_font_obj()
        fi = QFontInfo(font)
        name = unicode(fi.family())

        self.font_display.setFont(font)
        self.font_display.setText(name + " [%dpt]" % fi.pointSize())

    def move_df_up(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, -1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def move_df_down(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, 1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def change_font(self, *args):
        fd = QFontDialog(self.build_font_obj(), self)
        if fd.exec_() == fd.Accepted:
            font = fd.selectedFont()
            fi = QFontInfo(font)
            self.current_font = [unicode(fi.family()), fi.pointSize(), fi.weight(), fi.italic(), font.stretch()]
            self.update_font_display()
            self.changed_signal.emit()

    def commit(self, *args):
        rr = ConfigWidgetBase.commit(self, *args)
        if self.current_font != self.initial_font:
            gprefs["font"] = self.current_font[:4] if self.current_font else None
            gprefs["font_stretch"] = self.current_font[4] if self.current_font is not None else QFont.Unstretched
            QApplication.setFont(self.font_display.font())
            rr = True
        self.display_model.commit()
        self.edit_rules.commit(self.gui.current_db.prefs)
        self.icon_rules.commit(self.gui.current_db.prefs)
        gprefs["cover_grid_color"] = tuple(self.cover_grid_color_label.palette().color(QPalette.Window).getRgb())[:3]
        return rr

    def refresh_gui(self, gui):
        gui.library_view.model().reset()
        self.update_font_display()
        gui.tags_view.reread_collapse_parameters()
        gui.library_view.refresh_book_details()
        if hasattr(gui.cover_flow, "setShowReflections"):
            gui.cover_flow.setShowReflections(gprefs["cover_browser_reflections"])
        gui.library_view.refresh_row_sizing()
        gui.grid_view.refresh_settings()
Exemple #11
0
    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r('gui_layout',
          config,
          restart_required=True,
          choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('ui_style',
          gprefs,
          restart_required=True,
          choices=[(_('System default'), 'system'),
                   (_('Calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('tag_browser_old_look', gprefs, restart_required=True)

        r('cover_flow_queue_length', config, restart_required=True)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations() \
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
                   (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'),
                   (_('Always'), 'always'), (_('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('default_author_link', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        choices = set([
            k for k in db.field_metadata.all_field_keys()
            if (db.field_metadata[k]['is_category'] and
                (db.field_metadata[k]['datatype'] in
                 ['text', 'series', 'enumeration'])
                and not db.field_metadata[k]['display'].get('is_names', False))
            or (db.field_metadata[k]['datatype'] in ['composite'] and
                db.field_metadata[k]['display'].get('make_category', False))
        ])
        choices -= set(
            ['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy',
          db.prefs,
          setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                              QIcon(I('format-fill-color.png')),
                              _('Column coloring'))
        self.tabWidget.setCurrentIndex(0)
        keys = [
            QKeySequence('F11', QKeySequence.PortableText),
            QKeySequence('Ctrl+Shift+F', QKeySequence.PortableText)
        ]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(
            unicode(self.fs_help_msg.text()) % (_(' or ').join(keys)))
Exemple #12
0
class ConfigWidget(ConfigWidgetBase, Ui_Form):
    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r('gui_layout',
          config,
          restart_required=True,
          choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('ui_style',
          gprefs,
          restart_required=True,
          choices=[(_('System default'), 'system'),
                   (_('Calibre style'), 'calibre')])
        r('book_list_tooltips', gprefs)
        r('tag_browser_old_look', gprefs, restart_required=True)

        r('cover_flow_queue_length', config, restart_required=True)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations() \
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
                   (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'),
                   (_('Always'), 'always'), (_('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('default_author_link', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        choices = set([
            k for k in db.field_metadata.all_field_keys()
            if (db.field_metadata[k]['is_category'] and
                (db.field_metadata[k]['datatype'] in
                 ['text', 'series', 'enumeration'])
                and not db.field_metadata[k]['display'].get('is_names', False))
            or (db.field_metadata[k]['datatype'] in ['composite'] and
                db.field_metadata[k]['display'].get('make_category', False))
        ])
        choices -= set(
            ['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy',
          db.prefs,
          setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                              QIcon(I('format-fill-color.png')),
                              _('Column coloring'))
        self.tabWidget.setCurrentIndex(0)
        keys = [
            QKeySequence('F11', QKeySequence.PortableText),
            QKeySequence('Ctrl+Shift+F', QKeySequence.PortableText)
        ]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(
            unicode(self.fs_help_msg.text()) % (_(' or ').join(keys)))

    def initialize(self):
        ConfigWidgetBase.initialize(self)
        font = gprefs['font']
        if font is not None:
            font = list(font)
            font.append(gprefs.get('font_stretch', QFont.Unstretched))
        self.current_font = self.initial_font = font
        self.update_font_display()
        self.display_model.initialize()
        db = self.gui.current_db
        try:
            idx = self.gui.library_view.currentIndex().row()
            mi = db.get_metadata(idx, index_is_id=False)
        except:
            mi = None
        self.edit_rules.initialize(db.field_metadata, db.prefs, mi)

    def restore_defaults(self):
        ConfigWidgetBase.restore_defaults(self)
        ofont = self.current_font
        self.current_font = None
        if ofont is not None:
            self.changed_signal.emit()
            self.update_font_display()
        self.display_model.restore_defaults()
        self.edit_rules.clear()
        self.changed_signal.emit()

    def build_font_obj(self):
        font_info = self.current_font
        if font_info is not None:
            font = QFont(*(font_info[:4]))
            font.setStretch(font_info[4])
        else:
            font = qt_app.original_font
        return font

    def update_font_display(self):
        font = self.build_font_obj()
        fi = QFontInfo(font)
        name = unicode(fi.family())

        self.font_display.setFont(font)
        self.font_display.setText(name + ' [%dpt]' % fi.pointSize())

    def move_df_up(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, -1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def move_df_down(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, 1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def change_font(self, *args):
        fd = QFontDialog(self.build_font_obj(), self)
        if fd.exec_() == fd.Accepted:
            font = fd.selectedFont()
            fi = QFontInfo(font)
            self.current_font = [
                unicode(fi.family()),
                fi.pointSize(),
                fi.weight(),
                fi.italic(),
                font.stretch()
            ]
            self.update_font_display()
            self.changed_signal.emit()

    def commit(self, *args):
        rr = ConfigWidgetBase.commit(self, *args)
        if self.current_font != self.initial_font:
            gprefs['font'] = (self.current_font[:4]
                              if self.current_font else None)
            gprefs['font_stretch'] = (self.current_font[4] if self.current_font
                                      is not None else QFont.Unstretched)
            QApplication.setFont(self.font_display.font())
            rr = True
        self.display_model.commit()
        self.edit_rules.commit(self.gui.current_db.prefs)
        return rr

    def refresh_gui(self, gui):
        gui.library_view.model().reset()
        self.update_font_display()
        gui.tags_view.reread_collapse_parameters()
        gui.library_view.refresh_book_details()
Exemple #13
0
    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r('gui_layout', config, restart_required=True, choices=
                [(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('ui_style', gprefs, restart_required=True, choices=
                [(_('System default'), 'system'), (_('Calibre style'),
                    'calibre')])
        r('book_list_tooltips', gprefs)
        r('tag_browser_old_look', gprefs, restart_required=True)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations() \
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
            (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'), (_('Always'), 'always'),
            (_('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('default_author_link', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        choices = set([k for k in db.field_metadata.all_field_keys()
                if (db.field_metadata[k]['is_category'] and
                   (db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']) and
                    not db.field_metadata[k]['display'].get('is_names', False))
                  or
                   (db.field_metadata[k]['datatype'] in ['composite'] and
                    db.field_metadata[k]['display'].get('make_category', False))])
        choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))


        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                QIcon(I('format-fill-color.png')), _('Column coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules,
                QIcon(I('icon_choose.png')), _('Column icons'))

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence(
            'Ctrl+Shift+F', QKeySequence.PortableText)]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
            _(' or ').join(keys)))
Exemple #14
0
class ConfigWidget(ConfigWidgetBase, Ui_Form):

    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r('gui_layout', config, restart_required=True, choices=
                [(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
        r('ui_style', gprefs, restart_required=True, choices=
                [(_('System default'), 'system'), (_('Calibre style'),
                    'calibre')])
        r('book_list_tooltips', gprefs)
        r('tag_browser_old_look', gprefs, restart_required=True)
        r('bd_show_cover', gprefs)
        r('bd_overlay_cover_size', gprefs)

        r('cover_flow_queue_length', config, restart_required=True)
        r('cover_browser_reflections', gprefs)

        def get_esc_lang(l):
            if l == 'en':
                return 'English'
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = 'en'
        items = [(l, get_esc_lang(l)) for l in available_translations() \
                 if l != lang]
        if lang != 'en':
            items.append(('en', get_esc_lang('en')))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r('language', prefs, choices=choices, restart_required=True)

        r('show_avg_rating', config)
        r('disable_animations', config)
        r('systray_icon', config, restart_required=True)
        r('show_splash_screen', gprefs)
        r('disable_tray_notification', config)
        r('use_roman_numerals_for_series_number', config)
        r('separate_cover_flow', config, restart_required=True)
        r('cb_fullscreen', gprefs)

        choices = [(_('Off'), 'off'), (_('Small'), 'small'),
            (_('Medium'), 'medium'), (_('Large'), 'large')]
        r('toolbar_icon_size', gprefs, choices=choices)

        choices = [(_('If there is enough room'), 'auto'), (_('Always'), 'always'),
            (_('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('default_author_link', gprefs)
        r('tag_browser_dont_collapse', gprefs, setting=CommaSeparatedList)

        choices = set([k for k in db.field_metadata.all_field_keys()
                if (db.field_metadata[k]['is_category'] and
                   (db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']) and
                    not db.field_metadata[k]['display'].get('is_names', False))
                  or
                   (db.field_metadata[k]['datatype'] in ['composite'] and
                    db.field_metadata[k]['display'].get('make_category', False))])
        choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
        choices |= set(['search'])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
          choices=sorted(list(choices), key=sort_key))


        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules,
                QIcon(I('format-fill-color.png')), _('Column coloring'))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules,
                QIcon(I('icon_choose.png')), _('Column icons'))

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence(
            'Ctrl+Shift+F', QKeySequence.PortableText)]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
            _(' or ').join(keys)))

    def initialize(self):
        ConfigWidgetBase.initialize(self)
        font = gprefs['font']
        if font is not None:
            font = list(font)
            font.append(gprefs.get('font_stretch', QFont.Unstretched))
        self.current_font = self.initial_font = font
        self.update_font_display()
        self.display_model.initialize()
        db = self.gui.current_db
        try:
            idx = self.gui.library_view.currentIndex().row()
            mi = db.get_metadata(idx, index_is_id=False)
        except:
            mi=None
        self.edit_rules.initialize(db.field_metadata, db.prefs, mi, 'column_color_rules')
        self.icon_rules.initialize(db.field_metadata, db.prefs, mi, 'column_icon_rules')

    def restore_defaults(self):
        ConfigWidgetBase.restore_defaults(self)
        ofont = self.current_font
        self.current_font = None
        if ofont is not None:
            self.changed_signal.emit()
            self.update_font_display()
        self.display_model.restore_defaults()
        self.edit_rules.clear()
        self.icon_rules.clear()
        self.changed_signal.emit()

    def build_font_obj(self):
        font_info = self.current_font
        if font_info is not None:
            font = QFont(*(font_info[:4]))
            font.setStretch(font_info[4])
        else:
            font = qt_app.original_font
        return font

    def update_font_display(self):
        font = self.build_font_obj()
        fi = QFontInfo(font)
        name = unicode(fi.family())

        self.font_display.setFont(font)
        self.font_display.setText(name +
                ' [%dpt]'%fi.pointSize())

    def move_df_up(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, -1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def move_df_down(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, 1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def change_font(self, *args):
        fd = QFontDialog(self.build_font_obj(), self)
        if fd.exec_() == fd.Accepted:
            font = fd.selectedFont()
            fi = QFontInfo(font)
            self.current_font = [unicode(fi.family()), fi.pointSize(),
                    fi.weight(), fi.italic(), font.stretch()]
            self.update_font_display()
            self.changed_signal.emit()

    def commit(self, *args):
        rr = ConfigWidgetBase.commit(self, *args)
        if self.current_font != self.initial_font:
            gprefs['font'] = (self.current_font[:4] if self.current_font else
                    None)
            gprefs['font_stretch'] = (self.current_font[4] if self.current_font
                    is not None else QFont.Unstretched)
            QApplication.setFont(self.font_display.font())
            rr = True
        self.display_model.commit()
        self.edit_rules.commit(self.gui.current_db.prefs)
        self.icon_rules.commit(self.gui.current_db.prefs)
        return rr

    def refresh_gui(self, gui):
        gui.library_view.model().reset()
        self.update_font_display()
        gui.tags_view.reread_collapse_parameters()
        gui.library_view.refresh_book_details()
        if hasattr(gui.cover_flow, 'setShowReflections'):
            gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections'])
Exemple #15
0
class ConfigWidget(ConfigWidgetBase, Ui_Form):

    size_calculated = pyqtSignal(object)

    def genesis(self, gui):
        self.gui = gui
        db = gui.library_view.model().db

        r = self.register

        r("gui_layout", config, restart_required=True, choices=[(_("Wide"), "wide"), (_("Narrow"), "narrow")])
        r(
            "ui_style",
            gprefs,
            restart_required=True,
            choices=[(_("System default"), "system"), (_("Calibre style"), "calibre")],
        )
        r("book_list_tooltips", gprefs)
        r("tag_browser_old_look", gprefs, restart_required=True)
        r("bd_show_cover", gprefs)
        r("bd_overlay_cover_size", gprefs)
        r("cover_grid_width", gprefs)
        r("cover_grid_height", gprefs)
        r("cover_grid_cache_size", gprefs)
        r("cover_grid_disk_cache_size", gprefs)
        r("cover_grid_spacing", gprefs)
        r("cover_grid_show_title", gprefs)

        r("cover_flow_queue_length", config, restart_required=True)
        r("cover_browser_reflections", gprefs)
        r("extra_row_spacing", gprefs)

        def get_esc_lang(l):
            if l == "en":
                return "English"
            return get_language(l)

        lang = get_lang()
        if lang is None or lang not in available_translations():
            lang = "en"
        items = [(l, get_esc_lang(l)) for l in available_translations() if l != lang]
        if lang != "en":
            items.append(("en", get_esc_lang("en")))
        items.sort(cmp=lambda x, y: cmp(x[1].lower(), y[1].lower()))
        choices = [(y, x) for x, y in items]
        # Default language is the autodetected one
        choices = [(get_language(lang), lang)] + choices
        r("language", prefs, choices=choices, restart_required=True)

        r("show_avg_rating", config)
        r("disable_animations", config)
        r("systray_icon", config, restart_required=True)
        r("show_splash_screen", gprefs)
        r("disable_tray_notification", config)
        r("use_roman_numerals_for_series_number", config)
        r("separate_cover_flow", config, restart_required=True)
        r("cb_fullscreen", gprefs)

        choices = [(_("Off"), "off"), (_("Small"), "small"), (_("Medium"), "medium"), (_("Large"), "large")]
        r("toolbar_icon_size", gprefs, choices=choices)

        choices = [(_("If there is enough room"), "auto"), (_("Always"), "always"), (_("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("default_author_link", gprefs)
        r("tag_browser_dont_collapse", gprefs, setting=CommaSeparatedList)

        choices = set(
            [
                k
                for k in db.field_metadata.all_field_keys()
                if (
                    db.field_metadata[k]["is_category"]
                    and (db.field_metadata[k]["datatype"] in ["text", "series", "enumeration"])
                    and not db.field_metadata[k]["display"].get("is_names", False)
                )
                or (
                    db.field_metadata[k]["datatype"] in ["composite"]
                    and db.field_metadata[k]["display"].get("make_category", False)
                )
            ]
        )
        choices -= set(["authors", "publisher", "formats", "news", "identifiers"])
        choices |= set(["search"])
        self.opt_categories_using_hierarchy.update_items_cache(choices)
        r(
            "categories_using_hierarchy",
            db.prefs,
            setting=CommaSeparatedList,
            choices=sorted(list(choices), key=sort_key),
        )

        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])
        )
        r("field_under_covers_in_grid", db.prefs, choices=choices)

        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)
        self.df_up_button.clicked.connect(self.move_df_up)
        self.df_down_button.clicked.connect(self.move_df_down)

        self.edit_rules = EditRules(self.tabWidget)
        self.edit_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.edit_rules, QIcon(I("format-fill-color.png")), _("Column coloring"))

        self.icon_rules = EditRules(self.tabWidget)
        self.icon_rules.changed.connect(self.changed_signal)
        self.tabWidget.addTab(self.icon_rules, QIcon(I("icon_choose.png")), _("Column icons"))

        self.tabWidget.setCurrentIndex(0)
        keys = [QKeySequence("F11", QKeySequence.PortableText), QKeySequence("Ctrl+Shift+F", QKeySequence.PortableText)]
        keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
        self.fs_help_msg.setText(unicode(self.fs_help_msg.text()) % (_(" or ").join(keys)))
        self.size_calculated.connect(self.update_cg_cache_size, type=Qt.QueuedConnection)
        self.tabWidget.currentChanged.connect(self.tab_changed)

        l = self.cg_background_box.layout()
        self.cg_bg_widget = w = Background(self)
        l.addWidget(w, 0, 0, 3, 1)
        self.cover_grid_color_button = b = QPushButton(_("Change &color"), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 0, 1)
        b.clicked.connect(self.change_cover_grid_color)
        self.cover_grid_texture_button = b = QPushButton(_("Change &background image"), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 1, 1)
        b.clicked.connect(self.change_cover_grid_texture)
        self.cover_grid_default_appearance_button = b = QPushButton(_("Restore &default appearance"), self)
        b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        l.addWidget(b, 2, 1)
        b.clicked.connect(self.restore_cover_grid_appearance)
        self.cover_grid_empty_cache.clicked.connect(self.empty_cache)
        self.cover_grid_open_cache.clicked.connect(self.open_cg_cache)
        self.cover_grid_smaller_cover.clicked.connect(partial(self.resize_cover, True))
        self.cover_grid_larger_cover.clicked.connect(partial(self.resize_cover, False))
        self.cover_grid_reset_size.clicked.connect(self.cg_reset_size)
        self.opt_cover_grid_disk_cache_size.setMinimum(self.gui.grid_view.thumbnail_cache.min_disk_cache)
        self.opt_cover_grid_disk_cache_size.setMaximum(self.gui.grid_view.thumbnail_cache.min_disk_cache * 100)
        self.opt_cover_grid_width.valueChanged.connect(self.update_aspect_ratio)
        self.opt_cover_grid_height.valueChanged.connect(self.update_aspect_ratio)

    @property
    def current_cover_size(self):
        cval = self.opt_cover_grid_height.value()
        wval = self.opt_cover_grid_width.value()
        if cval < 0.1:
            dpi = self.opt_cover_grid_height.logicalDpiY()
            cval = auto_height(self.opt_cover_grid_height) / dpi / CM_TO_INCH
        if wval < 0.1:
            wval = 0.75 * cval
        return wval, cval

    def update_aspect_ratio(self, *args):
        width, height = self.current_cover_size
        ar = width / height
        self.cover_grid_aspect_ratio.setText(_("Current aspect ratio (width/height): %.2g") % ar)

    def resize_cover(self, smaller):
        wval, cval = self.current_cover_size
        ar = wval / cval
        delta = 0.2 * (-1 if smaller else 1)
        cval += delta
        cval = max(0, cval)
        self.opt_cover_grid_height.setValue(cval)
        self.opt_cover_grid_width.setValue(cval * ar)

    def cg_reset_size(self):
        self.opt_cover_grid_width.setValue(0)
        self.opt_cover_grid_height.setValue(0)

    def initialize(self):
        ConfigWidgetBase.initialize(self)
        font = gprefs["font"]
        if font is not None:
            font = list(font)
            font.append(gprefs.get("font_stretch", QFont.Unstretched))
        self.current_font = self.initial_font = font
        self.update_font_display()
        self.display_model.initialize()
        db = self.gui.current_db
        try:
            idx = self.gui.library_view.currentIndex().row()
            mi = db.get_metadata(idx, index_is_id=False)
        except:
            mi = None
        self.edit_rules.initialize(db.field_metadata, db.prefs, mi, "column_color_rules")
        self.icon_rules.initialize(db.field_metadata, db.prefs, mi, "column_icon_rules")
        self.set_cg_color(gprefs["cover_grid_color"])
        self.set_cg_texture(gprefs["cover_grid_texture"])
        self.update_aspect_ratio()

    def open_cg_cache(self):
        open_local_file(self.gui.grid_view.thumbnail_cache.location)

    def update_cg_cache_size(self, size):
        self.cover_grid_current_disk_cache.setText(_("Current space used: %s") % human_readable(size))

    def tab_changed(self, index):
        if self.tabWidget.currentWidget() is self.cover_grid_tab:
            self.show_current_cache_usage()

    def show_current_cache_usage(self):
        t = Thread(target=self.calc_cache_size)
        t.daemon = True
        t.start()

    def calc_cache_size(self):
        self.size_calculated.emit(self.gui.grid_view.thumbnail_cache.current_size)

    def set_cg_color(self, val):
        self.cg_bg_widget.bcol = QColor(*val)
        self.cg_bg_widget.update_brush()

    def set_cg_texture(self, val):
        self.cg_bg_widget.btex = val
        self.cg_bg_widget.update_brush()

    def empty_cache(self):
        self.gui.grid_view.thumbnail_cache.empty()
        self.calc_cache_size()

    def restore_defaults(self):
        ConfigWidgetBase.restore_defaults(self)
        ofont = self.current_font
        self.current_font = None
        if ofont is not None:
            self.changed_signal.emit()
            self.update_font_display()
        self.display_model.restore_defaults()
        self.edit_rules.clear()
        self.icon_rules.clear()
        self.changed_signal.emit()
        self.set_cg_color(gprefs.defaults["cover_grid_color"])
        self.set_cg_texture(gprefs.defaults["cover_grid_texture"])

    def change_cover_grid_color(self):
        col = QColorDialog.getColor(self.cg_bg_widget.bcol, self.gui, _("Choose background color for cover grid"))
        if col.isValid():
            col = tuple(col.getRgb())[:3]
            self.set_cg_color(col)
            self.changed_signal.emit()
            if self.cg_bg_widget.btex:
                if question_dialog(
                    self,
                    _("Remove background image?"),
                    _(
                        "There is currently a background image set, so the color"
                        " you have chosen will not be visible. Remove the background image?"
                    ),
                ):
                    self.set_cg_texture(None)

    def change_cover_grid_texture(self):
        from calibre.gui2.preferences.texture_chooser import TextureChooser

        d = TextureChooser(parent=self, initial=self.cg_bg_widget.btex)
        if d.exec_() == d.Accepted:
            self.set_cg_texture(d.texture)
            self.changed_signal.emit()

    def restore_cover_grid_appearance(self):
        self.set_cg_color(gprefs.defaults["cover_grid_color"])
        self.set_cg_texture(gprefs.defaults["cover_grid_texture"])
        self.changed_signal.emit()

    def build_font_obj(self):
        font_info = self.current_font
        if font_info is not None:
            font = QFont(*(font_info[:4]))
            font.setStretch(font_info[4])
        else:
            font = qt_app.original_font
        return font

    def update_font_display(self):
        font = self.build_font_obj()
        fi = QFontInfo(font)
        name = unicode(fi.family())

        self.font_display.setFont(font)
        self.font_display.setText(name + " [%dpt]" % fi.pointSize())

    def move_df_up(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, -1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def move_df_down(self):
        idx = self.field_display_order.currentIndex()
        if idx.isValid():
            idx = self.display_model.move(idx, 1)
            if idx is not None:
                sm = self.field_display_order.selectionModel()
                sm.select(idx, sm.ClearAndSelect)
                self.field_display_order.setCurrentIndex(idx)

    def change_font(self, *args):
        fd = QFontDialog(self.build_font_obj(), self)
        if fd.exec_() == fd.Accepted:
            font = fd.selectedFont()
            fi = QFontInfo(font)
            self.current_font = [unicode(fi.family()), fi.pointSize(), fi.weight(), fi.italic(), font.stretch()]
            self.update_font_display()
            self.changed_signal.emit()

    def commit(self, *args):
        rr = ConfigWidgetBase.commit(self, *args)
        if self.current_font != self.initial_font:
            gprefs["font"] = self.current_font[:4] if self.current_font else None
            gprefs["font_stretch"] = self.current_font[4] if self.current_font is not None else QFont.Unstretched
            QApplication.setFont(self.font_display.font())
            rr = True
        self.display_model.commit()
        self.edit_rules.commit(self.gui.current_db.prefs)
        self.icon_rules.commit(self.gui.current_db.prefs)
        gprefs["cover_grid_color"] = tuple(self.cg_bg_widget.bcol.getRgb())[:3]
        gprefs["cover_grid_texture"] = self.cg_bg_widget.btex
        return rr

    def refresh_gui(self, gui):
        gui.library_view.model().reset()
        self.update_font_display()
        gui.tags_view.reread_collapse_parameters()
        gui.library_view.refresh_book_details()
        if hasattr(gui.cover_flow, "setShowReflections"):
            gui.cover_flow.setShowReflections(gprefs["cover_browser_reflections"])
        gui.library_view.refresh_row_sizing()
        gui.grid_view.refresh_settings()