diff --git a/imgsrc/calibreSymbols.spd b/imgsrc/calibreSymbols.spd
new file mode 100644
index 0000000000..da751f442a
--- /dev/null
+++ b/imgsrc/calibreSymbols.spd
@@ -0,0 +1,152 @@
+SplineFontDB: 3.0
+FontName: calibreSymbols
+FullName: calibre Symbols
+FamilyName: calibre Symbols
+Weight: Medium
+Copyright: Created by Kovid Goyal with FontForge 2.0 (http://fontforge.sf.net)
+UComments: "2012-2-27: Created."
+Version: 001.000
+ItalicAngle: 0
+UnderlinePosition: -100
+UnderlineWidth: 50
+Ascent: 800
+Descent: 200
+LayerCount: 2
+Layer: 0 0 "Back" 1
+Layer: 1 0 "Fore" 0
+NeedsXUIDChange: 1
+XUID: [1021 913 325894820 11538708]
+FSType: 0
+OS2Version: 0
+OS2_WeightWidthSlopeOnly: 0
+OS2_UseTypoMetrics: 1
+CreationTime: 1330331997
+ModificationTime: 1330337167
+OS2TypoAscent: 0
+OS2TypoAOffset: 1
+OS2TypoDescent: 0
+OS2TypoDOffset: 1
+OS2TypoLinegap: 90
+OS2WinAscent: 0
+OS2WinAOffset: 1
+OS2WinDescent: 0
+OS2WinDOffset: 1
+HheadAscent: 0
+HheadAOffset: 1
+HheadDescent: 0
+HheadDOffset: 1
+MarkAttachClasses: 1
+DEI: 91125
+Encoding: UnicodeFull
+UnicodeInterp: none
+NameList: Adobe Glyph List
+DisplaySize: -24
+AntiAlias: 1
+FitToEm: 1
+WidthSeparation: 150
+WinInfo: 0 75 22
+BeginPrivate: 0
+EndPrivate
+BeginChars: 1114112 3
+
+StartChar: uni2605
+Encoding: 9733 9733 0
+Width: 933
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+544.1 344.853 m 1
+ 723.713 360.062 l 2
+ 774.129 364.181 799.969 366.241 801.229 366.241 c 0
+ 816.984 366.241 824.862 359.429 824.862 345.803 c 0
+ 824.862 340.416 823.287 336.218 820.136 333.207 c 0
+ 816.984 330.197 792.878 314.274 747.817 285.438 c 2
+ 596.566 188 l 1
+ 693.461 -56.3096 l 2
+ 694.722 -58.8447 695.353 -62.6465 695.353 -67.7168 c 0
+ 695.353 -72.4697 693.619 -76.5898 690.152 -80.0742 c 0
+ 686.687 -83.5605 682.905 -85.3027 678.81 -85.3027 c 0
+ 675.028 -85.3027 671.089 -83.9561 666.991 -81.2637 c 0
+ 662.896 -78.5693 640.681 -59.7949 600.348 -24.9385 c 2
+ 466.11 91.9873 l 1
+ 333.765 -23.0381 l 2
+ 292.172 -59.1621 269.405 -78.5693 265.467 -81.2637 c 0
+ 261.527 -83.9561 257.667 -85.3027 253.887 -85.3027 c 0
+ 249.475 -85.3027 245.457 -83.4814 241.833 -79.8369 c 0
+ 238.209 -76.1934 236.397 -72.1523 236.397 -67.7168 c 0
+ 236.397 -64.8652 245.379 -40.7832 263.34 4.53027 c 2
+ 335.184 188 l 1
+ 181.096 287.34 l 2
+ 137.61 315.225 114.372 330.593 111.379 333.445 c 0
+ 108.385 336.297 106.888 340.416 106.888 345.803 c 0
+ 106.888 359.745 114.924 366.717 130.994 366.717 c 0
+ 132.255 366.717 154.312 364.815 197.167 361.013 c 2
+ 387.648 344.853 l 1
+ 430.661 528.798 l 2
+ 441.69 576.646 448.544 602.945 451.222 607.699 c 0
+ 453.9 612.452 458.863 614.828 466.11 614.828 c 0
+ 473.674 614.828 478.716 612.215 481.236 606.986 c 0
+ 483.757 601.758 491.005 573.317 502.979 521.667 c 2
+ 544.1 344.853 l 1
+EndSplineSet
+Validated: 524289
+EndChar
+
+StartChar: zero
+Encoding: 48 48 1
+Width: 1303
+VWidth: 2048
+Flags: W
+HStem: -43.3789 76.7998<582.097 721.09> 623.341 76.7998<582.097 721.091>
+VStem: 403.82 97.4395<148.044 508.66> 802.221 96.959<148.044 508.659>
+LayerCount: 2
+Fore
+SplineSet
+651.5 623.341 m 0
+ 601.58 623.341 564.061 598.78 538.939 549.66 c 0
+ 513.82 500.541 501.26 426.7 501.26 328.141 c 0
+ 501.26 229.9 513.82 156.221 538.939 107.101 c 0
+ 564.061 57.9805 601.58 33.4209 651.5 33.4209 c 0
+ 701.74 33.4209 739.42 57.9805 764.54 107.101 c 0
+ 789.66 156.221 802.221 229.9 802.221 328.141 c 0
+ 802.221 426.7 789.66 500.541 764.54 549.66 c 0
+ 739.42 598.78 701.74 623.341 651.5 623.341 c 0
+651.5 700.141 m 0
+ 731.82 700.141 793.18 668.38 835.58 604.859 c 0
+ 877.979 541.341 899.18 449.101 899.18 328.141 c 0
+ 899.18 207.5 877.979 115.421 835.58 51.9004 c 0
+ 793.18 -11.6201 731.819 -43.3789 651.5 -43.3789 c 0
+ 571.18 -43.3789 509.82 -11.6201 467.42 51.9004 c 0
+ 425.021 115.421 403.82 207.5 403.82 328.141 c 0
+ 403.82 449.101 425.021 541.341 467.42 604.859 c 0
+ 509.82 668.38 571.18 700.141 651.5 700.141 c 0
+EndSplineSet
+Validated: 524289
+EndChar
+
+StartChar: period
+Encoding: 46 46 2
+Width: 516
+VWidth: 2048
+Flags: W
+HStem: 53.4004 166.199<203.263 309.297>
+VStem: 174.6 163.801<82.9501 190.955>
+LayerCount: 2
+Fore
+SplineSet
+338.4 142.8 m 0
+ 338.4 119.2 330.5 98.4004 314.7 80.4004 c 0
+ 298.9 62.4004 277 53.4004 249 53.4004 c 0
+ 225.4 53.4004 207.1 61.2002 194.1 76.7998 c 0
+ 181.1 92.4004 174.6 111 174.6 132.6 c 0
+ 174.6 155.8 182.6 176.1 198.6 193.5 c 0
+ 214.6 210.9 236.8 219.6 265.2 219.6 c 0
+ 288.8 219.6 306.9 212.2 319.5 197.4 c 0
+ 332.1 182.6 338.4 164.4 338.4 142.8 c 0
+EndSplineSet
+Validated: 524289
+EndChar
+EndChars
+EndSplineFont
diff --git a/resources/fonts/calibreSymbols.otf b/resources/fonts/calibreSymbols.otf
new file mode 100644
index 0000000000..6406e2b2a8
Binary files /dev/null and b/resources/fonts/calibreSymbols.otf differ
diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py
index 445a0dbc03..c27c004ba2 100644
--- a/src/calibre/gui2/__init__.py
+++ b/src/calibre/gui2/__init__.py
@@ -806,6 +806,23 @@ def is_gui_thread():
global gui_thread
return gui_thread is QThread.currentThread()
+_rating_font = None
+def rating_font():
+ global _rating_font
+ if _rating_font is None:
+ from PyQt4.Qt import QFontDatabase
+ _rating_font = 'Arial Unicode MS' if iswindows else 'sans-serif'
+ fontid = QFontDatabase.addApplicationFont(
+ #P('fonts/liberation/LiberationSerif-Regular.ttf')
+ P('fonts/calibreSymbols.otf')
+ )
+ if fontid > -1:
+ try:
+ _rating_font = unicode(list(
+ QFontDatabase.applicationFontFamilies(fontid))[0])
+ except:
+ pass
+ return _rating_font
def find_forms(srcdir):
base = os.path.join(srcdir, 'calibre', 'gui2')
diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py
index 628f846aea..08df7007a2 100644
--- a/src/calibre/gui2/book_details.py
+++ b/src/calibre/gui2/book_details.py
@@ -20,7 +20,7 @@ from calibre.ebooks.metadata.sources.identify import urls_from_identifiers
from calibre.constants import filesystem_encoding
from calibre.library.comments import comments_to_html
from calibre.gui2 import (config, open_local_file, open_url, pixmap_to_data,
- gprefs)
+ gprefs, rating_font)
from calibre.utils.icu import sort_key
from calibre.utils.formatter import EvalFormatter
from calibre.utils.date import is_date_undefined
@@ -116,6 +116,14 @@ def render_data(mi, use_roman_numbers=True, all_fields=False):
val = force_unicode(val)
ans.append((field,
u'
'%comments_to_html(val)))
+ elif metadata['datatype'] == 'rating':
+ val = getattr(mi, field)
+ if val:
+ val = val/2.0
+ ans.append((field,
+ u'%s | %s | '%(
+ name, rating_font(), u'\u2605'*int(val))))
elif metadata['datatype'] == 'composite' and \
metadata['display'].get('contains_html', False):
val = getattr(mi, field)
diff --git a/src/calibre/gui2/cover_flow.py b/src/calibre/gui2/cover_flow.py
index 4ba6c198f2..dd4763782a 100644
--- a/src/calibre/gui2/cover_flow.py
+++ b/src/calibre/gui2/cover_flow.py
@@ -10,10 +10,11 @@ Module to implement the Cover Flow feature
import sys, os, time
from PyQt4.Qt import (QImage, QSizePolicy, QTimer, QDialog, Qt, QSize, QAction,
- QStackedLayout, QLabel, QByteArray, pyqtSignal, QKeySequence)
+ QStackedLayout, QLabel, QByteArray, pyqtSignal, QKeySequence, QFont)
from calibre import plugins
-from calibre.gui2 import config, available_height, available_width, gprefs
+from calibre.gui2 import (config, available_height, available_width, gprefs,
+ rating_font)
pictureflow, pictureflowerror = plugins['pictureflow']
@@ -102,6 +103,8 @@ if pictureflow is not None:
type=Qt.QueuedConnection)
self.context_menu = None
self.setContextMenuPolicy(Qt.DefaultContextMenu)
+ if hasattr(self, 'setSubtitleFont'):
+ self.setSubtitleFont(QFont(rating_font()))
def set_context_menu(self, cm):
self.context_menu = cm
diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py
index c9736719b5..13a64f154e 100644
--- a/src/calibre/gui2/library/delegates.py
+++ b/src/calibre/gui2/library/delegates.py
@@ -5,16 +5,12 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal '
__docformat__ = 'restructuredtext en'
-from math import cos, sin, pi
-from PyQt4.Qt import (QColor, Qt, QModelIndex, QSize, QApplication,
- QPainterPath, QLinearGradient, QBrush,
- QPen, QStyle, QPainter, QStyleOptionViewItemV4,
- QIcon, QDoubleSpinBox, QVariant, QSpinBox,
- QStyledItemDelegate, QComboBox, QTextDocument,
- QAbstractTextDocumentLayout)
+from PyQt4.Qt import (Qt, QApplication, QStyle, QIcon, QDoubleSpinBox,
+ QVariant, QSpinBox, QStyledItemDelegate, QComboBox, QTextDocument,
+ QAbstractTextDocumentLayout, QFont)
-from calibre.gui2 import UNDEFINED_QDATETIME, error_dialog
+from calibre.gui2 import UNDEFINED_QDATETIME, error_dialog, rating_font
from calibre.gui2.widgets import EnLineEdit
from calibre.gui2.complete import MultiCompleteLineEdit, MultiCompleteComboBox
from calibre.utils.date import now, format_date, qt_to_dt
@@ -27,81 +23,35 @@ from calibre.gui2.languages import LanguagesEdit
class RatingDelegate(QStyledItemDelegate): # {{{
- COLOR = QColor("blue")
- SIZE = 16
- def __init__(self, parent):
- QStyledItemDelegate.__init__(self, parent)
- self._parent = parent
- self.dummy = QModelIndex()
- self.star_path = QPainterPath()
- self.star_path.moveTo(90, 50)
- for i in range(1, 5):
- self.star_path.lineTo(50 + 40 * cos(0.8 * i * pi), \
- 50 + 40 * sin(0.8 * i * pi))
- self.star_path.closeSubpath()
- self.star_path.setFillRule(Qt.WindingFill)
- self.gradient = QLinearGradient(0, 0, 0, 100)
- self.factor = self.SIZE/100.
-
- def sizeHint(self, option, index):
- #num = index.model().data(index, Qt.DisplayRole).toInt()[0]
- return QSize(5*(self.SIZE), self.SIZE+4)
-
- def paint(self, painter, option, index):
- style = self._parent.style()
- option = QStyleOptionViewItemV4(option)
- self.initStyleOption(option, index)
- option.text = u''
- num = index.model().data(index, Qt.DisplayRole).toInt()[0]
- def draw_star():
- painter.save()
- painter.scale(self.factor, self.factor)
- painter.translate(50.0, 50.0)
- painter.rotate(-20)
- painter.translate(-50.0, -50.0)
- painter.drawPath(self.star_path)
- painter.restore()
-
- painter.save()
- if hasattr(QStyle, 'CE_ItemViewItem'):
- style.drawControl(QStyle.CE_ItemViewItem, option,
- painter, self._parent)
- elif option.state & QStyle.State_Selected:
- painter.fillRect(option.rect, option.palette.highlight())
- else:
- painter.fillRect(option.rect, option.backgroundBrush)
-
- try:
- painter.setRenderHint(QPainter.Antialiasing)
- painter.setClipRect(option.rect)
- y = option.rect.center().y()-self.SIZE/2.
- x = option.rect.left()
- color = index.data(Qt.ForegroundRole)
- if color.isNull() or not color.isValid():
- color = self.COLOR
- else:
- color = QColor(color)
- painter.setPen(QPen(color, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
- self.gradient.setColorAt(0.0, color)
- self.gradient.setColorAt(1.0, color)
- painter.setBrush(QBrush(self.gradient))
- painter.translate(x, y)
- i = 0
- while i < num:
- draw_star()
- painter.translate(self.SIZE, 0)
- i += 1
- except:
- import traceback
- traceback.print_exc()
- painter.restore()
+ def __init__(self, *args, **kwargs):
+ QStyledItemDelegate.__init__(self, *args, **kwargs)
+ self.rf = QFont(rating_font())
+ self.em = Qt.ElideMiddle
def createEditor(self, parent, option, index):
sb = QStyledItemDelegate.createEditor(self, parent, option, index)
sb.setMinimum(0)
sb.setMaximum(5)
+ sb.setSuffix(' ' + _('stars'))
return sb
+
+ def displayText(self, value, locale):
+ r = value.toInt()[0]
+ if r < 0 or r > 5:
+ r = 0
+ return u'\u2605'*r
+
+ def sizeHint(self, option, index):
+ option.font = self.rf
+ option.textElideMode = self.em
+ return QStyledItemDelegate.sizeHint(self, option, index)
+
+ def paint(self, painter, option, index):
+ option.font = self.rf
+ option.textElideMode = self.em
+ return QStyledItemDelegate.paint(self, painter, option, index)
+
# }}}
class DateDelegate(QStyledItemDelegate): # {{{
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 044c01c39e..0b3c048a2e 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -588,8 +588,8 @@ class BooksModel(QAbstractTableModel): # {{{
def rating_type(r, idx=-1):
r = self.db.data[r][idx]
- r = r/2 if r else 0
- return QVariant(r)
+ r = r/2.0 if r else 0
+ return QVariant(int(r))
def datetime_type(r, idx=-1):
val = self.db.data[r][idx]
diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py
index 48049b765f..b622009a69 100644
--- a/src/calibre/gui2/library/views.py
+++ b/src/calibre/gui2/library/views.py
@@ -200,10 +200,10 @@ class BooksView(QTableView): # {{{
ac = a if self._model.sorted_on[1] else d
ac.setCheckable(True)
ac.setChecked(True)
- if col not in ('ondevice', 'rating', 'inlibrary') and \
+ if col not in ('ondevice', 'inlibrary') and \
(not self.model().is_custom_column(col) or \
self.model().custom_columns[col]['datatype'] not in ('bool',
- 'rating')):
+ )):
m = self.column_header_context_menu.addMenu(
_('Change text alignment for %s') % name)
al = self._model.alignment_map.get(col, 'left')
diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py
index 091c10462b..6149c3be8a 100644
--- a/src/calibre/gui2/metadata/single_download.py
+++ b/src/calibre/gui2/metadata/single_download.py
@@ -27,7 +27,7 @@ from calibre.utils.logging import GUILog as Log
from calibre.ebooks.metadata.sources.identify import (identify,
urls_from_identifiers)
from calibre.ebooks.metadata.book.base import Metadata
-from calibre.gui2 import error_dialog, NONE
+from calibre.gui2 import error_dialog, NONE, rating_font
from calibre.utils.date import (utcnow, fromordinal, format_date,
UNDEFINED_DATE, as_utc)
from calibre.library.comments import comments_to_html
@@ -254,6 +254,7 @@ class ResultsView(QTableView): # {{{
return ret
def show_details(self, index):
+ f = rating_font()
book = self.model().data(index, Qt.UserRole)
parts = [
'',
@@ -265,7 +266,8 @@ class ResultsView(QTableView): # {{{
if series[1]:
parts.append('%s: %s
'%series)
if not book.is_null('rating'):
- parts.append('%s
'%('\u2605'*int(book.rating)))
+ style = 'style=\'font-family:"%s"\''%f
+ parts.append('%s
'%(style, '\u2605'*int(book.rating)))
parts.append('')
if book.identifiers:
urls = urls_from_identifiers(book.identifiers)
diff --git a/src/calibre/gui2/pictureflow/pictureflow.cpp b/src/calibre/gui2/pictureflow/pictureflow.cpp
index 4e9d8a402d..876c8cc65e 100644
--- a/src/calibre/gui2/pictureflow/pictureflow.cpp
+++ b/src/calibre/gui2/pictureflow/pictureflow.cpp
@@ -364,6 +364,8 @@ public:
QTime previousPosTimestamp;
int pixelDistanceMoved;
int pixelsToMovePerSlide;
+ QFont subtitleFont;
+
void setImages(FlowImages *images);
void dataChanged();
@@ -422,6 +424,7 @@ PictureFlowPrivate::PictureFlowPrivate(PictureFlow* w, int queueLength_)
step = 0;
target = 0;
fade = 256;
+ subtitleFont = QFont();
triggerTimer.setSingleShot(true);
triggerTimer.setInterval(0);
@@ -674,9 +677,13 @@ void PictureFlowPrivate::render_text(QPainter *painter, int index) {
caption = slideImages->caption(index);
subtitle = slideImages->subtitle(index);
buffer_width = buffer.width(); buffer_height = buffer.height();
+ subtitleFont.setPixelSize(fontSize);
brect = painter->boundingRect(QRect(0, 0, buffer_width, fontSize), TEXT_FLAGS, caption);
+ painter->save();
+ painter->setFont(subtitleFont);
brect2 = painter->boundingRect(QRect(0, 0, buffer_width, fontSize), TEXT_FLAGS, subtitle);
+ painter->restore();
// So that if there is no subtitle, the caption is not flush with the bottom
if (brect2.height() < fontSize) brect2.setHeight(fontSize);
@@ -691,7 +698,11 @@ void PictureFlowPrivate::render_text(QPainter *painter, int index) {
painter->drawText(brect, TEXT_FLAGS, caption);
brect2.moveTop(buffer_height - brect2.height());
+
+ painter->save();
+ painter->setFont(subtitleFont);
painter->drawText(brect2, TEXT_FLAGS, slideImages->subtitle(index));
+ painter->restore();
}
// Render the slides. Updates only the offscreen buffer.
@@ -1168,6 +1179,17 @@ void PictureFlow::setSlideSize(QSize size)
d->setSlideSize(size);
}
+void PictureFlow::setSubtitleFont(QFont font)
+{
+ d->subtitleFont = font;
+}
+
+QFont PictureFlow::subtitleFont() const
+{
+ return d->subtitleFont;
+}
+
+
QImage PictureFlow::slide(int index) const
{
return d->slide(index);
diff --git a/src/calibre/gui2/pictureflow/pictureflow.h b/src/calibre/gui2/pictureflow/pictureflow.h
index f2c2c947e6..c5a9c76190 100644
--- a/src/calibre/gui2/pictureflow/pictureflow.h
+++ b/src/calibre/gui2/pictureflow/pictureflow.h
@@ -92,6 +92,7 @@ Q_OBJECT
Q_PROPERTY(int currentSlide READ currentSlide WRITE setCurrentSlide)
Q_PROPERTY(QSize slideSize READ slideSize WRITE setSlideSize)
+ Q_PROPERTY(QFont subtitleFont READ subtitleFont WRITE setSubtitleFont)
public:
/*!
@@ -120,6 +121,17 @@ public:
*/
void setSlideSize(QSize size);
+ /*!
+ Returns the font used to render subtitles
+ */
+ QFont subtitleFont() const;
+
+ /*!
+ Sets the font used to render subtitles
+ */
+ void setSubtitleFont(QFont font);
+
+
/*!
Clears any caches held to free up memory
*/
diff --git a/src/calibre/gui2/pictureflow/pictureflow.sip b/src/calibre/gui2/pictureflow/pictureflow.sip
index 84d2498ea9..21c6209df5 100644
--- a/src/calibre/gui2/pictureflow/pictureflow.sip
+++ b/src/calibre/gui2/pictureflow/pictureflow.sip
@@ -41,6 +41,10 @@ public :
void setSlideSize(QSize size);
+ QFont subtitleFont() const;
+
+ void setSubtitleFont(QFont font);
+
void clearCaches();
virtual QImage slide(int index) const;
diff --git a/src/calibre/library/field_metadata.py b/src/calibre/library/field_metadata.py
index de95eabd40..5b81f4a6a6 100644
--- a/src/calibre/library/field_metadata.py
+++ b/src/calibre/library/field_metadata.py
@@ -173,7 +173,7 @@ class FieldMetadata(dict):
'datatype':'rating',
'is_multiple':{},
'kind':'field',
- 'name':_('Ratings'),
+ 'name':_('Rating'),
'search_terms':['rating'],
'is_custom':False,
'is_category':True,