mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
Add the swap_around_comma function ot the template language. Fix row numbers in a previous selection being incorrect after a sort operation.
This commit is contained in:
commit
e90676c78d
@ -260,7 +260,8 @@ class ChooseLibraryAction(InterfaceAction):
|
||||
'The files remain on your computer, if you want '
|
||||
'to delete them, you will have to do so manually.') % loc,
|
||||
show=True)
|
||||
open_local_file(loc)
|
||||
if os.path.exists(loc):
|
||||
open_local_file(loc)
|
||||
|
||||
def backup_status(self, location):
|
||||
dirty_text = 'no'
|
||||
|
@ -110,6 +110,7 @@ class BooksView(QTableView): # {{{
|
||||
self.column_header.sectionMoved.connect(self.save_state)
|
||||
self.column_header.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
self.column_header.customContextMenuRequested.connect(self.show_column_header_context_menu)
|
||||
self.column_header.sectionResized.connect(self.column_resized)
|
||||
# }}}
|
||||
|
||||
self._model.database_changed.connect(self.database_changed)
|
||||
@ -235,13 +236,8 @@ class BooksView(QTableView): # {{{
|
||||
self.selected_ids = [idc(r) for r in selected_rows]
|
||||
|
||||
def sorting_done(self, indexc):
|
||||
if self.selected_ids:
|
||||
indices = [self.model().index(indexc(i), 0) for i in
|
||||
self.selected_ids]
|
||||
sm = self.selectionModel()
|
||||
for idx in indices:
|
||||
sm.select(idx, sm.Select|sm.Rows)
|
||||
self.scroll_to_row(indices[0].row())
|
||||
self.select_rows(self.selected_ids, using_ids=True, change_current=True,
|
||||
scroll=True)
|
||||
self.selected_ids = []
|
||||
|
||||
def sort_by_named_field(self, field, order, reset=True):
|
||||
@ -456,7 +452,9 @@ class BooksView(QTableView): # {{{
|
||||
traceback.print_exc()
|
||||
old_state['sort_history'] = sh
|
||||
|
||||
self.column_header.blockSignals(True)
|
||||
self.apply_state(old_state)
|
||||
self.column_header.blockSignals(False)
|
||||
|
||||
# Resize all rows to have the correct height
|
||||
if self.model().rowCount(QModelIndex()) > 0:
|
||||
@ -465,6 +463,15 @@ class BooksView(QTableView): # {{{
|
||||
|
||||
self.was_restored = True
|
||||
|
||||
def column_resized(self, col, old_size, new_size):
|
||||
# arbitrary: scroll bar + header + some
|
||||
max_width = self.width() - (self.verticalScrollBar().width() +
|
||||
self.verticalHeader().width() + 10)
|
||||
if new_size > max_width:
|
||||
self.column_header.blockSignals(True)
|
||||
self.setColumnWidth(col, max_width)
|
||||
self.column_header.blockSignals(False)
|
||||
|
||||
# }}}
|
||||
|
||||
# Initialization/Delegate Setup {{{
|
||||
|
@ -116,7 +116,7 @@ If you have programming experience, please note that the syntax in this mode (si
|
||||
|
||||
Many functions use regular expressions. In all cases, regular expression matching is case-insensitive.
|
||||
|
||||
The functions available are:
|
||||
The functions available are listed below. Note that the definitive documentation for functions is available in the section :ref:`Function classification <template_functions_reference>`:
|
||||
|
||||
* ``lowercase()`` -- return value of the field in lower case.
|
||||
* ``uppercase()`` -- return the value of the field in upper case.
|
||||
@ -129,6 +129,7 @@ The functions available are:
|
||||
* ``list_item(index, separator)`` -- interpret the field as a list of items separated by `separator`, returning the `index`th item. The first item is number zero. The last item can be returned using `list_item(-1,separator)`. If the item is not in the list, then the empty value is returned. The separator has the same meaning as in the `count` function.
|
||||
* ``re(pattern, replacement)`` -- return the field after applying the regular expression. All instances of `pattern` are replaced with `replacement`. As in all of |app|, these are python-compatible regular expressions.
|
||||
* ``shorten(left chars, middle text, right chars)`` -- Return a shortened version of the field, consisting of `left chars` characters from the beginning of the field, followed by `middle text`, followed by `right chars` characters from the end of the string. `Left chars` and `right chars` must be integers. For example, assume the title of the book is `Ancient English Laws in the Times of Ivanhoe`, and you want it to fit in a space of at most 15 characters. If you use ``{title:shorten(9,-,5)}``, the result will be `Ancient E-nhoe`. If the field's length is less than ``left chars`` + ``right chars`` + the length of ``middle text``, then the field will be used intact. For example, the title `The Dome` would not be changed.
|
||||
* ``swap_around_comma(val) `` -- given a value of the form ``B, A``, return ``A B``. This is most useful for converting names in LN, FN format to FN LN. If there is no comma, the function returns val unchanged.
|
||||
* ``switch(pattern, value, pattern, value, ..., else_value)`` -- for each ``pattern, value`` pair, checks if the field matches the regular expression ``pattern`` and if so, returns that ``value``. If no ``pattern`` matches, then ``else_value`` is returned. You can have as many ``pattern, value`` pairs as you want.
|
||||
* ``lookup(pattern, field, pattern, field, ..., else_field)`` -- like switch, except the arguments are field (metadata) names, not text. The value of the appropriate field will be fetched and used. Note that because composite columns are fields, you can use this function in one composite field to use the value of some other composite field. This is extremely useful when constructing variable save paths (more later).
|
||||
* ``select(key)`` -- interpret the field as a comma-separated list of items, with the items being of the form "id:value". Find the pair with the id equal to key, and return the corresponding value. This function is particularly useful for extracting a value such as an isbn from the set of identifiers for a book.
|
||||
@ -230,13 +231,14 @@ For various values of series_index, the program returns:
|
||||
|
||||
**All the functions listed under single-function mode can be used in program mode**. To do so, you must supply the value that the function is to act upon as the first parameter, in addition to the parameters documented above. For example, in program mode the parameters of the `test` function are ``test(x, text_if_not_empty, text_if_empty)``. The `x` parameter, which is the value to be tested, will almost always be a variable or a function call, often `field()`.
|
||||
|
||||
The following functions are available in addition to those described in single-function mode. Remember from the example above that the single-function mode functions require an additional first parameter specifying the field to operate on. With the exception of the ``id`` parameter of assign, all parameters can be statements (sequences of expressions):
|
||||
The following functions are available in addition to those described in single-function mode. Remember from the example above that the single-function mode functions require an additional first parameter specifying the field to operate on. With the exception of the ``id`` parameter of assign, all parameters can be statements (sequences of expressions). Note that the definitive documentation for functions is available in the section :ref:`Function classification <template_functions_reference>`:
|
||||
|
||||
* ``and(value, value, ...)`` -- returns the string "1" if all values are not empty, otherwise returns the empty string. This function works well with test or first_non_empty. You can have as many values as you want.
|
||||
* ``add(x, y)`` -- returns x + y. Throws an exception if either x or y are not numbers.
|
||||
* ``assign(id, val)`` -- assigns val to id, then returns val. id must be an identifier, not an expression
|
||||
* ``booksize()`` -- returns the value of the |app| 'size' field. Returns '' if there are no formats.
|
||||
* ``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``.
|
||||
* ``days_between(date1, date2)`` -- return the number of days between ``date1`` and ``date2``. The number is positive if ``date1`` is greater than ``date2``, otherwise negative. If either ``date1`` or ``date2`` are not dates, the function returns the empty string.
|
||||
* ``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.
|
||||
@ -266,7 +268,10 @@ The following functions are available in addition to those described in single-f
|
||||
* ``strcmp(x, y, lt, eq, gt)`` -- does a case-insensitive comparison x and y as strings. Returns ``lt`` if x < y. Returns ``eq`` if x == y. Otherwise returns ``gt``.
|
||||
* ``substr(str, start, end)`` -- returns the ``start``'th through the ``end``'th characters of ``str``. The first character in ``str`` is the zero'th character. If end is negative, then it indicates that many characters counting from the right. If end is zero, then it indicates the last character. For example, ``substr('12345', 1, 0)`` returns ``'2345'``, and ``substr('12345', 1, -1)`` returns ``'234'``.
|
||||
* ``subtract(x, y)`` -- returns x - y. Throws an exception if either x or y are not numbers.
|
||||
* ``today()`` -- return a date string for today. This value is designed for use in format_date or days_between, but can be manipulated like any other string. The date is in ISO format.
|
||||
* ``template(x)`` -- evaluates x as a template. The evaluation is done in its own context, meaning that variables are not shared between the caller and the template evaluation. Because the `{` and `}` characters are special, you must use `[[` for the `{` character and `]]` for the '}' character; they are converted automatically. For example, ``template('[[title_sort]]') will evaluate the template ``{title_sort}`` and return its value.
|
||||
|
||||
.. _template_functions_reference:
|
||||
|
||||
Function classification
|
||||
---------------------------
|
||||
|
@ -417,6 +417,18 @@ class BuiltinRe(BuiltinFormatterFunction):
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val, pattern, replacement):
|
||||
return re.sub(pattern, replacement, val, flags=re.I)
|
||||
|
||||
class BuiltinSwapAroundComma(BuiltinFormatterFunction):
|
||||
name = 'swap_around_comma'
|
||||
arg_count = 1
|
||||
category = 'String Manipulation'
|
||||
__doc__ = doc = _('swap_around_comma(val) -- given a value of the form '
|
||||
'"B, A", return "A B". This is most useful for converting names '
|
||||
'in LN, FN format to FN LN. If there is no comma, the function '
|
||||
'returns val unchanged')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||
return re.sub(r'^(.*?),(.*$)', r'\2 \1', val, flags=re.I)
|
||||
|
||||
class BuiltinIfempty(BuiltinFormatterFunction):
|
||||
name = 'ifempty'
|
||||
arg_count = 2
|
||||
@ -825,6 +837,7 @@ builtin_subitems = BuiltinSubitems()
|
||||
builtin_sublist = BuiltinSublist()
|
||||
builtin_substr = BuiltinSubstr()
|
||||
builtin_subtract = BuiltinSubtract()
|
||||
builtin_swaparound = BuiltinSwapAroundComma()
|
||||
builtin_switch = BuiltinSwitch()
|
||||
builtin_template = BuiltinTemplate()
|
||||
builtin_test = BuiltinTest()
|
||||
|
Loading…
x
Reference in New Issue
Block a user