mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix #7643 ("Copy Structure" command). Add more tweaks to control how the enxt available series number is calculated (#7892). Add a tweak to control layout of custom metadata edit panel (#7920). Allow editing of title sort via the Edit metadata dialog.
This commit is contained in:
commit
f414aaf447
@ -12,13 +12,24 @@ defaults.
|
|||||||
|
|
||||||
|
|
||||||
# The algorithm used to assign a new book in an existing series a series number.
|
# 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:
|
# 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
|
# 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'
|
series_index_auto_increment = 'next'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# The algorithm used to copy author to author_sort
|
# The algorithm used to copy author to author_sort
|
||||||
# Possible values are:
|
# Possible values are:
|
||||||
# invert: use "fn ln" -> "ln, fn" (the original algorithm)
|
# invert: use "fn ln" -> "ln, fn" (the original algorithm)
|
||||||
@ -235,3 +246,9 @@ doubleclick_on_library_view = 'open_viewer'
|
|||||||
# Example: locale_for_sorting = 'fr' -- sort using French rules.
|
# Example: locale_for_sorting = 'fr' -- sort using French rules.
|
||||||
# Example: locale_for_sorting = 'nb' -- sort using Norwegian rules.
|
# Example: locale_for_sorting = 'nb' -- sort using Norwegian rules.
|
||||||
locale_for_sorting = ''
|
locale_for_sorting = ''
|
||||||
|
|
||||||
|
|
||||||
|
# Set whether to use one or two columns for custom metadata when editing
|
||||||
|
# metadata one book at a time. If True, then the fields are laid out using two
|
||||||
|
# columns. If False, one column is used.
|
||||||
|
metadata_single_use_2_cols_for_custom_fields = True
|
@ -303,7 +303,7 @@ class Series(Base):
|
|||||||
if val == '':
|
if val == '':
|
||||||
val = s_index = None
|
val = s_index = None
|
||||||
elif s_index == 0.0:
|
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,
|
s_index = self.db.get_next_cc_series_num_for(val,
|
||||||
num=self.col_id)
|
num=self.col_id)
|
||||||
else:
|
else:
|
||||||
@ -572,7 +572,6 @@ class BulkSeries(BulkBase):
|
|||||||
val = None if clear else self.normalize_ui_val(val)
|
val = None if clear else self.normalize_ui_val(val)
|
||||||
if clear or val != '':
|
if clear or val != '':
|
||||||
extras = []
|
extras = []
|
||||||
next_index = self.db.get_next_cc_series_num_for(val, num=self.col_id)
|
|
||||||
for book_id in book_ids:
|
for book_id in book_ids:
|
||||||
if clear:
|
if clear:
|
||||||
extras.append(None)
|
extras.append(None)
|
||||||
@ -581,9 +580,8 @@ class BulkSeries(BulkBase):
|
|||||||
if force_start:
|
if force_start:
|
||||||
s_index = at_value
|
s_index = at_value
|
||||||
at_value += 1
|
at_value += 1
|
||||||
elif tweaks['series_index_auto_increment'] == 'next':
|
elif tweaks['series_index_auto_increment'] != 'const':
|
||||||
s_index = next_index
|
s_index = self.db.get_next_cc_series_num_for(val, num=self.col_id)
|
||||||
next_index += 1
|
|
||||||
else:
|
else:
|
||||||
s_index = 1.0
|
s_index = 1.0
|
||||||
else:
|
else:
|
||||||
|
@ -32,6 +32,11 @@ class ChooseLibrary(QDialog, Ui_Dialog):
|
|||||||
loc = unicode(self.old_location.text()).format(lp)
|
loc = unicode(self.old_location.text()).format(lp)
|
||||||
self.old_location.setText(loc)
|
self.old_location.setText(loc)
|
||||||
self.browse_button.clicked.connect(self.choose_loc)
|
self.browse_button.clicked.connect(self.choose_loc)
|
||||||
|
self.empty_library.toggled.connect(self.empty_library_toggled)
|
||||||
|
self.copy_structure.setEnabled(False)
|
||||||
|
|
||||||
|
def empty_library_toggled(self, to_what):
|
||||||
|
self.copy_structure.setEnabled(to_what)
|
||||||
|
|
||||||
def choose_loc(self, *args):
|
def choose_loc(self, *args):
|
||||||
loc = choose_dir(self, 'choose library location',
|
loc = choose_dir(self, 'choose library location',
|
||||||
@ -64,7 +69,7 @@ class ChooseLibrary(QDialog, Ui_Dialog):
|
|||||||
def perform_action(self, ac, loc):
|
def perform_action(self, ac, loc):
|
||||||
if ac in ('new', 'existing'):
|
if ac in ('new', 'existing'):
|
||||||
prefs['library_path'] = loc
|
prefs['library_path'] = loc
|
||||||
self.callback(loc)
|
self.callback(loc, copy_structure=self.copy_structure.isChecked())
|
||||||
else:
|
else:
|
||||||
move_library(self.db.library_path, loc, self.parent(),
|
move_library(self.db.library_path, loc, self.parent(),
|
||||||
self.callback)
|
self.callback)
|
||||||
|
@ -49,11 +49,26 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="3">
|
<item row="5" column="0" colspan="3">
|
||||||
<widget class="QRadioButton" name="empty_library">
|
<layout class="QHBoxLayout" name="hbox1">
|
||||||
<property name="text">
|
<item>
|
||||||
<string>&Create an empty library at the new location</string>
|
<widget class="QRadioButton" name="empty_library">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>&Create an empty library at the new location</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="copy_structure">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Copy structure from the current library</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Copy the custom columns, saved searches, column widths, plugboards,
|
||||||
|
user categories, and other information from the old to the new library</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0" colspan="3">
|
<item row="6" column="0" colspan="3">
|
||||||
<widget class="QRadioButton" name="move_library">
|
<widget class="QRadioButton" name="move_library">
|
||||||
|
@ -23,7 +23,7 @@ from calibre.gui2.dialogs.tag_editor import TagEditor
|
|||||||
from calibre.gui2.widgets import ProgressIndicator
|
from calibre.gui2.widgets import ProgressIndicator
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.ebooks.metadata import string_to_authors, \
|
from calibre.ebooks.metadata import string_to_authors, \
|
||||||
authors_to_string, check_isbn
|
authors_to_string, check_isbn, title_sort
|
||||||
from calibre.ebooks.metadata.covers import download_cover
|
from calibre.ebooks.metadata.covers import download_cover
|
||||||
from calibre.ebooks.metadata.meta import get_metadata
|
from calibre.ebooks.metadata.meta import get_metadata
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
@ -444,13 +444,24 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
self.cover_fetcher = None
|
self.cover_fetcher = None
|
||||||
self.bc_box.layout().setAlignment(self.cover, Qt.AlignCenter|Qt.AlignHCenter)
|
self.bc_box.layout().setAlignment(self.cover, Qt.AlignCenter|Qt.AlignHCenter)
|
||||||
base = unicode(self.author_sort.toolTip())
|
base = unicode(self.author_sort.toolTip())
|
||||||
self.ok_aus_tooltip = '<p>' + textwrap.fill(base+'<br><br>'+
|
ok_tooltip = '<p>' + textwrap.fill(base+'<br><br>'+
|
||||||
_(' The green color indicates that the current '
|
_(' The green color indicates that the current '
|
||||||
'author sort matches the current author'))
|
'author sort matches the current author'))
|
||||||
self.bad_aus_tooltip = '<p>'+textwrap.fill(base + '<br><br>'+
|
bad_tooltip = '<p>'+textwrap.fill(base + '<br><br>'+
|
||||||
_(' The red color indicates that the current '
|
_(' The red color indicates that the current '
|
||||||
'author sort does not match the current author'))
|
'author sort does not match the current author. '
|
||||||
|
'No action is required if this is what you want.'))
|
||||||
|
self.aus_tooltips = (ok_tooltip, bad_tooltip)
|
||||||
|
|
||||||
|
base = unicode(self.title_sort.toolTip())
|
||||||
|
ok_tooltip = '<p>' + textwrap.fill(base+'<br><br>'+
|
||||||
|
_(' The green color indicates that the current '
|
||||||
|
'title sort matches the current title'))
|
||||||
|
bad_tooltip = '<p>'+textwrap.fill(base + '<br><br>'+
|
||||||
|
_(' The red color warns that the current '
|
||||||
|
'title sort does not match the current title. '
|
||||||
|
'No action is required if this is what you want.'))
|
||||||
|
self.ts_tooltips = (ok_tooltip, bad_tooltip)
|
||||||
self.row_delta = 0
|
self.row_delta = 0
|
||||||
if prev:
|
if prev:
|
||||||
self.prev_button = QPushButton(QIcon(I('back.png')), _('Previous'),
|
self.prev_button = QPushButton(QIcon(I('back.png')), _('Previous'),
|
||||||
@ -506,7 +517,13 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
self.remove_unused_series)
|
self.remove_unused_series)
|
||||||
QObject.connect(self.auto_author_sort, SIGNAL('clicked()'),
|
QObject.connect(self.auto_author_sort, SIGNAL('clicked()'),
|
||||||
self.deduce_author_sort)
|
self.deduce_author_sort)
|
||||||
|
QObject.connect(self.auto_title_sort, SIGNAL('clicked()'),
|
||||||
|
self.deduce_title_sort)
|
||||||
self.trim_cover_button.clicked.connect(self.trim_cover)
|
self.trim_cover_button.clicked.connect(self.trim_cover)
|
||||||
|
self.connect(self.title_sort, SIGNAL('textChanged(const QString&)'),
|
||||||
|
self.title_sort_box_changed)
|
||||||
|
self.connect(self.title, SIGNAL('textChanged(const QString&)'),
|
||||||
|
self.title_box_changed)
|
||||||
self.connect(self.author_sort, SIGNAL('textChanged(const QString&)'),
|
self.connect(self.author_sort, SIGNAL('textChanged(const QString&)'),
|
||||||
self.author_sort_box_changed)
|
self.author_sort_box_changed)
|
||||||
self.connect(self.authors, SIGNAL('editTextChanged(const QString&)'),
|
self.connect(self.authors, SIGNAL('editTextChanged(const QString&)'),
|
||||||
@ -523,6 +540,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
|
|
||||||
|
|
||||||
self.title.setText(db.title(row))
|
self.title.setText(db.title(row))
|
||||||
|
self.title_sort.setText(db.title_sort(row))
|
||||||
isbn = db.isbn(self.id, index_is_id=True)
|
isbn = db.isbn(self.id, index_is_id=True)
|
||||||
if not isbn:
|
if not isbn:
|
||||||
isbn = ''
|
isbn = ''
|
||||||
@ -598,8 +616,8 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
w = self.central_widget.widget(1)
|
w = self.central_widget.widget(1)
|
||||||
layout = w.layout()
|
layout = w.layout()
|
||||||
self.custom_column_widgets, self.__cc_spacers = \
|
self.custom_column_widgets, self.__cc_spacers = \
|
||||||
populate_metadata_page(layout, self.db, self.id,
|
populate_metadata_page(layout, self.db, self.id, parent=w, bulk=False,
|
||||||
parent=w, bulk=False, two_column=True)
|
two_column=tweaks['metadata_single_use_2_cols_for_custom_fields'])
|
||||||
self.__custom_col_layouts = [layout]
|
self.__custom_col_layouts = [layout]
|
||||||
ans = self.custom_column_widgets
|
ans = self.custom_column_widgets
|
||||||
for i in range(len(ans)-1):
|
for i in range(len(ans)-1):
|
||||||
@ -610,27 +628,40 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
for c in range(2, len(ans[i].widgets), 2):
|
for c in range(2, len(ans[i].widgets), 2):
|
||||||
w.setTabOrder(ans[i].widgets[c-1], ans[i].widgets[c+1])
|
w.setTabOrder(ans[i].widgets[c-1], ans[i].widgets[c+1])
|
||||||
|
|
||||||
|
def title_box_changed(self, txt):
|
||||||
|
ts = unicode(txt)
|
||||||
|
ts = title_sort(ts)
|
||||||
|
self.mark_box_as_ok(control = self.title_sort, tt=self.ts_tooltips,
|
||||||
|
normal=(unicode(self.title_sort.text()) == ts))
|
||||||
|
|
||||||
|
def title_sort_box_changed(self, txt):
|
||||||
|
ts = unicode(txt)
|
||||||
|
self.mark_box_as_ok(control = self.title_sort, tt=self.ts_tooltips,
|
||||||
|
normal=(title_sort(unicode(self.title.text())) == ts))
|
||||||
|
|
||||||
def authors_box_changed(self, txt):
|
def authors_box_changed(self, txt):
|
||||||
aus = unicode(txt)
|
aus = unicode(txt)
|
||||||
aus = re.sub(r'\s+et al\.$', '', aus)
|
aus = re.sub(r'\s+et al\.$', '', aus)
|
||||||
aus = self.db.author_sort_from_authors(string_to_authors(aus))
|
aus = self.db.author_sort_from_authors(string_to_authors(aus))
|
||||||
self.mark_author_sort(normal=(unicode(self.author_sort.text()) == aus))
|
self.mark_box_as_ok(control = self.author_sort, tt=self.aus_tooltips,
|
||||||
|
normal=(unicode(self.author_sort.text()) == aus))
|
||||||
|
|
||||||
def author_sort_box_changed(self, txt):
|
def author_sort_box_changed(self, txt):
|
||||||
au = unicode(self.authors.text())
|
au = unicode(self.authors.text())
|
||||||
au = re.sub(r'\s+et al\.$', '', au)
|
au = re.sub(r'\s+et al\.$', '', au)
|
||||||
au = self.db.author_sort_from_authors(string_to_authors(au))
|
au = self.db.author_sort_from_authors(string_to_authors(au))
|
||||||
self.mark_author_sort(normal=(au == txt))
|
self.mark_box_as_ok(control = self.author_sort, tt=self.aus_tooltips,
|
||||||
|
normal=(au == txt))
|
||||||
|
|
||||||
def mark_author_sort(self, normal=True):
|
def mark_box_as_ok(self, control, tt, normal=True):
|
||||||
if normal:
|
if normal:
|
||||||
col = 'rgb(0, 255, 0, 20%)'
|
col = 'rgb(0, 255, 0, 20%)'
|
||||||
else:
|
else:
|
||||||
col = 'rgb(255, 0, 0, 20%)'
|
col = 'rgb(255, 0, 0, 20%)'
|
||||||
self.author_sort.setStyleSheet('QLineEdit { color: black; '
|
control.setStyleSheet('QLineEdit { color: black; '
|
||||||
'background-color: %s; }'%col)
|
'background-color: %s; }'%col)
|
||||||
tt = self.ok_aus_tooltip if normal else self.bad_aus_tooltip
|
tt = tt[0] if normal else tt[1]
|
||||||
self.author_sort.setToolTip(tt)
|
control.setToolTip(tt)
|
||||||
|
|
||||||
def validate_isbn(self, isbn):
|
def validate_isbn(self, isbn):
|
||||||
isbn = unicode(isbn).strip()
|
isbn = unicode(isbn).strip()
|
||||||
@ -652,12 +683,16 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
authors = string_to_authors(au)
|
authors = string_to_authors(au)
|
||||||
self.author_sort.setText(self.db.author_sort_from_authors(authors))
|
self.author_sort.setText(self.db.author_sort_from_authors(authors))
|
||||||
|
|
||||||
|
def deduce_title_sort(self):
|
||||||
|
ts = unicode(self.title.text())
|
||||||
|
self.title_sort.setText(title_sort(ts))
|
||||||
|
|
||||||
def swap_title_author(self):
|
def swap_title_author(self):
|
||||||
title = self.title.text()
|
title = self.title.text()
|
||||||
self.title.setText(self.authors.text())
|
self.title.setText(self.authors.text())
|
||||||
self.authors.setText(title)
|
self.authors.setText(title)
|
||||||
self.author_sort.setText('')
|
self.deduce_author_sort()
|
||||||
|
self.deduce_title_sort()
|
||||||
|
|
||||||
def initialize_combos(self):
|
def initialize_combos(self):
|
||||||
self.initalize_authors()
|
self.initalize_authors()
|
||||||
@ -804,7 +839,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
series = unicode(self.series.text()).strip()
|
series = unicode(self.series.text()).strip()
|
||||||
if series and series != self.original_series_name:
|
if series and series != self.original_series_name:
|
||||||
ns = 1
|
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)
|
ns = self.db.get_next_series_num_for(series)
|
||||||
self.series_index.setValue(ns)
|
self.series_index.setValue(ns)
|
||||||
self.original_series_name = series
|
self.original_series_name = series
|
||||||
@ -838,6 +873,10 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
title = unicode(self.title.text()).strip()
|
title = unicode(self.title.text()).strip()
|
||||||
if title != self.original_title:
|
if title != self.original_title:
|
||||||
self.db.set_title(self.id, title, notify=False)
|
self.db.set_title(self.id, title, notify=False)
|
||||||
|
# This must be after setting the title because of the DB update trigger
|
||||||
|
ts = unicode(self.title_sort.text()).strip()
|
||||||
|
if ts:
|
||||||
|
self.db.set_title_sort(self.id, ts, notify=False, commit=False)
|
||||||
au = unicode(self.authors.text()).strip()
|
au = unicode(self.authors.text()).strip()
|
||||||
if au and au != self.original_author:
|
if au and au != self.original_author:
|
||||||
self.db.set_authors(self.id, string_to_authors(au), notify=False)
|
self.db.set_authors(self.id, string_to_authors(au), notify=False)
|
||||||
|
@ -100,27 +100,27 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2" rowspan="2">
|
<item row="1" column="0">
|
||||||
<widget class="QToolButton" name="swap_button">
|
<widget class="QLabel" name="label">
|
||||||
<property name="toolTip">
|
|
||||||
<string>Swap the author and title</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>Title &sort: </string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="alignment">
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
<normaloff>:/images/swap.png</normaloff>:/images/swap.png</iconset>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="buddy">
|
||||||
<size>
|
<cstring>title_sort</cstring>
|
||||||
<width>16</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="1">
|
||||||
|
<widget class="EnLineEdit" name="title_sort">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Specify how this book should be sorted when by title. For example, The Exorcist might be sorted as Exorcist, The.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Author(s): </string>
|
<string>&Author(s): </string>
|
||||||
@ -133,7 +133,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="1">
|
||||||
|
<widget class="EnComboBox" name="authors">
|
||||||
|
<property name="editable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_8">
|
<widget class="QLabel" name="label_8">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Author S&ort: </string>
|
<string>Author S&ort: </string>
|
||||||
@ -146,34 +153,15 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1" colspan="2">
|
<item row="3" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<widget class="EnLineEdit" name="author_sort">
|
||||||
<item>
|
<property name="toolTip">
|
||||||
<widget class="EnLineEdit" name="author_sort">
|
<string>Specify how the author(s) of this book should be sorted. For example Charles Dickens should be sorted as Dickens, Charles.
|
||||||
<property name="toolTip">
|
|
||||||
<string>Specify how the author(s) of this book should be sorted. For example Charles Dickens should be sorted as Dickens, Charles.
|
|
||||||
If the box is colored green, then text matches the individual author's sort strings. If it is colored red, then the authors and this text do not match.</string>
|
If the box is colored green, then text matches the individual author's sort strings. If it is colored red, then the authors and this text do not match.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="auto_author_sort">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Automatically create the author sort entry based on the current author entry.
|
|
||||||
Using this button to create author sort will change author sort from red to green.</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
|
||||||
<normaloff>:/images/auto_author_sort.png</normaloff>:/images/auto_author_sort.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Rating:</string>
|
<string>&Rating:</string>
|
||||||
@ -186,7 +174,7 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1" colspan="2">
|
<item row="4" column="1" colspan="2">
|
||||||
<widget class="QSpinBox" name="rating">
|
<widget class="QSpinBox" name="rating">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Rating of this book. 0-5 stars</string>
|
<string>Rating of this book. 0-5 stars</string>
|
||||||
@ -205,7 +193,7 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Publisher: </string>
|
<string>&Publisher: </string>
|
||||||
@ -218,7 +206,14 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="5" column="1" colspan="2">
|
||||||
|
<widget class="EnComboBox" name="publisher">
|
||||||
|
<property name="editable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Ta&gs: </string>
|
<string>Ta&gs: </string>
|
||||||
@ -231,32 +226,7 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1" colspan="2">
|
<item row="7" column="0">
|
||||||
<layout class="QHBoxLayout" name="_2">
|
|
||||||
<item>
|
|
||||||
<widget class="TagsLineEdit" name="tags">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="tag_editor_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Open Tag Editor</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Open Tag Editor</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
|
||||||
<normaloff>:/images/chapters.png</normaloff>:/images/chapters.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Series:</string>
|
<string>&Series:</string>
|
||||||
@ -272,7 +242,7 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1" colspan="2">
|
<item row="7" column="1">
|
||||||
<layout class="QHBoxLayout" name="_3">
|
<layout class="QHBoxLayout" name="_3">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
@ -293,59 +263,9 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="remove_series_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Remove unused series (Series that have no books)</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
|
||||||
<normaloff>:/images/trash.png</normaloff>:/images/trash.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>IS&BN:</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>isbn</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1" colspan="2">
|
<item row="8" column="1" colspan="2">
|
||||||
<widget class="QLineEdit" name="isbn"/>
|
|
||||||
</item>
|
|
||||||
<item row="10" column="0">
|
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="text">
|
|
||||||
<string>Publishe&d:</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>pubdate</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1" colspan="2">
|
|
||||||
<widget class="EnComboBox" name="publisher">
|
|
||||||
<property name="editable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1" colspan="2">
|
|
||||||
<widget class="QDoubleSpinBox" name="series_index">
|
<widget class="QDoubleSpinBox" name="series_index">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -358,34 +278,23 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="1" colspan="2">
|
<item row="9" column="0">
|
||||||
<widget class="QDateEdit" name="pubdate">
|
<widget class="QLabel" name="label_9">
|
||||||
<property name="displayFormat">
|
<property name="text">
|
||||||
<string>MMM yyyy</string>
|
<string>IS&BN:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="calendarPopup">
|
<property name="alignment">
|
||||||
<bool>true</bool>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="buddy">
|
||||||
</item>
|
<cstring>isbn</cstring>
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="EnComboBox" name="authors">
|
|
||||||
<property name="editable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="1" colspan="2">
|
<item row="9" column="1" colspan="2">
|
||||||
<widget class="QDateEdit" name="date">
|
<widget class="QLineEdit" name="isbn"/>
|
||||||
<property name="displayFormat">
|
|
||||||
<string>dd MMM yyyy</string>
|
|
||||||
</property>
|
|
||||||
<property name="calendarPopup">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0">
|
<item row="10" column="0">
|
||||||
<widget class="QLabel" name="label_11">
|
<widget class="QLabel" name="label_11">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Date:</string>
|
<string>&Date:</string>
|
||||||
@ -398,9 +307,194 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="10" column="1" colspan="2">
|
||||||
|
<widget class="QDateEdit" name="date">
|
||||||
|
<property name="displayFormat">
|
||||||
|
<string>dd MMM yyyy</string>
|
||||||
|
</property>
|
||||||
|
<property name="calendarPopup">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>Publishe&d:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>pubdate</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="1" colspan="2">
|
||||||
|
<widget class="QDateEdit" name="pubdate">
|
||||||
|
<property name="displayFormat">
|
||||||
|
<string>MMM yyyy</string>
|
||||||
|
</property>
|
||||||
|
<property name="calendarPopup">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2" rowspan="4">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="auto_title_sort">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Automatically create the author sort entry based on the current author entry.
|
||||||
|
Using this button to create author sort will change author sort from red to green.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/auto_author_sort.png</normaloff>:/images/auto_author_sort.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="swap_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Swap the author and title</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/swap.png</normaloff>:/images/swap.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>16</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="auto_author_sort">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Automatically create the title sort entry based on the current title entry.
|
||||||
|
Using this button to create title sort will change title sort from red to green.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/auto_author_sort.png</normaloff>:/images/auto_author_sort.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="_2">
|
||||||
|
<item>
|
||||||
|
<widget class="TagsLineEdit" name="tags">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Tags categorize the book. This is particularly useful while searching. <br><br>They can be any words or phrases, separated by commas.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="2">
|
||||||
|
<widget class="QToolButton" name="tag_editor_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Open Tag Editor</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Open Tag Editor</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/chapters.png</normaloff>:/images/chapters.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="2">
|
||||||
|
<widget class="QToolButton" name="remove_series_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove unused series (Series that have no books)</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/trash.png</normaloff>:/images/trash.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="fetch_metadata_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Fetch metadata from server</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -420,13 +514,6 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="fetch_metadata_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Fetch metadata from server</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="layoutWidget_2">
|
<widget class="QWidget" name="layoutWidget_2">
|
||||||
@ -744,10 +831,12 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>title</tabstop>
|
<tabstop>title</tabstop>
|
||||||
|
<tabstop>auto_title_sort</tabstop>
|
||||||
|
<tabstop>title_sort</tabstop>
|
||||||
<tabstop>swap_button</tabstop>
|
<tabstop>swap_button</tabstop>
|
||||||
<tabstop>authors</tabstop>
|
<tabstop>authors</tabstop>
|
||||||
<tabstop>author_sort</tabstop>
|
|
||||||
<tabstop>auto_author_sort</tabstop>
|
<tabstop>auto_author_sort</tabstop>
|
||||||
|
<tabstop>author_sort</tabstop>
|
||||||
<tabstop>rating</tabstop>
|
<tabstop>rating</tabstop>
|
||||||
<tabstop>publisher</tabstop>
|
<tabstop>publisher</tabstop>
|
||||||
<tabstop>tags</tabstop>
|
<tabstop>tags</tabstop>
|
||||||
@ -758,20 +847,22 @@ Using this button to create author sort will change author sort from red to gree
|
|||||||
<tabstop>isbn</tabstop>
|
<tabstop>isbn</tabstop>
|
||||||
<tabstop>date</tabstop>
|
<tabstop>date</tabstop>
|
||||||
<tabstop>pubdate</tabstop>
|
<tabstop>pubdate</tabstop>
|
||||||
<tabstop>comments</tabstop>
|
|
||||||
<tabstop>fetch_metadata_button</tabstop>
|
<tabstop>fetch_metadata_button</tabstop>
|
||||||
<tabstop>add_format_button</tabstop>
|
<tabstop>comments</tabstop>
|
||||||
<tabstop>remove_format_button</tabstop>
|
|
||||||
<tabstop>button_set_cover</tabstop>
|
<tabstop>button_set_cover</tabstop>
|
||||||
<tabstop>button_set_metadata</tabstop>
|
<tabstop>button_set_metadata</tabstop>
|
||||||
<tabstop>formats</tabstop>
|
<tabstop>formats</tabstop>
|
||||||
|
<tabstop>add_format_button</tabstop>
|
||||||
|
<tabstop>remove_format_button</tabstop>
|
||||||
<tabstop>cover_path</tabstop>
|
<tabstop>cover_path</tabstop>
|
||||||
|
<tabstop>cover_button</tabstop>
|
||||||
|
<tabstop>trim_cover_button</tabstop>
|
||||||
<tabstop>reset_cover</tabstop>
|
<tabstop>reset_cover</tabstop>
|
||||||
<tabstop>fetch_cover_button</tabstop>
|
<tabstop>fetch_cover_button</tabstop>
|
||||||
<tabstop>generate_cover_button</tabstop>
|
<tabstop>generate_cover_button</tabstop>
|
||||||
|
<tabstop>button_box</tabstop>
|
||||||
<tabstop>scrollArea</tabstop>
|
<tabstop>scrollArea</tabstop>
|
||||||
<tabstop>central_widget</tabstop>
|
<tabstop>central_widget</tabstop>
|
||||||
<tabstop>button_box</tabstop>
|
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../../../resources/images.qrc"/>
|
<include location="../../../../resources/images.qrc"/>
|
||||||
|
@ -772,7 +772,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
self.db.set_series_index(id, float(match.group(1)))
|
self.db.set_series_index(id, float(match.group(1)))
|
||||||
val = pat.sub('', val).strip()
|
val = pat.sub('', val).strip()
|
||||||
elif val:
|
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)
|
ni = self.db.get_next_series_num_for(val)
|
||||||
if ni != 1:
|
if ni != 1:
|
||||||
self.db.set_series_index(id, ni)
|
self.db.set_series_index(id, ni)
|
||||||
|
@ -378,13 +378,16 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
def booklists(self):
|
def booklists(self):
|
||||||
return self.memory_view.model().db, self.card_a_view.model().db, self.card_b_view.model().db
|
return self.memory_view.model().db, self.card_a_view.model().db, self.card_b_view.model().db
|
||||||
|
|
||||||
def library_moved(self, newloc):
|
def library_moved(self, newloc, copy_structure=False):
|
||||||
if newloc is None: return
|
if newloc is None: return
|
||||||
|
default_prefs = None
|
||||||
try:
|
try:
|
||||||
olddb = self.library_view.model().db
|
olddb = self.library_view.model().db
|
||||||
|
if copy_structure:
|
||||||
|
default_prefs = olddb.prefs
|
||||||
except:
|
except:
|
||||||
olddb = None
|
olddb = None
|
||||||
db = LibraryDatabase2(newloc)
|
db = LibraryDatabase2(newloc, default_prefs=default_prefs)
|
||||||
if self.content_server is not None:
|
if self.content_server is not None:
|
||||||
self.content_server.set_database(db)
|
self.content_server.set_database(db)
|
||||||
self.library_path = newloc
|
self.library_path = newloc
|
||||||
|
@ -707,7 +707,7 @@ def parse_series_string(db, label, value):
|
|||||||
val = pat.sub('', val).strip()
|
val = pat.sub('', val).strip()
|
||||||
s_index = float(match.group(1))
|
s_index = float(match.group(1))
|
||||||
elif val:
|
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)
|
s_index = db.get_next_cc_series_num_for(val, label=label)
|
||||||
else:
|
else:
|
||||||
s_index = 1.0
|
s_index = 1.0
|
||||||
|
@ -8,12 +8,12 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import json, re
|
import json, re
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from math import floor
|
|
||||||
|
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
from calibre.constants import preferred_encoding
|
from calibre.constants import preferred_encoding
|
||||||
from calibre.library.field_metadata import FieldMetadata
|
from calibre.library.field_metadata import FieldMetadata
|
||||||
from calibre.utils.date import parse_date
|
from calibre.utils.date import parse_date
|
||||||
|
from calibre.utils.config import tweaks
|
||||||
|
|
||||||
class CustomColumns(object):
|
class CustomColumns(object):
|
||||||
|
|
||||||
@ -261,15 +261,15 @@ class CustomColumns(object):
|
|||||||
series_id = self.conn.get('SELECT id from %s WHERE value=?'%table,
|
series_id = self.conn.get('SELECT id from %s WHERE value=?'%table,
|
||||||
(series,), all=False)
|
(series,), all=False)
|
||||||
if series_id is None:
|
if series_id is None:
|
||||||
|
if isinstance(tweaks['series_index_auto_increment'], (int, float)):
|
||||||
|
return float(tweaks['series_index_auto_increment'])
|
||||||
return 1.0
|
return 1.0
|
||||||
# get the label of the associated series number table
|
series_indices = self.conn.get('''
|
||||||
series_num = self.conn.get('''
|
SELECT {lt}.extra FROM {lt}
|
||||||
SELECT MAX({lt}.extra) FROM {lt}
|
|
||||||
WHERE {lt}.book IN (SELECT book FROM {lt} where value=?)
|
WHERE {lt}.book IN (SELECT book FROM {lt} where value=?)
|
||||||
'''.format(lt=lt), (series_id,), all=False)
|
ORDER BY {lt}.extra
|
||||||
if series_num is None:
|
'''.format(lt=lt), (series_id,))
|
||||||
return 1.0
|
return self._get_next_series_num_for_list(series_indices)
|
||||||
return floor(series_num+1)
|
|
||||||
|
|
||||||
def all_custom(self, label=None, num=None):
|
def all_custom(self, label=None, num=None):
|
||||||
if label is not None:
|
if label is not None:
|
||||||
|
@ -8,7 +8,7 @@ The database used to store ebook metadata
|
|||||||
'''
|
'''
|
||||||
import os, sys, shutil, cStringIO, glob, time, functools, traceback, re
|
import os, sys, shutil, cStringIO, glob, time, functools, traceback, re
|
||||||
from itertools import repeat
|
from itertools import repeat
|
||||||
from math import floor
|
from math import ceil
|
||||||
from Queue import Queue
|
from Queue import Queue
|
||||||
|
|
||||||
from PyQt4.QtGui import QImage
|
from PyQt4.QtGui import QImage
|
||||||
@ -113,7 +113,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
def exists_at(cls, path):
|
def exists_at(cls, path):
|
||||||
return path and os.path.exists(os.path.join(path, 'metadata.db'))
|
return path and os.path.exists(os.path.join(path, 'metadata.db'))
|
||||||
|
|
||||||
def __init__(self, library_path, row_factory=False):
|
def __init__(self, library_path, row_factory=False, default_prefs=None):
|
||||||
self.field_metadata = FieldMetadata()
|
self.field_metadata = FieldMetadata()
|
||||||
self.dirtied_queue = Queue()
|
self.dirtied_queue = Queue()
|
||||||
if not os.path.exists(library_path):
|
if not os.path.exists(library_path):
|
||||||
@ -127,10 +127,29 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
if isinstance(self.dbpath, unicode) and not iswindows:
|
if isinstance(self.dbpath, unicode) and not iswindows:
|
||||||
self.dbpath = self.dbpath.encode(filesystem_encoding)
|
self.dbpath = self.dbpath.encode(filesystem_encoding)
|
||||||
|
|
||||||
|
apply_default_prefs = not os.path.exists(self.dbpath)
|
||||||
self.connect()
|
self.connect()
|
||||||
|
|
||||||
self.is_case_sensitive = not iswindows and not isosx and \
|
self.is_case_sensitive = not iswindows and not isosx and \
|
||||||
not os.path.exists(self.dbpath.replace('metadata.db', 'MeTAdAtA.dB'))
|
not os.path.exists(self.dbpath.replace('metadata.db', 'MeTAdAtA.dB'))
|
||||||
SchemaUpgrade.__init__(self)
|
SchemaUpgrade.__init__(self)
|
||||||
|
|
||||||
|
# if we are to copy the prefs and structure from some other DB, then
|
||||||
|
# we need to do it before we call initialize_dynamic
|
||||||
|
if apply_default_prefs and default_prefs is not None:
|
||||||
|
dbprefs = DBPrefs(self)
|
||||||
|
for key in default_prefs:
|
||||||
|
# be sure that prefs not to be copied are listed below
|
||||||
|
if key in ['news_to_be_synced']:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
dbprefs[key] = default_prefs[key]
|
||||||
|
except:
|
||||||
|
pass # ignore options that don't exist anymore
|
||||||
|
fmvals = [f for f in default_prefs['field_metadata'].values() if f['is_custom']]
|
||||||
|
for f in fmvals:
|
||||||
|
self.create_custom_column(f['label'], f['name'], f['datatype'],
|
||||||
|
f['is_multiple'] is not None, f['is_editable'], f['display'])
|
||||||
self.initialize_dynamic()
|
self.initialize_dynamic()
|
||||||
|
|
||||||
def get_property(self, idx, index_is_id=False, loc=-1):
|
def get_property(self, idx, index_is_id=False, loc=-1):
|
||||||
@ -1365,14 +1384,42 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
series_id = self.conn.get('SELECT id from series WHERE name=?',
|
series_id = self.conn.get('SELECT id from series WHERE name=?',
|
||||||
(series,), all=False)
|
(series,), all=False)
|
||||||
if series_id is None:
|
if series_id is None:
|
||||||
|
if isinstance(tweaks['series_index_auto_increment'], (int, float)):
|
||||||
|
return float(tweaks['series_index_auto_increment'])
|
||||||
return 1.0
|
return 1.0
|
||||||
series_num = self.conn.get(
|
series_indices = self.conn.get(
|
||||||
('SELECT MAX(series_index) FROM books WHERE id IN '
|
('SELECT series_index FROM books WHERE id IN '
|
||||||
'(SELECT book FROM books_series_link where series=?)'),
|
'(SELECT book FROM books_series_link where series=?) '
|
||||||
(series_id,), all=False)
|
'ORDER BY series_index'),
|
||||||
if series_num is None:
|
(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 1.0
|
||||||
return floor(series_num+1)
|
series_indices = [x[0] for x in 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):
|
def set(self, row, column, val):
|
||||||
'''
|
'''
|
||||||
@ -1565,6 +1612,20 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
if notify:
|
if notify:
|
||||||
self.notify('metadata', [id])
|
self.notify('metadata', [id])
|
||||||
|
|
||||||
|
def set_title_sort(self, id, title_sort_, notify=True, commit=True):
|
||||||
|
if not title_sort_:
|
||||||
|
return False
|
||||||
|
if isbytestring(title_sort_):
|
||||||
|
title_sort_ = title_sort_.decode(preferred_encoding, 'replace')
|
||||||
|
self.conn.execute('UPDATE books SET sort=? WHERE id=?', (title_sort_, id))
|
||||||
|
self.data.set(id, self.FIELD_MAP['sort'], title_sort_, row_is_id=True)
|
||||||
|
self.dirtied([id], commit=False)
|
||||||
|
if commit:
|
||||||
|
self.conn.commit()
|
||||||
|
if notify:
|
||||||
|
self.notify('metadata', [id])
|
||||||
|
return True
|
||||||
|
|
||||||
def _set_title(self, id, title):
|
def _set_title(self, id, title):
|
||||||
if not title:
|
if not title:
|
||||||
return False
|
return False
|
||||||
@ -1746,18 +1807,17 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
FROM books, books_series_link as lt
|
FROM books, books_series_link as lt
|
||||||
WHERE books.id = lt.book AND lt.series=?
|
WHERE books.id = lt.book AND lt.series=?
|
||||||
ORDER BY books.series_index''', (old_id,))
|
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
|
# Now update the link table
|
||||||
self.conn.execute('''UPDATE books_series_link
|
self.conn.execute('''UPDATE books_series_link
|
||||||
SET series=?
|
SET series=?
|
||||||
WHERE series=?''',(new_id, old_id,))
|
WHERE series=?''',(new_id, old_id,))
|
||||||
# Now set the indices
|
# Now set the indices
|
||||||
for (book_id,) in books:
|
for (book_id,) in books:
|
||||||
|
# Get the next series index
|
||||||
|
index = self.get_next_series_num_for(new_name)
|
||||||
self.conn.execute('''UPDATE books
|
self.conn.execute('''UPDATE books
|
||||||
SET series_index=?
|
SET series_index=?
|
||||||
WHERE id=?''',(index, book_id,))
|
WHERE id=?''',(index, book_id,))
|
||||||
index = index + 1
|
|
||||||
self.dirty_books_referencing('series', new_id, commit=False)
|
self.dirty_books_referencing('series', new_id, commit=False)
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
|
||||||
|
@ -429,3 +429,13 @@ class SchemaUpgrade(object):
|
|||||||
'Remove commas from tags'
|
'Remove commas from tags'
|
||||||
self.conn.execute("UPDATE tags SET name=REPLACE(name, ',', ';')")
|
self.conn.execute("UPDATE tags SET name=REPLACE(name, ',', ';')")
|
||||||
|
|
||||||
|
def upgrade_version_16(self):
|
||||||
|
self.conn.executescript('''
|
||||||
|
DROP TRIGGER IF EXISTS books_update_trg;
|
||||||
|
CREATE TRIGGER books_update_trg
|
||||||
|
AFTER UPDATE ON books
|
||||||
|
BEGIN
|
||||||
|
UPDATE books SET sort=title_sort(NEW.title)
|
||||||
|
WHERE id=NEW.id AND OLD.title <> NEW.title;
|
||||||
|
END;
|
||||||
|
''')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user