Allow multiple icons for column icons

Column icons: Allow the use of multiple icons with column icon rules.
You can now have column icon rules display multiple icons in a single
column, side by side. There are two ways to do this, either specify
multiple icons when creating the rule, or create multiple rules that
match the same book and specify the icon type to be 'composed' for every
rule. See Preferences->Look & Feel->Column icons for details.

Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
Kovid Goyal 2013-09-18 16:24:14 +05:30
commit 455afaa08f
5 changed files with 210 additions and 111 deletions

View File

@ -7,7 +7,7 @@ import json, os, traceback
from PyQt4.Qt import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter, QFont, from PyQt4.Qt import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter, QFont,
QRegExp, QApplication, QTextCharFormat, QColor, QCursor, QRegExp, QApplication, QTextCharFormat, QColor, QCursor,
QIcon, QSize) QIcon, QSize, QVariant)
from calibre import sanitize_file_name_unicode from calibre import sanitize_file_name_unicode
from calibre.constants import config_dir from calibre.constants import config_dir
@ -19,7 +19,6 @@ from calibre.ebooks.metadata.book.formatter import SafeFormat
from calibre.library.coloring import (displayable_columns, color_row_key) from calibre.library.coloring import (displayable_columns, color_row_key)
from calibre.gui2 import error_dialog, choose_files, pixmap_to_data from calibre.gui2 import error_dialog, choose_files, pixmap_to_data
class ParenPosition: class ParenPosition:
def __init__(self, block, pos, paren): def __init__(self, block, pos, paren):
@ -247,9 +246,15 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.icon_file_names.append(icon_file) self.icon_file_names.append(icon_file)
self.icon_file_names.sort(key=sort_key) self.icon_file_names.sort(key=sort_key)
self.update_filename_box() self.update_filename_box()
self.icon_with_text.setChecked(True)
if icon_rule_kind == 'icon_only': dex = 0
self.icon_without_text.setChecked(True) from calibre.gui2.preferences.coloring import icon_rule_kinds
for i,tup in enumerate(icon_rule_kinds):
txt,val = tup
self.icon_kind.addItem(txt, userData=QVariant(val))
if val == icon_rule_kind:
dex = i
self.icon_kind.setCurrentIndex(dex)
self.icon_field.setCurrentIndex(self.icon_field.findData(icon_field_key)) self.icon_field.setCurrentIndex(self.icon_field.findData(icon_field_key))
if mi: if mi:
@ -410,7 +415,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.rule = (unicode(self.colored_field.itemData( self.rule = (unicode(self.colored_field.itemData(
self.colored_field.currentIndex()).toString()), txt) self.colored_field.currentIndex()).toString()), txt)
elif self.iconing: elif self.iconing:
rt = 'icon' if self.icon_with_text.isChecked() else 'icon_only' rt = unicode(self.icon_kind.itemData(self.icon_kind.currentIndex()).toString())
self.rule = (rt, self.rule = (rt,
unicode(self.icon_field.itemData( unicode(self.icon_field.itemData(
self.icon_field.currentIndex()).toString()), self.icon_field.currentIndex()).toString()),

View File

@ -69,33 +69,19 @@
<widget class="QWidget" name="icon_layout"> <widget class="QWidget" name="icon_layout">
<layout class="QGridLayout"> <layout class="QGridLayout">
<item row="0" column="0" colspan="2"> <item row="0" column="0" colspan="2">
<widget class="QGroupBox">
<property name="title">
<string>Kind</string>
</property>
<layout class="QHBoxLayout"> <layout class="QHBoxLayout">
<item> <item>
<widget class="QRadioButton" name="icon_without_text"> <widget class="QLabel">
<property name="text"> <property name="text">
<string>icon with no text</string> <string>Kind:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QRadioButton" name="icon_with_text"> <widget class="QComboBox" name="icon_kind">
<property name="text">
<string>icon with text</string>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>100</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="icon_chooser_label"> <widget class="QLabel" name="icon_chooser_label">

View File

@ -9,7 +9,7 @@ import functools, re, os, traceback, errno, time
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from PyQt4.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage, from PyQt4.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage,
QModelIndex, QVariant, QDateTime, QColor, QPixmap) QModelIndex, QVariant, QDateTime, QColor, QPixmap, QPainter)
from calibre.gui2 import NONE, error_dialog from calibre.gui2 import NONE, error_dialog
from calibre.utils.search_query_parser import ParseException from calibre.utils.search_query_parser import ParseException
@ -61,7 +61,7 @@ class ColumnColor(object): # {{{
return color_cache[id_][key] return color_cache[id_][key]
try: try:
if self.mi is None: if self.mi is None:
self.mi = db.get_metadata(id_, index_is_id=True) self.mi = db.new_api.get_proxy_metadata(id_)
color = self.formatter.safe_format(fmt, self.mi, '', self.mi) color = self.formatter.safe_format(fmt, self.mi, '', self.mi)
if color in self.colors: if color in self.colors:
color = QColor(color) color = QColor(color)
@ -76,38 +76,68 @@ class ColumnColor(object): # {{{
class ColumnIcon(object): # {{{ class ColumnIcon(object): # {{{
def __init__(self, formatter): def __init__(self, formatter, model):
self.mi = None self.mi = None
self.formatter = formatter self.formatter = formatter
self.model = model
def __call__(self, id_, key, fmt, kind, db, icon_cache, icon_bitmap_cache): def __call__(self, id_, key, fmts, cache_index, db, icon_cache, icon_bitmap_cache):
dex = key+kind if id_ in icon_cache and cache_index in icon_cache[id_]:
if id_ in icon_cache and dex in icon_cache[id_]:
self.mi = None self.mi = None
return icon_cache[id_][dex] return icon_cache[id_][cache_index]
try: try:
if self.mi is None: if self.mi is None:
self.mi = db.get_metadata(id_, index_is_id=True) self.mi = db.new_api.get_proxy_metadata(id_)
icon = self.formatter.safe_format(fmt, self.mi, '', self.mi) icons = []
if icon: for kind, fmt in fmts:
if icon in icon_bitmap_cache: rule_icons = self.formatter.safe_format(fmt, self.mi, '', self.mi)
icon_bitmap = icon_bitmap_cache[icon] if not rule_icons:
icon_cache[id_][dex] = icon_bitmap continue
icon_list = [ic.strip() for ic in rule_icons.split(':')]
if icon_list and not kind.endswith('_composed'):
icons = icon_list
break
else:
icons.extend(icon_list)
if icons:
icon_string = ':'.join(icons)
if icon_string in icon_bitmap_cache:
icon_bitmap = icon_bitmap_cache[icon_string]
icon_cache[id_][cache_index] = icon_bitmap
return icon_bitmap return icon_bitmap
icon_bitmaps = []
total_width = 0
for icon in icons:
d = os.path.join(config_dir, 'cc_icons', icon) d = os.path.join(config_dir, 'cc_icons', icon)
if (os.path.exists(d)): if (os.path.exists(d)):
icon_bitmap = QPixmap(d) bm = QPixmap(d)
h = icon_bitmap.height() icon_bitmaps.append(bm)
w = icon_bitmap.width() total_width += bm.width()
# If the image is landscape and width is more than 50% if len(icon_bitmaps) > 1:
# large than height, use the pixmap. This tells Qt to display i = len(icon_bitmaps)
# the image full width. It might be clipped to row height. result = QPixmap((i * 128) + ((i-1)*2), 128)
if w < (3 * h)/2: result.fill(Qt.transparent)
icon_bitmap = QIcon(icon_bitmap) painter = QPainter(result)
icon_cache[id_][dex] = icon_bitmap x = 0
icon_bitmap_cache[icon] = icon_bitmap for bm in icon_bitmaps:
painter.drawPixmap(x, 0, bm)
x += bm.width() + 2
painter.end()
else:
result = icon_bitmaps[0]
# If the image height is less than the row height, leave it alone
# The -2 allows for a pixel above and below. Also ensure that
# it is always a bit positive
rh = max(2, self.model.row_height - 2)
if result.height() > rh:
result = result.scaledToHeight(rh, mode=Qt.SmoothTransformation)
icon_cache[id_][cache_index] = result
icon_bitmap_cache[icon_string] = result
self.mi = None self.mi = None
return icon_bitmap return result
except: except:
pass pass
# }}} # }}}
@ -145,7 +175,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.colors = frozenset([unicode(c) for c in QColor.colorNames()]) self.colors = frozenset([unicode(c) for c in QColor.colorNames()])
self._clear_caches() self._clear_caches()
self.column_color = ColumnColor(self.formatter, self.colors) self.column_color = ColumnColor(self.formatter, self.colors)
self.column_icon = ColumnIcon(self.formatter) self.column_icon = ColumnIcon(self.formatter, self)
self.book_on_device = None self.book_on_device = None
self.editable_cols = ['title', 'authors', 'rating', 'publisher', self.editable_cols = ['title', 'authors', 'rating', 'publisher',
@ -168,6 +198,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.ids_to_highlight_set = set() self.ids_to_highlight_set = set()
self.current_highlighted_idx = None self.current_highlighted_idx = None
self.highlight_only = False self.highlight_only = False
self.row_height = 0
self.read_config() self.read_config()
def _clear_caches(self): def _clear_caches(self):
@ -176,6 +207,9 @@ class BooksModel(QAbstractTableModel): # {{{
self.icon_bitmap_cache = {} self.icon_bitmap_cache = {}
self.color_row_fmt_cache = None self.color_row_fmt_cache = None
def set_row_height(self, height):
self.row_height = height
def change_alignment(self, colname, alignment): def change_alignment(self, colname, alignment):
if colname in self.column_map and alignment in ('left', 'right', 'center'): if colname in self.column_map and alignment in ('left', 'right', 'center'):
old = self.alignment_map.get(colname, 'left') old = self.alignment_map.get(colname, 'left')
@ -765,16 +799,21 @@ class BooksModel(QAbstractTableModel): # {{{
if rules: if rules:
key = self.column_map[col] key = self.column_map[col]
id_ = None id_ = None
fmts = []
for kind, k, fmt in rules: for kind, k, fmt in rules:
if k == key and kind == 'icon_only': if k == key and kind in {'icon_only', 'icon_only_composed'}:
if id_ is None: if id_ is None:
id_ = self.id(index) id_ = self.id(index)
self.column_icon.mi = None self.column_icon.mi = None
ccicon = self.column_icon(id_, key, fmt, 'icon_only', self.db, fmts.append((kind, fmt))
if fmts:
cache_index = key + ':DisplayRole'
ccicon = self.column_icon(id_, key, fmts, cache_index, self.db,
self.icon_cache, self.icon_bitmap_cache) self.icon_cache, self.icon_bitmap_cache)
if ccicon is not None: if ccicon is not None:
return NONE return NONE
self.icon_cache[id_][key+'icon_only'] = None self.icon_cache[id_][cache_index] = None
return self.column_to_dc_map[col](index.row()) return self.column_to_dc_map[col](index.row())
elif role in (Qt.EditRole, Qt.ToolTipRole): elif role in (Qt.EditRole, Qt.ToolTipRole):
return self.column_to_dc_map[col](index.row()) return self.column_to_dc_map[col](index.row())
@ -831,21 +870,25 @@ class BooksModel(QAbstractTableModel): # {{{
key = self.column_map[col] key = self.column_map[col]
id_ = None id_ = None
need_icon_with_text = False need_icon_with_text = False
fmts = []
for kind, k, fmt in rules: for kind, k, fmt in rules:
if k == key and kind in ('icon', 'icon_only'): if k == key and kind.startswith('icon'):
if id_ is None: if id_ is None:
id_ = self.id(index) id_ = self.id(index)
self.column_icon.mi = None self.column_icon.mi = None
if kind == 'icon': fmts.append((kind, fmt))
if kind in ('icon', 'icon_composed'):
need_icon_with_text = True need_icon_with_text = True
ccicon = self.column_icon(id_, key, fmt, kind, self.db, if fmts:
cache_index = key + ':DecorationRole'
ccicon = self.column_icon(id_, key, fmts, cache_index, self.db,
self.icon_cache, self.icon_bitmap_cache) self.icon_cache, self.icon_bitmap_cache)
if ccicon is not None: if ccicon is not None:
return ccicon return ccicon
if need_icon_with_text: if need_icon_with_text:
self.icon_cache[id_][key+'icon'] = self.bool_blank_icon self.icon_cache[id_][cache_index] = self.bool_blank_icon
return self.bool_blank_icon return self.bool_blank_icon
self.icon_cache[id_][key+'icon'] = None self.icon_cache[id_][cache_index] = None
elif role == Qt.TextAlignmentRole: elif role == Qt.TextAlignmentRole:
cname = self.column_map[index.column()] cname = self.column_map[index.column()]
ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname, ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname,

View File

@ -649,6 +649,7 @@ class BooksView(QTableView): # {{{
self.resizeRowToContents(0) self.resizeRowToContents(0)
self.verticalHeader().setDefaultSectionSize(self.rowHeight(0) + self.verticalHeader().setDefaultSectionSize(self.rowHeight(0) +
gprefs['extra_row_spacing']) gprefs['extra_row_spacing'])
self._model.set_row_height(self.rowHeight(0))
self.row_sizing_done = True self.row_sizing_done = True
def resize_column_to_fit(self, column): def resize_column_to_fit(self, column):

View File

@ -7,13 +7,13 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os import os, textwrap
from PyQt4.Qt import (QWidget, QDialog, QLabel, QGridLayout, QComboBox, QSize, from PyQt4.Qt import (QWidget, QDialog, QLabel, QGridLayout, QComboBox, QSize,
QLineEdit, QIntValidator, QDoubleValidator, QFrame, QColor, Qt, QIcon, QLineEdit, QIntValidator, QDoubleValidator, QFrame, QColor, Qt, QIcon,
QScrollArea, QPushButton, QVBoxLayout, QDialogButtonBox, QToolButton, QScrollArea, QPushButton, QVBoxLayout, QDialogButtonBox, QToolButton,
QListView, QAbstractListModel, pyqtSignal, QSizePolicy, QSpacerItem, QListView, QAbstractListModel, pyqtSignal, QSizePolicy, QSpacerItem,
QApplication) QApplication, QStandardItem, QStandardItemModel, QCheckBox)
from calibre import prepare_string_for_xml, sanitize_file_name_unicode from calibre import prepare_string_for_xml, sanitize_file_name_unicode
from calibre.constants import config_dir from calibre.constants import config_dir
@ -29,7 +29,9 @@ from calibre.utils.icu import lower
all_columns_string = _('All Columns') all_columns_string = _('All Columns')
icon_rule_kinds = [(_('icon with text'), 'icon'), icon_rule_kinds = [(_('icon with text'), 'icon'),
(_('icon with no text'), 'icon_only') ] (_('icon with no text'), 'icon_only'),
(_('composed icons w/text'), 'icon_composed'),
(_('composed icons w/no text'), 'icon_only_composed'),]
class ConditionEditor(QWidget): # {{{ class ConditionEditor(QWidget): # {{{
@ -312,6 +314,10 @@ class RuleEditor(QDialog): # {{{
for tt, t in icon_rule_kinds: for tt, t in icon_rule_kinds:
self.kind_box.addItem(tt, t) self.kind_box.addItem(tt, t)
l.addWidget(self.kind_box, 2, 1) l.addWidget(self.kind_box, 2, 1)
self.kind_box.setToolTip(textwrap.fill(_(
'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.')))
self.l3 = l3 = QLabel(_('of the column:')) self.l3 = l3 = QLabel(_('of the column:'))
l.addWidget(l3, 2, 2) l.addWidget(l3, 2, 2)
@ -331,7 +337,6 @@ class RuleEditor(QDialog): # {{{
l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7)
else: else:
self.filename_box = QComboBox() self.filename_box = QComboBox()
self.filename_box.setInsertPolicy(self.filename_box.InsertAlphabetically)
d = os.path.join(config_dir, 'cc_icons') d = os.path.join(config_dir, 'cc_icons')
self.icon_file_names = [] self.icon_file_names = []
if os.path.exists(d): if os.path.exists(d):
@ -341,9 +346,15 @@ class RuleEditor(QDialog): # {{{
if icon_file.endswith('.png'): if icon_file.endswith('.png'):
self.icon_file_names.append(icon_file) self.icon_file_names.append(icon_file)
self.icon_file_names.sort(key=sort_key) self.icon_file_names.sort(key=sort_key)
self.update_filename_box()
l.addWidget(self.filename_box, 2, 5) vb = QVBoxLayout()
self.multiple_icon_cb = QCheckBox(_('Choose more than one icon'))
vb.addWidget(self.multiple_icon_cb)
self.update_filename_box()
self.multiple_icon_cb.clicked.connect(self.multiple_box_clicked)
vb.addWidget(self.filename_box)
l.addLayout(vb, 2, 5)
self.filename_button = QPushButton(QIcon(I('document_open.png')), self.filename_button = QPushButton(QIcon(I('document_open.png')),
_('&Add icon')) _('&Add icon'))
l.addWidget(self.filename_button, 2, 6) l.addWidget(self.filename_button, 2, 6)
@ -401,18 +412,37 @@ class RuleEditor(QDialog): # {{{
self.update_color_label() self.update_color_label()
self.color_box.currentIndexChanged.connect(self.update_color_label) self.color_box.currentIndexChanged.connect(self.update_color_label)
else: else:
self.rule_icon_files = []
self.filename_button.clicked.connect(self.filename_button_clicked) self.filename_button.clicked.connect(self.filename_button_clicked)
self.resize(self.sizeHint()) self.resize(self.sizeHint())
def multiple_box_clicked(self):
self.update_filename_box()
self.update_icon_filenames_in_box()
def update_filename_box(self): def update_filename_box(self):
self.filename_box.clear() doing_multiple = self.multiple_icon_cb.isChecked()
model = QStandardItemModel()
self.filename_box.setModel(model)
self.icon_file_names.sort(key=sort_key) self.icon_file_names.sort(key=sort_key)
self.filename_box.addItem('') if doing_multiple:
self.filename_box.addItems(self.icon_file_names) item = QStandardItem(_('Open to see checkboxes'))
else:
item = QStandardItem('')
model.appendRow(item)
for i,filename in enumerate(self.icon_file_names): for i,filename in enumerate(self.icon_file_names):
item = QStandardItem(filename)
if doing_multiple:
item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled);
item.setData(Qt.Unchecked, Qt.CheckStateRole)
else:
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable);
icon = QIcon(os.path.join(config_dir, 'cc_icons', filename)) icon = QIcon(os.path.join(config_dir, 'cc_icons', filename))
self.filename_box.setItemIcon(i+1, icon) item.setIcon(icon)
model.appendRow(item)
def update_color_label(self): def update_color_label(self):
pal = QApplication.palette() pal = QApplication.palette()
@ -432,9 +462,9 @@ class RuleEditor(QDialog): # {{{
all_files=False, select_only_single_file=True) all_files=False, select_only_single_file=True)
if path: if path:
icon_path = path[0] icon_path = path[0]
icon_name = sanitize_file_name_unicode( icon_name = lower(sanitize_file_name_unicode(
os.path.splitext( os.path.splitext(
os.path.basename(icon_path))[0]+'.png') os.path.basename(icon_path))[0]+'.png'))
if icon_name not in self.icon_file_names: if icon_name not in self.icon_file_names:
self.icon_file_names.append(icon_name) self.icon_file_names.append(icon_name)
self.update_filename_box() self.update_filename_box()
@ -449,6 +479,11 @@ class RuleEditor(QDialog): # {{{
except: except:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
if self.multiple_icon_cb.isChecked():
if icon_name not in self.rule_icon_files:
self.rule_icon_files.append(icon_name)
self.update_icon_filenames_in_box()
else:
self.filename_box.setCurrentIndex(self.filename_box.findText(icon_name)) self.filename_box.setCurrentIndex(self.filename_box.findText(icon_name))
self.filename_box.adjustSize() self.filename_box.adjustSize()
except: except:
@ -456,6 +491,35 @@ class RuleEditor(QDialog): # {{{
traceback.print_exc() traceback.print_exc()
return return
def get_filenames_from_box(self):
if self.multiple_icon_cb.isChecked():
model = self.filename_box.model()
fnames = []
for i in range(1, model.rowCount()):
item = model.item(i, 0)
if item.checkState() == Qt.Checked:
fnames.append(lower(unicode(item.text())))
fname = ' : '.join(fnames)
else:
fname = lower(unicode(self.filename_box.currentText()))
return fname
def update_icon_filenames_in_box(self):
if self.rule_icon_files:
if not self.multiple_icon_cb.isChecked():
idx = self.filename_box.findText(self.rule_icon_files[0])
if idx >= 0:
self.filename_box.setCurrentIndex(idx)
else:
self.filename_box.setCurrentIndex(0)
else:
model = self.filename_box.model()
for icon in self.rule_icon_files:
idx = self.filename_box.findText(icon)
if idx >= 0:
item = model.item(idx)
item.setCheckState(Qt.Checked)
def add_blank_condition(self): def add_blank_condition(self):
c = ConditionEditor(self.fm, parent=self.conditions_widget) c = ConditionEditor(self.fm, parent=self.conditions_widget)
self.conditions.append(c) self.conditions.append(c)
@ -468,13 +532,15 @@ class RuleEditor(QDialog): # {{{
if idx >= 0: if idx >= 0:
self.color_box.setCurrentIndex(idx) self.color_box.setCurrentIndex(idx)
else: else:
self.kind_box.setCurrentIndex(0 if kind == 'icon' else 1) for i,tup in enumerate(icon_rule_kinds):
if rule.color: if kind == tup[1]:
idx = self.filename_box.findText(rule.color) self.kind_box.setCurrentIndex(i)
if idx >= 0: break
self.filename_box.setCurrentIndex(idx) self.rule_icon_files = [ic.strip() for ic in rule.color.split(':')]
else: if len(self.rule_icon_files) > 1:
self.filename_box.setCurrentIndex(0) self.multiple_icon_cb.setChecked(True)
self.update_filename_box()
self.update_icon_filenames_in_box()
for i in range(self.column_box.count()): for i in range(self.column_box.count()):
c = unicode(self.column_box.itemData(i).toString()) c = unicode(self.column_box.itemData(i).toString())
@ -492,10 +558,9 @@ class RuleEditor(QDialog): # {{{
import traceback import traceback
traceback.print_exc() traceback.print_exc()
def accept(self): def accept(self):
if self.rule_kind != 'color': if self.rule_kind != 'color':
fname = lower(unicode(self.filename_box.currentText())) fname = self.get_filenames_from_box()
if not fname: if not fname:
error_dialog(self, _('No icon selected'), error_dialog(self, _('No icon selected'),
_('You must choose an icon for this rule'), show=True) _('You must choose an icon for this rule'), show=True)
@ -528,7 +593,7 @@ class RuleEditor(QDialog): # {{{
def rule(self): def rule(self):
r = Rule(self.fm) r = Rule(self.fm)
if self.rule_kind != 'color': if self.rule_kind != 'color':
r.color = unicode(self.filename_box.currentText()) r.color = self.get_filenames_from_box()
else: else:
r.color = unicode(self.color_box.currentText()) r.color = unicode(self.color_box.currentText())
idx = self.column_box.currentIndex() idx = self.column_box.currentIndex()
@ -635,6 +700,15 @@ class RulesModel(QAbstractListModel): # {{{
self.reset() self.reset()
def rule_to_html(self, kind, col, rule): def rule_to_html(self, kind, col, rule):
trans_kind = 'not found'
if kind == 'color':
trans_kind = _('color')
else:
for tt, t in icon_rule_kinds:
if kind == t:
trans_kind = tt
break
if not isinstance(rule, Rule): if not isinstance(rule, Rule):
if kind == 'color': if kind == 'color':
return _(''' return _('''
@ -646,21 +720,11 @@ class RulesModel(QAbstractListModel): # {{{
<p>Advanced Rule: set <b>%(typ)s</b> for column <b>%(col)s</b>: <p>Advanced Rule: set <b>%(typ)s</b> for column <b>%(col)s</b>:
<pre>%(rule)s</pre> <pre>%(rule)s</pre>
''')%dict(col=col, ''')%dict(col=col,
typ=icon_rule_kinds[0][0] typ=trans_kind,
if kind == icon_rule_kinds[0][1] else icon_rule_kinds[1][0],
rule=prepare_string_for_xml(rule)) rule=prepare_string_for_xml(rule))
conditions = [self.condition_to_html(c) for c in rule.conditions] conditions = [self.condition_to_html(c) for c in rule.conditions]
trans_kind = 'not found'
if kind == 'color':
trans_kind = _('color')
else:
for tt, t in icon_rule_kinds:
if kind == t:
trans_kind = tt
break
return _('''\ return _('''\
<p>Set the <b>%(kind)s</b> of <b>%(col)s</b> to <b>%(color)s</b> if the following <p>Set the <b>%(kind)s</b> of <b>%(col)s</b> to <b>%(color)s</b> if the following
conditions are met:</p> conditions are met:</p>