From b12e505f5c24b27dc24ccdd87c383ed781be86e8 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Fri, 17 Dec 2010 11:50:50 +0000 Subject: [PATCH] Enhancement #7892: New tweak options for series number increment --- resources/default_tweaks.py | 15 ++++++- src/calibre/gui2/custom_column_widgets.py | 8 ++-- src/calibre/gui2/dialogs/metadata_single.py | 2 +- src/calibre/gui2/library/models.py | 2 +- src/calibre/library/cli.py | 2 +- src/calibre/library/custom_columns.py | 16 +++---- src/calibre/library/database2.py | 48 ++++++++++++++++----- 7 files changed, 65 insertions(+), 28 deletions(-) diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index cd746ccdaa..750af9efa7 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -12,13 +12,24 @@ defaults. # The algorithm used to assign a new book in an existing series a series number. +# New series numbers assigned using this tweak are always integer values, except +# if a constant non-integer is specified. # Possible values are: -# next - Next available number +# next - First available integer larger than the largest existing number +# first_free - First available integer larger than 0 +# next_free - First available integer larger than the smallest existing number +# last_free - First available integer smaller than the largest existing number +# Return largest existing + 1 if no free number is found # const - Assign the number 1 always +# a number - Assign that number always. The number is not in quotes. Note that +# 0.0 can be used here. +# Examples: +# series_index_auto_increment = 'next' +# series_index_auto_increment = 'next_free' +# series_index_auto_increment = 16.5 series_index_auto_increment = 'next' - # The algorithm used to copy author to author_sort # Possible values are: # invert: use "fn ln" -> "ln, fn" (the original algorithm) diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py index 5ab8bb6940..6e4fc0a0ac 100644 --- a/src/calibre/gui2/custom_column_widgets.py +++ b/src/calibre/gui2/custom_column_widgets.py @@ -303,7 +303,7 @@ class Series(Base): if val == '': val = s_index = None elif s_index == 0.0: - if tweaks['series_index_auto_increment'] == 'next': + if tweaks['series_index_auto_increment'] != 'const': s_index = self.db.get_next_cc_series_num_for(val, num=self.col_id) else: @@ -572,7 +572,6 @@ class BulkSeries(BulkBase): val = None if clear else self.normalize_ui_val(val) if clear or val != '': extras = [] - next_index = self.db.get_next_cc_series_num_for(val, num=self.col_id) for book_id in book_ids: if clear: extras.append(None) @@ -581,9 +580,8 @@ class BulkSeries(BulkBase): if force_start: s_index = at_value at_value += 1 - elif tweaks['series_index_auto_increment'] == 'next': - s_index = next_index - next_index += 1 + elif tweaks['series_index_auto_increment'] != 'const': + s_index = self.db.get_next_cc_series_num_for(val, num=self.col_id) else: s_index = 1.0 else: diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index 99fe2017dd..133f449550 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -839,7 +839,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog): series = unicode(self.series.text()).strip() if series and series != self.original_series_name: ns = 1 - if tweaks['series_index_auto_increment'] == 'next': + if tweaks['series_index_auto_increment'] != 'const': ns = self.db.get_next_series_num_for(series) self.series_index.setValue(ns) self.original_series_name = series diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index e0d5c64961..661f21e53d 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -772,7 +772,7 @@ class BooksModel(QAbstractTableModel): # {{{ self.db.set_series_index(id, float(match.group(1))) val = pat.sub('', val).strip() elif val: - if tweaks['series_index_auto_increment'] == 'next': + if tweaks['series_index_auto_increment'] != 'const': ni = self.db.get_next_series_num_for(val) if ni != 1: self.db.set_series_index(id, ni) diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index 01e8ad449b..c98b3be4d3 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -707,7 +707,7 @@ def parse_series_string(db, label, value): val = pat.sub('', val).strip() s_index = float(match.group(1)) elif val: - if tweaks['series_index_auto_increment'] == 'next': + if tweaks['series_index_auto_increment'] != 'const': s_index = db.get_next_cc_series_num_for(val, label=label) else: s_index = 1.0 diff --git a/src/calibre/library/custom_columns.py b/src/calibre/library/custom_columns.py index f544a9bf7e..e95ace2cd4 100644 --- a/src/calibre/library/custom_columns.py +++ b/src/calibre/library/custom_columns.py @@ -8,12 +8,12 @@ __docformat__ = 'restructuredtext en' import json, re from functools import partial -from math import floor from calibre import prints from calibre.constants import preferred_encoding from calibre.library.field_metadata import FieldMetadata from calibre.utils.date import parse_date +from calibre.utils.config import tweaks class CustomColumns(object): @@ -261,15 +261,15 @@ class CustomColumns(object): series_id = self.conn.get('SELECT id from %s WHERE value=?'%table, (series,), all=False) if series_id is None: + if isinstance(tweaks['series_index_auto_increment'], (int, float)): + return float(tweaks['series_index_auto_increment']) return 1.0 - # get the label of the associated series number table - series_num = self.conn.get(''' - SELECT MAX({lt}.extra) FROM {lt} + series_indices = self.conn.get(''' + SELECT {lt}.extra FROM {lt} WHERE {lt}.book IN (SELECT book FROM {lt} where value=?) - '''.format(lt=lt), (series_id,), all=False) - if series_num is None: - return 1.0 - return floor(series_num+1) + ORDER BY {lt}.extra + '''.format(lt=lt), (series_id,)) + return self._get_next_series_num_for_list(series_indices) def all_custom(self, label=None, num=None): if label is not None: diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index b09c2bfc7c..b9ab54b80a 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -8,7 +8,7 @@ The database used to store ebook metadata ''' import os, sys, shutil, cStringIO, glob, time, functools, traceback, re from itertools import repeat -from math import floor +from math import ceil from Queue import Queue from PyQt4.QtGui import QImage @@ -1365,14 +1365,43 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): series_id = self.conn.get('SELECT id from series WHERE name=?', (series,), all=False) if series_id is None: + if isinstance(tweaks['series_index_auto_increment'], (int, float)): + return float(tweaks['series_index_auto_increment']) return 1.0 - series_num = self.conn.get( - ('SELECT MAX(series_index) FROM books WHERE id IN ' - '(SELECT book FROM books_series_link where series=?)'), - (series_id,), all=False) - if series_num is None: + series_indices = self.conn.get( + ('SELECT series_index FROM books WHERE id IN ' + '(SELECT book FROM books_series_link where series=?) ' + 'ORDER BY series_index'), + (series_id,)) + return self._get_next_series_num_for_list(series_indices) + + def _get_next_series_num_for_list(self, series_indices): + if not series_indices: + if isinstance(tweaks['series_index_auto_increment'], (int, float)): + return float(tweaks['series_index_auto_increment']) return 1.0 - return floor(series_num+1) + series_indices = [x[0] for x in series_indices] + print series_indices + if tweaks['series_index_auto_increment'] == 'next': + return series_indices[-1] + 1 + if tweaks['series_index_auto_increment'] == 'first_free': + for i in range(1, 10000): + if i not in series_indices: + return i + # really shouldn't get here. + if tweaks['series_index_auto_increment'] == 'next_free': + for i in range(int(ceil(series_indices[0])), 10000): + if i not in series_indices: + return i + # really shouldn't get here. + if tweaks['series_index_auto_increment'] == 'last_free': + for i in range(int(ceil(series_indices[-1])), 0, -1): + if i not in series_indices: + return i + return series_indices[-1] + 1 + if isinstance(tweaks['series_index_auto_increment'], (int, float)): + return float(tweaks['series_index_auto_increment']) + return 1.0 def set(self, row, column, val): ''' @@ -1760,18 +1789,17 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): FROM books, books_series_link as lt WHERE books.id = lt.book AND lt.series=? ORDER BY books.series_index''', (old_id,)) - # Get the next series index - index = self.get_next_series_num_for(new_name) # Now update the link table self.conn.execute('''UPDATE books_series_link SET series=? WHERE series=?''',(new_id, old_id,)) # Now set the indices for (book_id,) in books: + # Get the next series index + index = self.get_next_series_num_for(new_name) self.conn.execute('''UPDATE books SET series_index=? WHERE id=?''',(index, book_id,)) - index = index + 1 self.dirty_books_referencing('series', new_id, commit=False) self.conn.commit()