mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Use randomnly colored pins for text marks
This commit is contained in:
parent
b027b253f4
commit
d693cb46fe
Binary file not shown.
Before Width: | Height: | Size: 4.8 KiB |
177
resources/pin-template.svg
Normal file
177
resources/pin-template.svg
Normal file
@ -0,0 +1,177 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="128"
|
||||
height="128"
|
||||
viewBox="0 0 128 128"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||
sodipodi:docname="marked.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs4">
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter3014"
|
||||
inkscape:label="Ridged border"
|
||||
inkscape:menu="Bevels"
|
||||
inkscape:menu-tooltip="Ridged border with inner bevel"
|
||||
x="-0.029185463"
|
||||
y="-0.02918546"
|
||||
width="1.0583709"
|
||||
height="1.0583709">
|
||||
<feMorphology
|
||||
id="feMorphology3016"
|
||||
radius="4.3"
|
||||
in="SourceAlpha"
|
||||
result="result91" />
|
||||
<feComposite
|
||||
id="feComposite3018"
|
||||
in2="result91"
|
||||
operator="out"
|
||||
in="SourceGraphic" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3020"
|
||||
result="result0"
|
||||
stdDeviation="1.2" />
|
||||
<feDiffuseLighting
|
||||
id="feDiffuseLighting3022"
|
||||
diffuseConstant="1"
|
||||
result="result92">
|
||||
<feDistantLight
|
||||
id="feDistantLight3024"
|
||||
elevation="66"
|
||||
azimuth="225" />
|
||||
</feDiffuseLighting>
|
||||
<feBlend
|
||||
id="feBlend3026"
|
||||
in2="SourceGraphic"
|
||||
mode="multiply"
|
||||
result="result93" />
|
||||
<feComposite
|
||||
id="feComposite3028"
|
||||
in2="SourceAlpha"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3782"
|
||||
id="linearGradient3813"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-18.805519,996.21376)"
|
||||
x1="58"
|
||||
y1="91"
|
||||
x2="73"
|
||||
y2="91" />
|
||||
<linearGradient
|
||||
id="linearGradient3782">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3784" />
|
||||
<stop
|
||||
style="stop-color:#c3c3c0;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3786" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.2"
|
||||
inkscape:cx="19.821429"
|
||||
inkscape:cy="69.732143"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2101"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="59"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:pagecheckerboard="0" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Kovid Goyal</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-924.36216)">
|
||||
<g
|
||||
transform="translate(7.9775182,9.4253197)"
|
||||
id="g4149">
|
||||
<path
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3088"
|
||||
d="m 1.9128912,974.70018 49.4974748,-49.49747 -7.071068,21.2132 31.819805,17.67767 24.433067,-3.85121 -63.639613,63.63963 3.851207,-24.43308 -17.677669,-31.81981 z"
|
||||
style="fill:#f39509;fill-opacity:1;stroke:#7a6822;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3014)" />
|
||||
<path
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3097"
|
||||
d="M 63.925974,996.92087 120,1042.5389 74.532576,986.31427"
|
||||
style="fill:url(#linearGradient3813);fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.4 KiB |
@ -93,6 +93,7 @@ class View:
|
||||
'au_map': self.get_author_data,
|
||||
'ondevice': self.get_ondevice,
|
||||
'marked': self.get_marked,
|
||||
'all_marked_labels': self.all_marked_labels,
|
||||
'series_sort':self.get_series_sort,
|
||||
}.get(col, self._get)
|
||||
if isinstance(col, numbers.Integral):
|
||||
@ -221,6 +222,9 @@ class View:
|
||||
id_ = idx if index_is_id else self.index_to_id(idx)
|
||||
return self.marked_ids.get(id_, default_value)
|
||||
|
||||
def all_marked_labels(self):
|
||||
return set(self.marked_ids.values()) - {'true'}
|
||||
|
||||
def get_author_data(self, idx, index_is_id=True, default_value=None):
|
||||
id_ = idx if index_is_id else self.index_to_id(idx)
|
||||
with self.cache.safe_read_lock:
|
||||
|
@ -122,7 +122,7 @@ class MarkBooksAction(InterfaceAction):
|
||||
self.menu = m = self.qaction.menu()
|
||||
m.aboutToShow.connect(self.about_to_show_menu)
|
||||
ma = partial(self.create_menu_action, m)
|
||||
self.show_marked_action = a = ma('mark_with_text', _('Mark books with text label'), icon='marked-text.png')
|
||||
self.show_marked_action = a = ma('mark_with_text', _('Mark books with text label'), icon='marked.png')
|
||||
a.triggered.connect(self.mark_with_text)
|
||||
self.show_marked_action = a = ma('show-marked', _('Show marked books'), icon='search.png', shortcut='Shift+Ctrl+M')
|
||||
a.triggered.connect(self.show_marked)
|
||||
|
@ -23,7 +23,7 @@ from calibre import (
|
||||
fit_image, force_unicode, human_readable, isbytestring, prepare_string_for_xml,
|
||||
strftime
|
||||
)
|
||||
from calibre.constants import DEBUG, config_dir, filesystem_encoding
|
||||
from calibre.constants import DEBUG, config_dir, dark_link_color, filesystem_encoding
|
||||
from calibre.db.search import CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH, _match
|
||||
from calibre.ebooks.metadata import authors_to_string, fmt_sidx, string_to_authors
|
||||
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
||||
@ -52,6 +52,17 @@ ALIGNMENT_MAP = {'left': Qt.AlignmentFlag.AlignLeft, 'right': Qt.AlignmentFlag.A
|
||||
_default_image = None
|
||||
|
||||
|
||||
def render_pin(color='green', save_to=None):
|
||||
svg = P('pin-template.svg', data=True).replace(b'fill:#f39509', ('fill:' + color).encode('utf-8'))
|
||||
pm = QPixmap()
|
||||
dpr = QApplication.instance().devicePixelRatio()
|
||||
pm.setDevicePixelRatio(dpr)
|
||||
pm.loadFromData(svg, 'svg')
|
||||
if save_to:
|
||||
pm.save(save_to)
|
||||
return pm
|
||||
|
||||
|
||||
def default_image():
|
||||
global _default_image
|
||||
if _default_image is None:
|
||||
@ -232,7 +243,6 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
# remember that the cover grid view needs a larger version of the icon,
|
||||
# anyway)
|
||||
self.marked_icon = QIcon(I('marked.png'))
|
||||
self.marked_text_icon = QIcon(I('marked-text.png'))
|
||||
self.bool_blank_icon_as_icon = QIcon(self.bool_blank_icon)
|
||||
self.row_decoration = None
|
||||
self.device_connected = False
|
||||
@ -241,8 +251,33 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
self.current_highlighted_idx = None
|
||||
self.highlight_only = False
|
||||
self.row_height = 0
|
||||
self.marked_text_icons = {}
|
||||
self.read_config()
|
||||
|
||||
def marked_text_icon_for(self, label):
|
||||
import random
|
||||
ans = self.marked_text_icons.get(label)
|
||||
if ans is not None:
|
||||
return ans[1]
|
||||
used_labels = self.db.data.all_marked_labels()
|
||||
for qlabel in tuple(self.marked_text_icons):
|
||||
if qlabel not in used_labels:
|
||||
del self.marked_text_icons[qlabel]
|
||||
used_colors = {x[0] for x in self.marked_text_icons.values()}
|
||||
if QApplication.instance().is_dark_theme:
|
||||
all_colors = {dark_link_color, 'lightgreen', 'red', 'maroon', 'cyan', 'pink'}
|
||||
else:
|
||||
all_colors = {'blue', 'green', 'red', 'maroon', 'cyan', 'pink'}
|
||||
for c in all_colors - used_colors:
|
||||
color = c
|
||||
break
|
||||
else:
|
||||
color = random.choice(sorted(all_colors))
|
||||
pm = render_pin(color)
|
||||
ans = QIcon(pm)
|
||||
self.marked_text_icons[label] = color, ans
|
||||
return ans
|
||||
|
||||
def _clear_caches(self):
|
||||
self.color_cache = defaultdict(dict)
|
||||
self.icon_cache = defaultdict(dict)
|
||||
@ -1075,7 +1110,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
try:
|
||||
m = self.db.data.get_marked(self.db.data.index_to_id(section))
|
||||
if m:
|
||||
i = self.marked_icon if m == 'true' else self.marked_text_icon
|
||||
i = self.marked_icon if m == 'true' else self.marked_text_icon_for(m)
|
||||
else:
|
||||
i = self.row_decoration
|
||||
return i
|
||||
|
Loading…
x
Reference in New Issue
Block a user