mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Merge branch 'master' of https://github.com/kovidgoyal/calibre
This commit is contained in:
commit
05fb53ff42
@ -20,6 +20,53 @@
|
||||
# new recipes:
|
||||
# - title:
|
||||
|
||||
- version: 1.31.0
|
||||
date: 2014-04-04
|
||||
|
||||
new features:
|
||||
- title: "DOCX Input: Support for converting indexes created using the Word Index tool. The entries in the index are automatically converted into links pointing to the indexed locations."
|
||||
|
||||
- title: "AZW3 Output: Add support for converting documents with very large table of contents (with more than 2000 entries)."
|
||||
tickets: [1250475]
|
||||
|
||||
- title: "Edit Book: Add a button to easily insert HTML tags. Useful if you want to quickly surround selected text with an arbitrary tag. You can right click the button to get a list of recently used tags."
|
||||
|
||||
- title: "Driver for Tolino Vision (OS X/Linux only)."
|
||||
tickets: [1301875]
|
||||
|
||||
- title: "Edit book: Allow editing SVG files as raw XML"
|
||||
|
||||
bug fixes:
|
||||
- title: "DOCX Input: Fix incorrect numbering being generated for numbered lists in some circumstances."
|
||||
tickets: [1301044]
|
||||
|
||||
- title: "calibredb check_library: Do not create empty library if user specifies incorrect path"
|
||||
|
||||
- title: "DOCX Input: Fix handling of hyperlinks in documents where the hyperlink is specified as a field internally (Microsoft Word does not use fields for hyperlinks)"
|
||||
|
||||
- title: "Get Books: Update WH Smiths plugin for website changes and remove Diesel eBooks, as they are shutting down"
|
||||
|
||||
- title: "AZW3 Output: Fix a bug that caused popup footnotes in some AZW3 files to not work properly. The popup would show all remaining footnotes instead of only the current footnote."
|
||||
tickets: [1293290]
|
||||
|
||||
- title: "AZW3 Output: Various tweaks to the internal structure and headers of the output file to make it closer to what kindlegen 2.9 generates"
|
||||
|
||||
- title: "Edit Book: When user is editing files belonging to another user account on linux/os x rather than erroring out when saving, change the ownership of the file to the editing user."
|
||||
tickets: [1299097]
|
||||
|
||||
- title: "Edit Book: Fix insert Inline ToC creating non-linear jumps in class names"
|
||||
|
||||
- title: "Fix regression that broke ebook-device cp"
|
||||
|
||||
improved recipes:
|
||||
- CNET
|
||||
- El Pais Impreso
|
||||
- CNet News
|
||||
- Antyweb
|
||||
|
||||
new recipes:
|
||||
- title:
|
||||
|
||||
- version: 1.30.0
|
||||
date: 2014-03-28
|
||||
|
||||
|
@ -4,7 +4,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
__appname__ = u'calibre'
|
||||
numeric_version = (1, 30, 0)
|
||||
numeric_version = (1, 31, 0)
|
||||
__version__ = u'.'.join(map(unicode, numeric_version))
|
||||
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"
|
||||
|
||||
|
@ -229,9 +229,6 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
for n1, k1 in cols:
|
||||
self.colored_field.addItem(n1, k1)
|
||||
self.colored_field.setCurrentIndex(self.colored_field.findData(color_field))
|
||||
colors = QColor.colorNames()
|
||||
colors.sort()
|
||||
self.color_name.addItems(colors)
|
||||
elif self.iconing:
|
||||
self.icon_layout.setVisible(True)
|
||||
for n1, k1 in cols:
|
||||
@ -362,7 +359,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
def color_to_clipboard(self):
|
||||
app = QApplication.instance()
|
||||
c = app.clipboard()
|
||||
c.setText(unicode(self.color_name.currentText()))
|
||||
c.setText(unicode(self.color_name.color))
|
||||
|
||||
def icon_to_clipboard(self):
|
||||
app = QApplication.instance()
|
||||
|
@ -48,7 +48,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="color_name">
|
||||
<widget class="ColorButton" name="color_name">
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
@ -246,6 +246,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>calibre/gui2/widgets2.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en'
|
||||
import os, textwrap
|
||||
|
||||
from PyQt4.Qt import (QWidget, QDialog, QLabel, QGridLayout, QComboBox, QSize,
|
||||
QLineEdit, QIntValidator, QDoubleValidator, QFrame, QColor, Qt, QIcon,
|
||||
QLineEdit, QIntValidator, QDoubleValidator, QFrame, Qt, QIcon,
|
||||
QScrollArea, QPushButton, QVBoxLayout, QDialogButtonBox, QToolButton,
|
||||
QListView, QAbstractListModel, pyqtSignal, QSizePolicy, QSpacerItem,
|
||||
QApplication, QStandardItem, QStandardItemModel, QCheckBox)
|
||||
@ -21,6 +21,7 @@ from calibre.utils.icu import sort_key
|
||||
from calibre.gui2 import error_dialog, choose_files, pixmap_to_data
|
||||
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
||||
from calibre.gui2.metadata.single_download import RichTextDelegate
|
||||
from calibre.gui2.widgets2 import ColorButton
|
||||
from calibre.library.coloring import (Rule, conditionable_columns,
|
||||
displayable_columns, rule_from_template, color_row_key)
|
||||
from calibre.utils.localization import lang_map
|
||||
@ -33,7 +34,8 @@ icon_rule_kinds = [(_('icon with text'), 'icon'),
|
||||
(_('composed icons w/text'), 'icon_composed'),
|
||||
(_('composed icons w/no text'), 'icon_only_composed'),]
|
||||
|
||||
class ConditionEditor(QWidget): # {{{
|
||||
|
||||
class ConditionEditor(QWidget): # {{{
|
||||
|
||||
ACTION_MAP = {
|
||||
'bool' : (
|
||||
@ -86,7 +88,6 @@ class ConditionEditor(QWidget): # {{{
|
||||
for x in ('float', 'rating'):
|
||||
ACTION_MAP[x] = ACTION_MAP['int']
|
||||
|
||||
|
||||
def __init__(self, fm, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
self.fm = fm
|
||||
@ -108,8 +109,6 @@ class ConditionEditor(QWidget): # {{{
|
||||
self.column_box = QComboBox(self)
|
||||
l.addWidget(self.column_box, 0, 1)
|
||||
|
||||
|
||||
|
||||
self.l2 = l2 = QLabel(two)
|
||||
l.addWidget(l2, 0, 2)
|
||||
|
||||
@ -277,7 +276,7 @@ class ConditionEditor(QWidget): # {{{
|
||||
self.value_box.setEnabled(False)
|
||||
# }}}
|
||||
|
||||
class RuleEditor(QDialog): # {{{
|
||||
class RuleEditor(QDialog): # {{{
|
||||
|
||||
def __init__(self, fm, pref_name, parent=None):
|
||||
QDialog.__init__(self, parent)
|
||||
@ -329,7 +328,7 @@ class RuleEditor(QDialog): # {{{
|
||||
l.addWidget(l4, 2, 4)
|
||||
|
||||
if self.rule_kind == 'color':
|
||||
self.color_box = QComboBox(self)
|
||||
self.color_box = ColorButton(parent=self)
|
||||
self.color_label = QLabel('Sample text Sample text')
|
||||
self.color_label.setTextFormat(Qt.RichText)
|
||||
l.addWidget(self.color_box, 2, 5)
|
||||
@ -393,7 +392,7 @@ class RuleEditor(QDialog): # {{{
|
||||
self.conditions = []
|
||||
|
||||
if self.rule_kind == 'color':
|
||||
for b in (self.column_box, self.color_box):
|
||||
for b in (self.column_box, ):
|
||||
b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon)
|
||||
b.setMinimumContentsLength(15)
|
||||
|
||||
@ -407,10 +406,9 @@ class RuleEditor(QDialog): # {{{
|
||||
self.column_box.setCurrentIndex(0)
|
||||
|
||||
if self.rule_kind == 'color':
|
||||
self.color_box.addItems(QColor.colorNames())
|
||||
self.color_box.setCurrentIndex(0)
|
||||
self.color_box.color = '#000'
|
||||
self.update_color_label()
|
||||
self.color_box.currentIndexChanged.connect(self.update_color_label)
|
||||
self.color_box.color_changed.connect(self.update_color_label)
|
||||
else:
|
||||
self.rule_icon_files = []
|
||||
self.filename_button.clicked.connect(self.filename_button_clicked)
|
||||
@ -436,10 +434,10 @@ class RuleEditor(QDialog): # {{{
|
||||
for i,filename in enumerate(self.icon_file_names):
|
||||
item = QStandardItem(filename)
|
||||
if doing_multiple:
|
||||
item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled);
|
||||
item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
|
||||
item.setData(Qt.Unchecked, Qt.CheckStateRole)
|
||||
else:
|
||||
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable);
|
||||
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
||||
icon = QIcon(os.path.join(config_dir, 'cc_icons', filename))
|
||||
item.setIcon(icon)
|
||||
model.appendRow(item)
|
||||
@ -448,7 +446,7 @@ class RuleEditor(QDialog): # {{{
|
||||
pal = QApplication.palette()
|
||||
bg1 = unicode(pal.color(pal.Base).name())
|
||||
bg2 = unicode(pal.color(pal.AlternateBase).name())
|
||||
c = unicode(self.color_box.currentText())
|
||||
c = self.color_box.color
|
||||
self.color_label.setText('''
|
||||
<span style="color: {c}; background-color: {bg1}"> {st} </span>
|
||||
<span style="color: {c}; background-color: {bg2}"> {st} </span>
|
||||
@ -528,9 +526,7 @@ class RuleEditor(QDialog): # {{{
|
||||
def apply_rule(self, kind, col, rule):
|
||||
if kind == 'color':
|
||||
if rule.color:
|
||||
idx = self.color_box.findText(rule.color)
|
||||
if idx >= 0:
|
||||
self.color_box.setCurrentIndex(idx)
|
||||
self.color_box.color = rule.color
|
||||
else:
|
||||
for i,tup in enumerate(icon_rule_kinds):
|
||||
if kind == tup[1]:
|
||||
@ -595,7 +591,7 @@ class RuleEditor(QDialog): # {{{
|
||||
if self.rule_kind != 'color':
|
||||
r.color = self.get_filenames_from_box()
|
||||
else:
|
||||
r.color = unicode(self.color_box.currentText())
|
||||
r.color = self.color_box.color
|
||||
idx = self.column_box.currentIndex()
|
||||
col = unicode(self.column_box.itemData(idx).toString())
|
||||
for c in self.conditions:
|
||||
@ -611,7 +607,7 @@ class RuleEditor(QDialog): # {{{
|
||||
return kind, col, r
|
||||
# }}}
|
||||
|
||||
class RulesModel(QAbstractListModel): # {{{
|
||||
class RulesModel(QAbstractListModel): # {{{
|
||||
|
||||
def __init__(self, prefs, fm, pref_name, parent=None):
|
||||
QAbstractListModel.__init__(self, parent)
|
||||
@ -623,7 +619,8 @@ class RulesModel(QAbstractListModel): # {{{
|
||||
rules = list(prefs[pref_name])
|
||||
self.rules = []
|
||||
for col, template in rules:
|
||||
if col not in self.fm and col != color_row_key: continue
|
||||
if col not in self.fm and col != color_row_key:
|
||||
continue
|
||||
try:
|
||||
rule = rule_from_template(self.fm, template)
|
||||
except:
|
||||
@ -634,7 +631,8 @@ class RulesModel(QAbstractListModel): # {{{
|
||||
rules = list(prefs[pref_name])
|
||||
self.rules = []
|
||||
for kind, col, template in rules:
|
||||
if col not in self.fm and col != color_row_key: continue
|
||||
if col not in self.fm and col != color_row_key:
|
||||
continue
|
||||
try:
|
||||
rule = rule_from_template(self.fm, template)
|
||||
except:
|
||||
@ -764,7 +762,7 @@ class RulesModel(QAbstractListModel): # {{{
|
||||
|
||||
# }}}
|
||||
|
||||
class EditRules(QWidget): # {{{
|
||||
class EditRules(QWidget): # {{{
|
||||
|
||||
changed = pyqtSignal()
|
||||
|
||||
@ -881,7 +879,7 @@ class EditRules(QWidget): # {{{
|
||||
icon_rule_kind=kind)
|
||||
|
||||
if d.exec_() == d.Accepted:
|
||||
if len(d.rule) == 2: # Convert template dialog rules to a triple
|
||||
if len(d.rule) == 2: # Convert template dialog rules to a triple
|
||||
d.rule = ('color', d.rule[0], d.rule[1])
|
||||
kind, col, r = d.rule
|
||||
if kind and r is not None and col:
|
||||
@ -945,7 +943,7 @@ if __name__ == '__main__':
|
||||
d.add_blank_condition()
|
||||
d.exec_()
|
||||
|
||||
col, r = d.rule
|
||||
kind, col, r = d.rule
|
||||
|
||||
print ('Column to be colored:', col)
|
||||
print ('Template:')
|
||||
|
@ -84,10 +84,15 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
||||
for t in self.column_types:
|
||||
self.column_type_box.addItem(self.column_types[t]['text'])
|
||||
self.column_type_box.currentIndexChanged.connect(self.datatype_changed)
|
||||
|
||||
all_colors = [unicode(s) for s in list(QColor.colorNames())]
|
||||
self.enum_colors_label.setToolTip('<p>' + ', '.join(all_colors) + '</p>')
|
||||
|
||||
if not self.editing_col:
|
||||
self.datatype_changed()
|
||||
self.exec_()
|
||||
return
|
||||
|
||||
self.setWindowTitle(_('Edit a custom column'))
|
||||
self.heading_label.setText(_('Edit a custom column'))
|
||||
self.shortcuts.setVisible(False)
|
||||
@ -141,9 +146,6 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
||||
elif ct == '*text':
|
||||
self.is_names.setChecked(c['display'].get('is_names', False))
|
||||
|
||||
all_colors = [unicode(s) for s in list(QColor.colorNames())]
|
||||
self.enum_colors_label.setToolTip('<p>' + ', '.join(all_colors) + '</p>')
|
||||
|
||||
self.composite_contains_html.setToolTip('<p>' +
|
||||
_('If checked, this column will be displayed as HTML in '
|
||||
'book details and the content server. This can be used to '
|
||||
@ -295,7 +297,7 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
|
||||
return self.simple_error('', _('The colors box must be empty or '
|
||||
'contain the same number of items as the value box'))
|
||||
for tc in c:
|
||||
if tc not in QColor.colorNames():
|
||||
if tc not in QColor.colorNames() and not re.match("#(?:[0-9a-f]{3}){1,4}",tc,re.I):
|
||||
return self.simple_error('',
|
||||
_('The color {0} is unknown').format(tc))
|
||||
|
||||
|
@ -6,6 +6,8 @@ from __future__ import (unicode_literals, division, absolute_import,
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
from PyQt4.Qt import QPushButton, QPixmap, QIcon, QColor, Qt, QColorDialog, pyqtSignal
|
||||
|
||||
from calibre.gui2.complete2 import LineEdit
|
||||
from calibre.gui2.widgets import history
|
||||
|
||||
@ -46,3 +48,41 @@ class HistoryLineEdit2(LineEdit):
|
||||
history.set(self.store_name, self.history)
|
||||
self.update_items_cache(self.history)
|
||||
|
||||
class ColorButton(QPushButton):
|
||||
|
||||
color_changed = pyqtSignal(object)
|
||||
|
||||
def __init__(self, initial_color=None, parent=None, choose_text=None):
|
||||
QPushButton.__init__(self, parent)
|
||||
self._color = None
|
||||
self.choose_text = choose_text or _('Choose &color')
|
||||
self.color = initial_color
|
||||
self.clicked.connect(self.choose_color)
|
||||
|
||||
@dynamic_property
|
||||
def color(self):
|
||||
def fget(self):
|
||||
return self._color
|
||||
def fset(self, val):
|
||||
val = unicode(val or '')
|
||||
col = QColor(val)
|
||||
orig = self._color
|
||||
if col.isValid():
|
||||
self._color = val
|
||||
self.setText(val)
|
||||
p = QPixmap(self.iconSize())
|
||||
p.fill(col)
|
||||
self.setIcon(QIcon(p))
|
||||
else:
|
||||
self._color = None
|
||||
self.setText(self.choose_text)
|
||||
self.setIcon(QIcon())
|
||||
if orig != col:
|
||||
self.color_changed.emit(self._color)
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
def choose_color(self):
|
||||
col = QColorDialog.getColor(QColor(self._color or Qt.white), self, _('Choose a color'))
|
||||
if col.isValid():
|
||||
self.color = unicode(col.name())
|
||||
|
||||
|
@ -1211,6 +1211,10 @@ def command_check_library(args, dbpath):
|
||||
for i in list:
|
||||
print ' %-40.40s - %-40.40s'%(i[0], i[1])
|
||||
|
||||
if not LibraryDatabase.exists_at(dbpath):
|
||||
prints('No library found at', dbpath, file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
|
||||
db = LibraryDatabase(dbpath)
|
||||
checker = CheckLibrary(dbpath, db)
|
||||
checker.scan_library(names, exts)
|
||||
|
Loading…
x
Reference in New Issue
Block a user