diff --git a/src/calibre/db/backend.py b/src/calibre/db/backend.py index cdcb14bcf0..0afc2bac72 100644 --- a/src/calibre/db/backend.py +++ b/src/calibre/db/backend.py @@ -407,6 +407,7 @@ class DB(object): defs['categories_using_hierarchy'] = [] defs['column_color_rules'] = [] defs['column_icon_rules'] = [] + defs['cover_grid_icon_rules'] = [] defs['grouped_search_make_user_categories'] = [] defs['similar_authors_search_key'] = 'authors' defs['similar_authors_match_kind'] = 'match_any' diff --git a/src/calibre/gui2/preferences/coloring.py b/src/calibre/gui2/preferences/coloring.py index 80350a1db4..117d9bbe4a 100644 --- a/src/calibre/gui2/preferences/coloring.py +++ b/src/calibre/gui2/preferences/coloring.py @@ -278,24 +278,31 @@ class ConditionEditor(QWidget): # {{{ class RuleEditor(QDialog): # {{{ + @property + def doing_multiple(self): + return hasattr(self, 'multiple_icon_cb') and self.multiple_icon_cb.isChecked() + def __init__(self, fm, pref_name, parent=None): QDialog.__init__(self, parent) self.fm = fm if pref_name == 'column_color_rules': self.rule_kind = 'color' - rule_text = _('coloring') - else: + rule_text = _('column coloring') + elif pref_name == 'column_icon_rules': self.rule_kind = 'icon' - rule_text = _('icon') + rule_text = _('column icon') + elif pref_name == 'cover_grid_icon_rules': + self.rule_kind = 'emblem' + rule_text = _('cover grid emblem') self.setWindowIcon(QIcon(I('format-fill-color.png'))) - self.setWindowTitle(_('Create/edit a column {0} rule').format(rule_text)) + self.setWindowTitle(_('Create/edit a {0} rule').format(rule_text)) self.l = l = QGridLayout(self) self.setLayout(l) - self.l1 = l1 = QLabel(_('Create a column {0} rule by' + self.l1 = l1 = QLabel(_('Create a {0} rule by' ' filling in the boxes below'.format(rule_text))) l.addWidget(l1, 0, 0, 1, 8) @@ -303,12 +310,12 @@ class RuleEditor(QDialog): # {{{ self.f1.setFrameShape(QFrame.HLine) l.addWidget(self.f1, 1, 0, 1, 8) - self.l2 = l2 = QLabel(_('Set the')) + self.l2 = l2 = QLabel(_('Add the emblem:') if self.rule_kind == 'emblem' else _('Set the')) l.addWidget(l2, 2, 0) if self.rule_kind == 'color': l.addWidget(QLabel(_('color'))) - else: + elif self.rule_kind == 'icon': self.kind_box = QComboBox(self) for tt, t in icon_rule_kinds: self.kind_box.addItem(tt, t) @@ -317,6 +324,8 @@ class RuleEditor(QDialog): # {{{ 'If you choose composed icons and multiple rules match, then all the' ' matching icons will be combined, otherwise the icon from the' ' first rule to match will be used.'))) + else: + pass self.l3 = l3 = QLabel(_('of the column:')) l.addWidget(l3, 2, 2) @@ -326,17 +335,12 @@ class RuleEditor(QDialog): # {{{ self.l4 = l4 = QLabel(_('to')) l.addWidget(l4, 2, 4) + if self.rule_kind == 'emblem': + l3.setVisible(False), self.column_box.setVisible(False), l4.setVisible(False) - if self.rule_kind == 'color': - self.color_box = ColorButton(parent=self) - self.color_label = QLabel('Sample text Sample text') - self.color_label.setTextFormat(Qt.RichText) - l.addWidget(self.color_box, 2, 5) - l.addWidget(self.color_label, 2, 6) - l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) - else: + def create_filename_box(folder='cc_icons'): self.filename_box = QComboBox() - d = os.path.join(config_dir, 'cc_icons') + d = os.path.join(config_dir, folder) self.icon_file_names = [] if os.path.exists(d): for icon_file in os.listdir(d): @@ -346,6 +350,25 @@ class RuleEditor(QDialog): # {{{ self.icon_file_names.append(icon_file) self.icon_file_names.sort(key=sort_key) + if self.rule_kind == 'color': + self.color_box = ColorButton(parent=self) + self.color_label = QLabel('Sample text Sample text') + self.color_label.setTextFormat(Qt.RichText) + l.addWidget(self.color_box, 2, 5) + l.addWidget(self.color_label, 2, 6) + l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) + elif self.rule_kind == 'emblem': + create_filename_box() + self.update_filename_box() + self.filename_button = QPushButton(QIcon(I('document_open.png')), + _('&Add new image')) + l.addWidget(self.filename_box) + l.addWidget(self.filename_button, 2, 6) + l.addWidget(QLabel(_('(Images should be square-ish)')), 2, 7) + l.setColumnStretch(7, 10) + else: + create_filename_box() + vb = QVBoxLayout() self.multiple_icon_cb = QCheckBox(_('Choose more than one icon')) vb.addWidget(self.multiple_icon_cb) @@ -420,7 +443,7 @@ class RuleEditor(QDialog): # {{{ self.update_icon_filenames_in_box() def update_filename_box(self): - doing_multiple = self.multiple_icon_cb.isChecked() + doing_multiple = self.doing_multiple model = QStandardItemModel() self.filename_box.setModel(model) @@ -477,7 +500,7 @@ class RuleEditor(QDialog): # {{{ except: import traceback traceback.print_exc() - if self.multiple_icon_cb.isChecked(): + if self.doing_multiple: if icon_name not in self.rule_icon_files: self.rule_icon_files.append(icon_name) self.update_icon_filenames_in_box() @@ -490,7 +513,7 @@ class RuleEditor(QDialog): # {{{ return def get_filenames_from_box(self): - if self.multiple_icon_cb.isChecked(): + if self.doing_multiple: model = self.filename_box.model() fnames = [] for i in range(1, model.rowCount()): @@ -504,7 +527,7 @@ class RuleEditor(QDialog): # {{{ def update_icon_filenames_in_box(self): if self.rule_icon_files: - if not self.multiple_icon_cb.isChecked(): + if not self.doing_multiple: idx = self.filename_box.findText(self.rule_icon_files[0]) if idx >= 0: self.filename_box.setCurrentIndex(idx) @@ -528,10 +551,11 @@ class RuleEditor(QDialog): # {{{ if rule.color: self.color_box.color = rule.color else: - for i,tup in enumerate(icon_rule_kinds): - if kind == tup[1]: - self.kind_box.setCurrentIndex(i) - break + if self.rule_kind == 'icon': + for i, tup in enumerate(icon_rule_kinds): + if kind == tup[1]: + self.kind_box.setCurrentIndex(i) + break self.rule_icon_files = [ic.strip() for ic in rule.color.split(':')] if len(self.rule_icon_files) > 1: self.multiple_icon_cb.setChecked(True) @@ -602,7 +626,7 @@ class RuleEditor(QDialog): # {{{ kind = unicode(self.kind_box.itemData( self.kind_box.currentIndex()).toString()) else: - kind = 'color' + kind = self.rule_kind return kind, col, r # }}} @@ -761,8 +785,8 @@ class RulesModel(QAbstractListModel): # {{{ continue break return ( - _('
  • If the %(col)s column %(action)s value: %(val)s') % - dict(col=c, action=action_name, val=prepare_string_for_xml(v))) + _('
  • If the %(col)s column %(action)s value: %(val)s') % dict( + col=c, action=action_name, val=prepare_string_for_xml(v))) # }}} @@ -824,20 +848,27 @@ class EditRules(QWidget): # {{{ self.fm = fm self.mi = mi if pref_name == 'column_color_rules': - self.l1.setText('

    '+_( + text = _( 'You can control the color of columns in the' ' book list by creating "rules" that tell calibre' ' what color to use. Click the Add Rule button below' ' to get started.

    You can change an existing rule by' - ' double clicking it.')) - else: - self.l1.setText('

    '+_( + ' double clicking it.') + elif pref_name == 'column_icon_rules': + text = _( 'You can add icons to columns in the' ' book list by creating "rules" that tell calibre' ' what icon to use. Click the Add Rule button below' ' to get started.

    You can change an existing rule by' - ' double clicking it.')) + ' double clicking it.') + elif pref_name == 'cover_grid_icon_rules': + text = _('You can add emblems (small icons) that are displayed on the side of covers' + ' in the cover grid by creating "rules" that tell calibre' + ' what image to use. Click the Add Rule button below' + ' to get started.

    You can change an existing rule by' + ' double clicking it.') # self.add_advanced_button.setVisible(False) + self.l1.setText('

    '+ text) def add_rule(self): d = RuleEditor(self.model.fm, self.pref_name) diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index 87b2564c95..2e31f9410f 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -11,7 +11,7 @@ from functools import partial from PyQt4.Qt import ( QApplication, QFont, QFontInfo, QFontDialog, QColorDialog, QPainter, QAbstractListModel, Qt, QIcon, QKeySequence, QColor, pyqtSignal, - QWidget, QSizePolicy, QBrush, QPixmap, QSize, QPushButton) + QWidget, QSizePolicy, QBrush, QPixmap, QSize, QPushButton, QVBoxLayout) from calibre import human_readable from calibre.gui2.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList @@ -240,6 +240,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): 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)] @@ -320,6 +325,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): 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() @@ -365,6 +371,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): 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']) @@ -453,6 +460,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): 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 diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index f99204c001..c0cab1f787 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -233,375 +233,417 @@ - - - Control the cover grid view. You can enable this view by clicking the grid button in the bottom right corner of the main calibre window. + + + QTabWidget::West - - true + + 0 - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - Show a field (such as title) &under the covers - - - - - - - - - &Field to show under the covers: - - - opt_field_under_covers_in_grid - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - &Spacing between covers: - - - opt_cover_grid_spacing - - - - - - - The spacing between covers. A value of zero means calculate automatically based on cover size. - - - Automatic - - - cm - - - 2 - - - 0.100000000000000 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Background for the cover grid - - - - - - - - Cover size - - - - - - - - - - - - - Cover &Width: - - - opt_cover_grid_width - - - - - - - The width of displayed covers. + + + Main + + + + + + Control the cover grid view. You can enable this view by clicking the grid button in the bottom right corner of the main calibre window. + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + Show a field (such as title) &under the covers + + + + + + + + + &Field to show under the covers: + + + opt_field_under_covers_in_grid + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + &Spacing between covers: + + + opt_cover_grid_spacing + + + + + + + The spacing between covers. A value of zero means calculate automatically based on cover size. + + + Automatic + + + cm + + + 2 + + + 0.100000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Background for the cover grid + + + + + + + + Cover size + + + + + + + + + + + + + Cover &Width: + + + opt_cover_grid_width + + + + + + + The width of displayed covers. A value of zero means calculate automatically. - - - Automatic - - - cm - - - 1 - - - - - - - Make the covers larger, maintaining current aspect ratio. - - - &Larger covers - - - - :/images/plus.png:/images/plus.png - - - - - - - Cover &Height: - - - opt_cover_grid_height - - - - - - - The height of displayed covers. + + + Automatic + + + cm + + + 1 + + + + + + + Make the covers larger, maintaining current aspect ratio. + + + &Larger covers + + + + :/images/plus.png:/images/plus.png + + + + + + + Cover &Height: + + + opt_cover_grid_height + + + + + + + The height of displayed covers. A value of zero means calculate automatically. - - - Automatic - - - cm - - - 1 - - - - - - - Make the covers smaller, maintaining current aspect ratio. - - - &Smaller covers - - - - :/images/minus.png:/images/minus.png - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - By default, calibre chooses a cover size based on your computer's screen size. You can change the cover size here: - - - true - - - - - - - Reset size to automatic - - - &Reset size - - - - + + + Automatic + + + cm + + + 1 + + + + + + + Make the covers smaller, maintaining current aspect ratio. + + + &Smaller covers + + + + :/images/minus.png:/images/minus.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + By default, calibre chooses a cover size based on your computer's screen size. You can change the cover size here: + + + true + + + + + + + Reset size to automatic + + + &Reset size + + + + + + + + + + Qt::Vertical + + + + 20 + 170 + + + + + + + + + Emblems + + + + + Performance + + + + + + Caching of covers for improved performance + + + + + + Disable + + + MB + + + 100 + + + 100 + + + + + + + Open cache directory + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + There are two kinds of caches that calibre uses to improve performance when rendering covers in the grid view. A disk cache that is kept on your hard disk and stores the cover thumbnails and an in memory cache used to ensure flicker free rendering of covers. For best results, keep the memory cache small and the disk cache large, unless you have a lot of extra RAM in your computer and dont mind it being used by the memory cache. + + + true + + + + + + + + + + + + + + Qt::Horizontal + + + + 310 + 20 + + + + + + + + Number of covers to cache in &memory (keep this small): + + + opt_cover_grid_cache_size + + + + + + + Maximum amount of disk space to use for caching thumbnails: + + + + + + + Empty disk cache + + + + + + + The maximum number of covers to keep in memory. Increasing this will make rendering faster, at the cost of more memory usage. + + + 50000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + - - - - Caching of covers for improved performance - - - - - - There are two kinds of caches that calibre uses to improve performance when rendering covers in the grid view. A disk cache that is kept on your hard disk and stores the cover thumbnails and an in memory cache used to ensure flicker free rendering of covers. For best results, keep the memory cache small and the disk cache large, unless you have a lot of extra RAM in your computer and dont mind it being used by the memory cache. - - - true - - - - - - - Number of covers to cache in &memory (keep this small): - - - opt_cover_grid_cache_size - - - - - - - The maximum number of covers to keep in memory. Increasing this will make rendering faster, at the cost of more memory usage. - - - 50000 - - - - - - - Maximum amount of disk space to use for caching thumbnails: - - - - - - - Disable - - - MB - - - 100 - - - 100 - - - - - - - - - - - - - - Empty disk cache - - - - - - - Qt::Horizontal - - - - 310 - 20 - - - - - - - - Open cache directory - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - -