From 3c92c4a988eca819c813baf2f306cc0cfbff69c9 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 22 May 2011 14:14:23 +0100 Subject: [PATCH] More work on coloring columns. Refactor the template editor, add some documentation for the new template function first_non_empty, add help text to the configuration dialog. --- .../gui2/dialogs/template_line_editor.py | 2 +- src/calibre/gui2/library/models.py | 2 - src/calibre/gui2/preferences/look_feel.py | 26 +++++++- src/calibre/gui2/preferences/look_feel.ui | 66 +++++++++++-------- src/calibre/gui2/preferences/plugboard.py | 26 +------- src/calibre/manual/template_lang.rst | 1 + src/calibre/utils/formatter_functions.py | 19 +++++- 7 files changed, 85 insertions(+), 57 deletions(-) diff --git a/src/calibre/gui2/dialogs/template_line_editor.py b/src/calibre/gui2/dialogs/template_line_editor.py index d7ba8e4900..69999f59a0 100644 --- a/src/calibre/gui2/dialogs/template_line_editor.py +++ b/src/calibre/gui2/dialogs/template_line_editor.py @@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en' from PyQt4.Qt import (SIGNAL, QLineEdit) from calibre.gui2.dialogs.template_dialog import TemplateDialog -class LineEditWithTextBox(QLineEdit): +class TemplateLineEditor(QLineEdit): ''' Extend the context menu of a QLineEdit to include more actions. diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 7d6cfadacb..83bf5868ba 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -535,12 +535,10 @@ class BooksModel(QAbstractTableModel): # {{{ return img def set_color_templates(self): - print 'here' self.column_color_map = {} for i in range(1,self.db.column_color_count+1): name = self.db.prefs.get('column_color_name_'+str(i)) if name: - print name, self.db.prefs.get('column_color_template_'+str(i)) self.column_color_map[name] = \ self.db.prefs.get('column_color_template_'+str(i)) self.refresh() diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index fc6990fcc9..97400c45bd 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -6,7 +6,7 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' from PyQt4.Qt import (QApplication, QFont, QFontInfo, QFontDialog, - QAbstractListModel, Qt) + QAbstractListModel, Qt, QColor) from calibre.gui2.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList from calibre.gui2.preferences.look_feel_ui import Ui_Form @@ -159,12 +159,36 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.df_up_button.clicked.connect(self.move_df_up) self.df_down_button.clicked.connect(self.move_df_down) + self.color_help_text.setWordWrap(True) + self.color_help_text.setText('

' + + _('Here you can specify coloring rules for fields shown in the ' + 'library view. Choose the field you wish to color, then ' + 'supply a template that specifies the color to use.') + + '

' + + _('The template must evaluate to one of the color names shown ' + 'below. You can use any legal template expression. ' + 'For example, you can set the title to always display in ' + 'green using the template "green" (without the quotes). ' + 'To show the title in blue if the book has the tag "Science ' + 'Fiction", red if the book has the tag "Mystery", or black if ' + 'the book has neither tag, use ' + '"{tags:switch(Science Fiction,blue,Mystery,red,)}" ' + 'To show the title in green if it has one format, blue if it ' + 'two formats, and red if more, use ' + "\"program:cmp(count(field('formats'),','), 2, 'green', 'blue', 'red')\"") + + '

' + + _('Note: if you want to color a "custom column with a fixed set ' + 'of values", it is possible and often easier to specify the ' + 'colors in the column definition dialog. There you can ' + 'provide a color for each value without using a template.')+ '

') choices = db.field_metadata.displayable_field_keys() choices.sort(key=sort_key) choices.insert(0, '') for i in range(1, db.column_color_count+1): r('column_color_name_'+str(i), db.prefs, choices=choices) r('column_color_template_'+str(i), db.prefs) + all_colors = [unicode(s) for s in list(QColor.colorNames())] + self.colors_box.setText(', '.join(all_colors)) def initialize(self): ConfigWidgetBase.initialize(self) diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index d7fca70c08..aa5afe26dd 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -416,72 +416,80 @@ then the tags will be displayed each on their own line. Column Coloring - + Column name - + + + + + Selection template - + - - - - - - - - - + - + - + - + - + - + - + - - - - Qt::Vertical + + + + + + + + + + + + Color names - - - 690 - 283 - + + + + + + + 0 + 1 + - + @@ -496,7 +504,7 @@ then the tags will be displayed each on their own line.
calibre/gui2/complete.h
- LineEditWithTextBox + TemplateLineEditor QLineEdit
calibre/gui2/dialogs/template_line_editor.h
diff --git a/src/calibre/gui2/preferences/plugboard.py b/src/calibre/gui2/preferences/plugboard.py index b4b1d4e08e..cf632c04c0 100644 --- a/src/calibre/gui2/preferences/plugboard.py +++ b/src/calibre/gui2/preferences/plugboard.py @@ -7,12 +7,12 @@ __docformat__ = 'restructuredtext en' import copy -from PyQt4.Qt import Qt, QLineEdit, QComboBox, SIGNAL, QListWidgetItem +from PyQt4.Qt import Qt, QComboBox, QListWidgetItem from calibre.customize.ui import is_disabled from calibre.gui2 import error_dialog, question_dialog from calibre.gui2.device import device_name_for_plugboards -from calibre.gui2.dialogs.template_dialog import TemplateDialog +from calibre.gui2.dialogs.template_line_editor import TemplateLineEditor from calibre.gui2.preferences import ConfigWidgetBase, test_widget from calibre.gui2.preferences.plugboard_ui import Ui_Form from calibre.customize.ui import metadata_writers, device_plugins @@ -24,26 +24,6 @@ from calibre.library.server.content import plugboard_content_server_value, \ from calibre.utils.formatter import validation_formatter -class LineEditWithTextBox(QLineEdit): - - ''' - Extend the context menu of a QLineEdit to include more actions. - ''' - - def contextMenuEvent(self, event): - menu = self.createStandardContextMenu() - menu.addSeparator() - - action_open_editor = menu.addAction(_('Open Editor')) - - self.connect(action_open_editor, SIGNAL('triggered()'), self.open_editor) - menu.exec_(event.globalPos()) - - def open_editor(self): - t = TemplateDialog(self, self.text()) - if t.exec_(): - self.setText(t.textbox.toPlainText()) - class ConfigWidget(ConfigWidgetBase, Ui_Form): def genesis(self, gui): @@ -107,7 +87,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.source_widgets = [] self.dest_widgets = [] for i in range(0, len(self.dest_fields)-1): - w = LineEditWithTextBox(self) + w = TemplateLineEditor(self) self.source_widgets.append(w) self.fields_layout.addWidget(w, 5+i, 0, 1, 1) w = QComboBox(self) diff --git a/src/calibre/manual/template_lang.rst b/src/calibre/manual/template_lang.rst index 0fd396fb64..9b5fe63f25 100644 --- a/src/calibre/manual/template_lang.rst +++ b/src/calibre/manual/template_lang.rst @@ -234,6 +234,7 @@ The following functions are available in addition to those described in single-f * ``cmp(x, y, lt, eq, gt)`` -- compares x and y after converting both to numbers. Returns ``lt`` if x < y. Returns ``eq`` if x == y. Otherwise returns ``gt``. * ``divide(x, y)`` -- returns x / y. Throws an exception if either x or y are not numbers. * ``field(name)`` -- returns the metadata field named by ``name``. + * ``first_non_empty(value, value, ...) -- returns the first value that is not empty. If all values are empty, then the empty value is returned. You can have as many values as you want. * ``format_date(x, date_format)`` -- format_date(val, format_string) -- format the value, which must be a date field, using the format_string, returning a string. The formatting codes are:: d : the day as number without a leading zero (1 to 31) diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index aa8e4fb3a3..59a750bcc5 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -562,6 +562,22 @@ class BuiltinBooksize(BuiltinFormatterFunction): pass return '' +class BuiltinFirstNonEmpty(BuiltinFormatterFunction): + name = 'first_non_empty' + arg_count = -1 + doc = _('first_non_empty(value, value, ...) -- ' + 'returns the first value that is not empty. If all values are ' + 'empty, then the empty value is returned.' + 'You can have as many values as you want.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + i = 0 + while i < len(args): + if args[i]: + return args[i] + i += 1 + return '' + builtin_add = BuiltinAdd() builtin_assign = BuiltinAssign() builtin_booksize = BuiltinBooksize() @@ -571,8 +587,9 @@ builtin_contains = BuiltinContains() builtin_count = BuiltinCount() builtin_divide = BuiltinDivide() builtin_eval = BuiltinEval() -builtin_format_date = BuiltinFormat_date() +builtin_first_non_empty = BuiltinFirstNonEmpty() builtin_field = BuiltinField() +builtin_format_date = BuiltinFormat_date() builtin_ifempty = BuiltinIfempty() builtin_list_item = BuiltinListitem() builtin_lookup = BuiltinLookup()