KG updates

This commit is contained in:
GRiker 2010-06-16 06:35:34 -06:00
commit c1293b5a94
24 changed files with 6425 additions and 7013 deletions

View File

@ -72,9 +72,4 @@ gui_pubdate_display_format = 'MMM yyyy'
# without changing anything is sufficient to change the sort.
title_series_sorting = 'library_order'
# How to render average rating in the tag browser.
# There are two rendering methods available. The first is to show a partial
# star, and the second is to show a partially filled rectangle. The first is
# better looking, but uses more screen space than the second.
# Values are 'star' or 'rectangle'
render_avg_rating_using='star'

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
@ -10,446 +9,238 @@
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
width="48"
height="48"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.44.1"
inkscape:version="0.45"
version="1.0"
sodipodi:docbase="/Users/david/Progetti/oxygen-svn/theme/svg/actions"
sodipodi:docname="bookmark.svg">
sodipodi:docbase="/home/dobey/Projects/gnome-icon-theme/scalable/apps"
sodipodi:docname="accessories-dictionary.svg"
inkscape:export-filename="/home/ulisse/Desktop/accessories-dictionary.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs4">
<linearGradient
id="linearGradient26907"
gradientUnits="userSpaceOnUse"
x1="-84.002403"
y1="-383.9971"
x2="-12.0029"
y2="-383.9971"
gradientTransform="matrix(0,1,-1,0,-39.9985,140.0029)">
<stop
offset="0"
style="stop-color:#888a85;stop-opacity:1;"
id="stop26909" />
<stop
offset="1"
style="stop-color:#2e3436;stop-opacity:1;"
id="stop26911" />
</linearGradient>
<linearGradient
gradientTransform="matrix(0,1,-1,0,-39.9985,140.0029)"
y2="-383.9975"
x2="-23.516129"
y1="-383.9971"
x1="-84.002403"
gradientUnits="userSpaceOnUse"
id="linearGradient3711">
<stop
id="stop3713"
style="stop-color:white;stop-opacity:1;"
offset="0" />
<stop
id="stop3715"
style="stop-color:white;stop-opacity:0;"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3081">
<stop
id="stop3083"
offset="0"
style="stop-color:#28691f;stop-opacity:1;" />
<stop
id="stop3085"
offset="1"
style="stop-color:#00bf00;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3290">
<stop
style="stop-color:yellow;stop-opacity:1;"
offset="0"
id="stop3292" />
<stop
style="stop-color:#ffb66d;stop-opacity:1;"
offset="1"
id="stop3294" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3765">
id="linearGradient2309">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3767" />
id="stop2311" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop3769" />
id="stop2313" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3747">
id="linearGradient2301">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
style="stop-color:#790000;stop-opacity:1"
offset="0"
id="stop3749" />
id="stop2303" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
style="stop-color:#b03636;stop-opacity:1"
offset="1"
id="stop3751" />
id="stop2305" />
</linearGradient>
<linearGradient
id="linearGradient3638">
inkscape:collect="always"
id="linearGradient2286">
<stop
style="stop-color:#ffffff;stop-opacity:0;"
style="stop-color:#555753"
offset="0"
id="stop3640" />
id="stop2288" />
<stop
id="stop3661"
offset="0.06868132"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3659"
offset="0.5"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
style="stop-color:#555753;stop-opacity:0"
offset="1"
id="stop3642" />
id="stop2290" />
</linearGradient>
<linearGradient
id="linearGradient1563">
inkscape:collect="always"
id="linearGradient2276">
<stop
id="stop1565"
style="stop-color:#babdb6;stop-opacity:1;"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
id="stop2278" />
<stop
id="stop1567"
style="stop-color:#8f9488;stop-opacity:1"
offset="1"
style="stop-color:white;stop-opacity:0;" />
id="stop2280" />
</linearGradient>
<linearGradient
id="linearGradient3273">
inkscape:collect="always"
id="linearGradient2258">
<stop
id="stop3275"
style="stop-color:#ffa4a4;stop-opacity:1"
offset="0"
style="stop-color:#ffffff;stop-opacity:0.55035973;" />
id="stop2260" />
<stop
id="stop3277"
style="stop-color:#a40000"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
id="stop2262" />
</linearGradient>
<linearGradient
id="linearGradient3291"
inkscape:collect="always"
id="linearGradient2235">
<stop
style="stop-color:#cccccc;stop-opacity:1"
offset="0"
id="stop2237" />
<stop
style="stop-color:#9b9b9b;stop-opacity:1"
offset="1"
id="stop2239" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2229">
<stop
style="stop-color:#888a85"
offset="0"
id="stop2231" />
<stop
style="stop-color:#d3d7cf;stop-opacity:0;"
offset="1"
id="stop2233" />
</linearGradient>
<linearGradient
id="linearGradient2221"
inkscape:collect="always">
<stop
id="stop3293"
id="stop2223"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
style="stop-color:#babdb6" />
<stop
id="stop3295"
id="stop2225"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
style="stop-color:#d3d7cf;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient12948">
inkscape:collect="always"
id="linearGradient2184">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop12950" />
id="stop2186" />
<stop
style="stop-color:#c0c0c0;stop-opacity:0;"
style="stop-color:#e3e3e3;stop-opacity:1"
offset="1"
id="stop12952" />
id="stop2188" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3273"
id="linearGradient3605"
x1="80.100487"
y1="44.807674"
x2="77.714729"
y2="101.4734"
xlink:href="#linearGradient2229"
id="linearGradient2211"
x1="24"
y1="19.505583"
x2="19.982143"
y2="19.550226"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.959962,0,0,0.959962,2.35549,3.275418)"
spreadMethod="reflect" />
gradientTransform="matrix(-1,0,0,1,48,0)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3638"
id="linearGradient3644"
x1="57.287113"
y1="1.1597457"
x2="144.2531"
y2="16.876789"
xlink:href="#linearGradient2221"
id="linearGradient2219"
x1="24"
y1="19.996655"
x2="32"
y2="19.90625"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1,0,0,1,48,0)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2184"
id="linearGradient2245"
gradientUnits="userSpaceOnUse"
x1="15.714286"
y1="16.82852"
x2="36.482143"
y2="20.667807" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2235"
id="linearGradient2247"
gradientUnits="userSpaceOnUse"
x1="19.940901"
y1="10.918805"
x2="24"
y2="22.750927" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2258"
id="linearGradient2264"
x1="32.794643"
y1="21.696428"
x2="34.79464"
y2="32.321426"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3638"
id="linearGradient3646"
x1="57.287113"
y1="1.1597457"
x2="144.2531"
y2="16.876789"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3638"
id="linearGradient3648"
x1="57.287113"
y1="1.1597457"
x2="144.2531"
y2="16.876789"
xlink:href="#linearGradient2276"
id="linearGradient2282"
x1="37.535713"
y1="34.196426"
x2="9.9285688"
y2="20.089285"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient12948"
id="radialGradient3716"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,-7.045514e-15,1.946707e-15,0.941176,2.788953e-13,3.492906)"
cx="23.190451"
cy="59.379417"
fx="22.471308"
fy="59.354759"
r="2.1082227" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1563"
id="linearGradient3732"
x1="98.291809"
y1="-126.7503"
x2="44.242641"
y2="101.45739"
xlink:href="#linearGradient2286"
id="radialGradient2292"
cx="24"
cy="36.75"
fx="24"
fy="36.75"
r="22.5"
gradientTransform="matrix(1,0,0,0.3,-3.16587e-17,25.725)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1563"
id="linearGradient3739"
gradientUnits="userSpaceOnUse"
x1="98.291809"
y1="-44.01474"
x2="44.242641"
y2="101.45739" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3291"
id="radialGradient3743"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.197802,0,92.82166)"
cx="63.912209"
cy="115.70919"
fx="63.975182"
fy="116.88514"
r="63.912209" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3747"
id="radialGradient3753"
cx="5.7531347"
cy="-45.41592"
fx="74.816956"
fy="-43.169445"
r="124.10334"
gradientTransform="matrix(1,-5.290907e-17,-3.962245e-18,9.492274e-2,9.333694e-14,-41.10492)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3747"
id="radialGradient3757"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,-1.087455e-16,-5.565153e-18,9.492274e-2,-1.420331e-15,-41.10492)"
cx="5.7531347"
cy="-45.41592"
fx="74.816956"
fy="-43.169445"
r="124.10334" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3747"
id="radialGradient3761"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,-1.302059e-16,-7.897474e-18,9.492274e-2,1.345372e-13,-41.10492)"
cx="5.7531347"
cy="-45.41592"
fx="74.816956"
fy="-43.169445"
r="124.10334" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3765"
id="radialGradient3771"
cx="23.662739"
cy="95.898506"
fx="24.26058"
fy="96.778763"
r="2.793914"
gradientTransform="matrix(1.484142,0.129521,-0.489782,5.61225,35.51325,-445.3727)"
xlink:href="#linearGradient2301"
id="linearGradient2307"
x1="23.955357"
y1="10.008928"
x2="29.214285"
y2="30.276785"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3290"
id="linearGradient3106"
x1="84.634949"
y1="116.10083"
x2="89.72541"
y2="-15.33666"
xlink:href="#linearGradient2309"
id="linearGradient2315"
x1="6.7230334"
y1="37.683041"
x2="37.804565"
y2="29.096745"
gradientUnits="userSpaceOnUse" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.111111,0,138.1081)"
r="64.796692"
fy="177.29686"
fx="80.738739"
cy="155.37218"
cx="80.738739"
id="radialGradient5079"
xlink:href="#linearGradient5073"
inkscape:collect="always" />
<linearGradient
id="linearGradient5073"
inkscape:collect="always">
<stop
id="stop5075"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop5077"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<foreignObject
id="foreignObject7221"
height="1"
width="1"
y="0"
x="0"
requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/">
<i:pgfRef
xlink:href="#adobe_illustrator_pgf" />
</foreignObject>
<linearGradient
id="XMLID_1_"
gradientUnits="userSpaceOnUse"
x1="95.693398"
y1="141.1738"
x2="32.308601"
y2="77.789001">
<stop
offset="0"
style="stop-color:#75511A"
id="stop7227" />
<stop
offset="0.3988"
style="stop-color:#563A11"
id="stop7229" />
<stop
offset="0.7642"
style="stop-color:#402B0B"
id="stop7231" />
<stop
offset="1"
style="stop-color:#382509"
id="stop7233" />
</linearGradient>
<linearGradient
id="XMLID_3_"
gradientUnits="userSpaceOnUse"
x1="63.9995"
y1="92.865196"
x2="63.9995"
y2="120.8652"
gradientTransform="translate(175.0067,11.74752)">
<stop
offset="0"
style="stop-color:#888A85"
id="stop7261" />
<stop
offset="0.3226"
style="stop-color:#A6A7A3"
id="stop7263" />
<stop
offset="1"
style="stop-color:#EEEEEC"
id="stop7265" />
</linearGradient>
<linearGradient
id="XMLID_4_"
gradientUnits="userSpaceOnUse"
x1="64.000504"
y1="108.8652"
x2="64.000504"
y2="92.865196">
<stop
offset="0"
style="stop-color:#EEEEEC"
id="stop7270" />
<stop
offset="1"
style="stop-color:#FFFFFF"
id="stop7272" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3081"
id="linearGradient2149"
gradientUnits="userSpaceOnUse"
x1="62.112335"
y1="90.513916"
x2="67.887672"
y2="39.095695" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient26907"
id="linearGradient3226"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,1,-1,0,-39.9985,140.0029)"
x1="-70.002899"
y1="-383.9971"
x2="-11.91648"
y2="-383.9971" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3711"
id="radialGradient3228"
gradientUnits="userSpaceOnUse"
cx="343.99899"
cy="92"
fx="343.99899"
fy="92"
r="36" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3711"
id="linearGradient3230"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,1.022977,-1.022977,0,111.9686,137.8125)"
x1="-88.058083"
y1="-131.93112"
x2="-45.096584"
y2="-131.93112" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
bordercolor="#a8a8a8"
borderopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.8203125"
inkscape:cx="64"
inkscape:cy="64"
inkscape:zoom="7.919596"
inkscape:cx="41.482905"
inkscape:cy="24.425816"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:window-width="1247"
inkscape:window-height="816"
inkscape:window-x="388"
inkscape:window-y="110"
inkscape:showpageshadow="false"
inkscape:grid-bbox="true"
showgrid="true"
gridspacingx="4px"
gridspacingy="4px"
gridempspacing="0"
inkscape:grid-points="true" />
inkscape:grid-points="true"
gridspacingx="0.5px"
gridspacingy="0.5px"
gridempspacing="2"
inkscape:window-width="872"
inkscape:window-height="694"
inkscape:window-x="0"
inkscape:window-y="25"
fill="#75507b" />
<metadata
id="metadata7">
<rdf:RDF>
@ -458,133 +249,108 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Ulisse Perusin</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>Dictionary</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>dictionary</rdf:li>
<rdf:li>translation</rdf:li>
</rdf:Bag>
</dc:subject>
<cc:license
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
<cc:requires
rdf:resource="http://web.resource.org/cc/SourceCode" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:label="Livello 1"
inkscape:groupmode="layer"
id="layer1">
<path
transform="matrix(0.511285,0.187762,-0.187762,0.511285,41.72321,44.08266)"
d="M 153.09403,94.713757 C 144.53658,107.09689 92.616372,93.013297 78.414631,98.001518 C 64.21289,102.98974 32.50348,146.4474 18.082028,142.13539 C 3.6605746,137.82337 1.0106378,84.092245 -8.1220219,72.127031 C -17.254681,60.161818 -68.384124,43.433534 -68.739625,28.385431 C -69.095125,13.337327 -18.812666,-5.7867426 -10.255219,-18.169872 C -1.697772,-30.553002 -1.5880954,-84.349316 12.613645,-89.337536 C 26.815387,-94.325757 60.541592,-52.41396 74.963045,-48.101941 C 89.384498,-43.789923 140.58172,-60.30959 149.71438,-48.344376 C 158.84704,-36.379162 129.40853,8.6478227 129.76403,23.695927 C 130.11953,38.74403 161.65148,82.330628 153.09403,94.713757 z "
inkscape:randomized="0"
inkscape:rounded="0.20136392"
inkscape:flatsided="false"
sodipodi:arg2="1.2330172"
sodipodi:arg1="0.60469864"
sodipodi:r2="76.832565"
sodipodi:r1="121.72647"
sodipodi:cy="25.510532"
sodipodi:cx="52.952892"
sodipodi:sides="5"
id="path3574"
style="opacity:1;fill:#e3ad00;fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:14.80892919;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
sodipodi:type="star" />
<path
style="opacity:1;fill:url(#linearGradient3106);fill-opacity:1.0;fill-rule:nonzero;stroke:url(#linearGradient3605);stroke-width:6.803;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
d="M 64.817613,10.159328 C 64.581604,10.317484 63.312654,10.957094 61.843149,12.708869 C 60.101516,14.785047 58.138879,17.917081 56.177505,21.235666 C 54.216128,24.55425 52.251443,28.092247 50.341888,31.150546 C 48.432331,34.208845 46.806952,36.762169 44.279648,38.544213 C 41.752344,40.326257 38.764915,41.002069 35.242943,41.773631 C 31.720971,42.545192 27.75285,43.193621 23.968308,43.926576 C 20.183765,44.659533 16.5656,45.476237 14.025101,46.419462 C 11.841858,47.230044 10.829167,48.201295 10.625712,48.345781 C 10.626839,48.347738 10.624524,48.371367 10.625712,48.374108 C 10.696321,48.571093 10.870285,49.989399 12.127109,52.000123 C 13.563478,54.298089 15.950898,57.154462 18.50096,60.045339 C 21.051023,62.936217 23.774397,65.867627 26.092925,68.628793 C 28.411454,71.389955 30.363146,73.748045 31.27699,76.702337 C 32.190833,79.656627 31.914822,82.68926 31.560274,86.277278 C 31.205724,89.8653 30.616267,93.839413 30.143862,97.665227 C 30.113483,97.911252 30.08362,98.156728 30.054361,98.401429 C 29.628627,101.96194 29.330856,105.3582 29.435657,107.89172 C 29.533657,110.26089 30.173974,111.54076 30.228847,111.74436 C 30.438123,111.73798 31.837454,111.97838 34.138142,111.40442 C 36.7675,110.74847 40.20401,109.39531 43.741411,107.86339 C 47.278812,106.33148 50.937026,104.62602 54.279513,103.27421 C 57.621999,101.9224 60.450754,100.79418 63.542844,100.838 C 66.634933,100.8818 69.418339,102.08321 72.721189,103.52916 C 76.024038,104.97512 79.653393,106.79843 83.145977,108.42996 C 86.638561,110.06147 90.026215,111.49575 92.635935,112.22595 C 94.919441,112.86485 96.334003,112.66799 96.54523,112.67918 C 96.605258,112.47676 97.286649,111.22034 97.451733,108.85487 C 97.640395,106.1515 97.418963,102.46604 97.055137,98.628384 C 96.691312,94.790732 96.174767,90.780408 95.922008,87.183781 C 95.669251,83.587159 95.491404,80.56438 96.488573,77.637169 C 97.485753,74.709955 99.503438,72.399636 101.89927,69.705264 C 104.29508,67.010894 107.11524,64.16591 109.74619,61.348436 C 112.37711,58.530963 114.78913,55.729544 116.29001,53.47319 C 117.57984,51.534136 117.84976,50.137859 117.93304,49.903833 C 117.93436,49.901119 117.93183,49.877435 117.93304,49.875506 C 117.7318,49.725835 116.72138,48.73631 114.56198,47.864201 C 112.04922,46.849382 108.49434,45.927914 104.73209,45.088035 C 100.96983,44.248155 97.012813,43.466178 93.514108,42.595149 C 90.015409,41.724119 87.038194,40.992031 84.562389,39.139105 C 82.086586,37.286179 80.548923,34.65831 78.726774,31.54714 C 76.904626,28.435971 75.041014,24.863438 73.174441,21.49062 C 71.307869,18.117801 69.417536,14.946869 67.735421,12.822182 C 66.263569,10.963081 64.982527,10.293346 64.817613,10.159328 z "
id="path3580"
sodipodi:nodetypes="cssssssssssssssssscssssssscssssssssssssssssc" />
<path
sodipodi:nodetypes="ccc"
id="path2276"
d="M -106.3852,44.124126 L -106.3852,41.329417 L -106.3852,44.124126 z "
style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" />
<path
sodipodi:type="arc"
style="opacity:0.38139535;fill:url(#radialGradient3743);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
id="path3289"
sodipodi:cx="63.912209"
sodipodi:cy="115.70919"
sodipodi:rx="63.912209"
sodipodi:ry="12.641975"
d="M 127.82442 115.70919 A 63.912209 12.641975 0 1 1 0,115.70919 A 63.912209 12.641975 0 1 1 127.82442 115.70919 z"
transform="matrix(-1.001374,0,0,0.410379,128,75.32738)" />
style="opacity:0.50196078;color:#000000;fill:url(#radialGradient2292);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:17.85;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
id="path2284"
sodipodi:cx="24"
sodipodi:cy="36.75"
sodipodi:rx="22.5"
sodipodi:ry="6.75"
d="M 46.5 36.75 A 22.5 6.75 0 1 1 1.5,36.75 A 22.5 6.75 0 1 1 46.5 36.75 z"
transform="matrix(1.066667,0,0,0.962963,-1.600001,1.111111)" />
<path
style="fill:none;fill-opacity:1.0;fill-rule:evenodd;stroke:url(#linearGradient3648);stroke-width:0.50672567;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.5813008"
d="M 55.266721,10.739701 C 56.520212,8.5685899 61.220699,1.3579337 65.008418,1.4134271 C 71.889436,1.5172832 83.511202,31.129589 88.946059,34.460427 C 95.635958,38.560436 119.92387,41.46414 124.34296,44.969282"
id="path3632"
sodipodi:nodetypes="csss" />
style="color:#000000;fill:#523856;fill-opacity:1;fill-rule:nonzero;stroke:#3e263b;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:17.85;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
d="M 4.5,11.5 L 43.5,11.5 L 47.5,38.5 L 29,38.5 L 28,37.5 C 26,39 22,39 20,37.5 L 19,38.5 L 0.5,38.5 L 4.5,11.5 z "
id="rect1304"
sodipodi:nodetypes="ccccccccc" />
<path
sodipodi:nodetypes="csss"
id="path3634"
d="M 55.236135,11.274949 C 56.489626,9.1038383 61.236542,1.57297 65.023711,1.6581121 C 71.830955,1.8111507 83.271335,31.483209 88.869595,34.705112 C 95.670099,38.618929 119.98852,41.765855 124.40761,45.270997"
style="fill:none;fill-opacity:1.0;fill-rule:evenodd;stroke:url(#linearGradient3646);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.43089432" />
sodipodi:type="inkscape:offset"
inkscape:radius="-0.91809106"
inkscape:original="M 4.5 11.5 L 0.5 38.5 L 19 38.5 L 20 37.5 C 22 39 26 39 28 37.5 L 29 38.5 L 47.5 38.5 L 43.5 11.5 L 4.5 11.5 z "
xlink:href="#rect1304"
style="opacity:0.13333333;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:17.85;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
id="path2274"
inkscape:href="#rect1304"
d="M 5.28125,12.40625 L 1.5625,37.59375 L 18.59375,37.59375 L 19.34375,36.84375 C 19.667151,36.507336 20.191452,36.467006 20.5625,36.75 C 21.327469,37.323727 22.653015,37.71875 24,37.71875 C 25.346985,37.71875 26.672531,37.323727 27.4375,36.75 C 27.808548,36.467006 28.332849,36.507336 28.65625,36.84375 L 29.40625,37.59375 L 46.4375,37.59375 L 42.71875,12.40625 L 5.28125,12.40625 z " />
<path
style="fill:none;fill-opacity:1.0;fill-rule:evenodd;stroke:url(#linearGradient3644);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.43089432"
d="M 55.205632,12.312054 C 56.459123,10.140944 61.420826,2.0361374 65.023711,2.1461616 C 71.282863,2.3391656 83.42385,32.459308 88.778086,35.193162 C 95.766183,38.761259 121.08663,42.680948 124.71264,46.094581"
id="path3636"
sodipodi:nodetypes="csss" />
style="fill:url(#linearGradient2282);fill-opacity:1.0;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 2,36.5 C 7.6666667,36.5 16,35 19,36.5 C 22,34 26,34 29,36.5 C 32,35 41,36.5 46,36.5 L 45.5,34 C 38.5,31.5 29,28.5 24,33 C 19,28.5 9.5,31.5 2.5,34 L 2,36.5 z "
id="path2180"
sodipodi:nodetypes="cccccccc" />
<path
sodipodi:type="arc"
style="opacity:0.70232556;fill:url(#radialGradient3716);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
id="path11160"
sodipodi:cx="23.190451"
sodipodi:cy="59.379417"
sodipodi:rx="2.1082227"
sodipodi:ry="1.9842097"
d="M 25.298673 59.379417 A 2.1082227 1.9842097 0 1 1 21.082228,59.379417 A 2.1082227 1.9842097 0 1 1 25.298673 59.379417 z"
transform="matrix(-1.742936,-1.063485,-0.470527,1.244278,191.1539,-3.699137)" />
sodipodi:type="inkscape:offset"
inkscape:radius="-1.0582203"
inkscape:original="M 14 30.875 C 10.125 31.375 6 32.75 2.5 34 L 2 36.5 C 7.6666667 36.5 16 35 19 36.5 C 22 34 26 34 29 36.5 C 32 35 41 36.5 46 36.5 L 45.5 34 C 38.5 31.5 29 28.5 24 33 C 21.5 30.75 17.875 30.375 14 30.875 z "
xlink:href="#path2180"
style="opacity:0.30196078;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2315);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path2266"
inkscape:href="#path2180"
d="M 14.375,31.9375 C 10.963293,32.392394 7.260823,33.622273 3.90625,34.8125 L 3.8125,35.34375 C 6.2979599,35.262594 9.0476285,35.037732 11.6875,34.875 C 14.462294,34.703951 16.881256,34.711661 18.78125,35.40625 C 20.133116,34.409774 21.661646,33.894157 23.21875,33.75 C 21.042747,31.830616 17.941674,31.461944 14.375,31.9375 z M 28.625,31.9375 C 27.145571,32.213473 25.86037,32.798142 24.78125,33.75 C 26.338354,33.894157 27.866884,34.409774 29.21875,35.40625 C 31.163554,34.697135 33.704549,34.703523 36.5625,34.875 C 39.261382,35.036933 41.920385,35.260963 44.1875,35.34375 L 44.09375,34.8125 C 40.739177,33.622273 37.036707,32.392394 33.625,31.9375 C 31.827105,31.697781 30.128781,31.656984 28.625,31.9375 z " />
<path
style="opacity:1;fill:url(#linearGradient3732);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:6.803;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
d="M 64.8125 10.15625 C 64.576492 10.314406 63.313255 10.966975 61.84375 12.71875 C 60.102119 14.794928 58.148874 17.931415 56.1875 21.25 C 54.226123 24.568584 52.253305 28.097951 50.34375 31.15625 C 48.434193 34.21455 46.808554 36.749206 44.28125 38.53125 C 41.753946 40.313295 38.771972 41.009688 35.25 41.78125 C 31.728028 42.55281 27.753292 43.204545 23.96875 43.9375 C 20.184208 44.670458 16.571749 45.463025 14.03125 46.40625 C 11.848007 47.216834 10.828455 48.199264 10.625 48.34375 C 10.62496 48.346283 10.625145 48.371753 10.625 48.375 C 10.695609 48.571986 10.868176 49.989276 12.125 52 C 13.561369 54.297967 15.949938 57.140373 18.5 60.03125 C 20.422509 62.210702 22.440722 64.427292 24.3125 66.5625 C 47.187815 68.967477 71.532076 77.450485 95.75 81.53125 C 95.830132 80.186335 96.067405 78.894893 96.5 77.625 C 97.497182 74.697786 99.510418 72.413122 101.90625 69.71875 C 104.30206 67.024383 107.11905 64.161224 109.75 61.34375 C 112.38092 58.526279 114.78037 55.725104 116.28125 53.46875 C 117.57108 51.529696 117.85422 50.140276 117.9375 49.90625 C 117.93747 49.903618 117.93766 49.878251 117.9375 49.875 C 117.73626 49.725328 116.7219 48.747109 114.5625 47.875 C 112.04974 46.860181 108.481 45.933629 104.71875 45.09375 C 100.95649 44.253869 96.998705 43.464779 93.5 42.59375 C 90.001302 41.722719 87.038305 40.977926 84.5625 39.125 C 82.0867 37.272072 80.540899 34.67367 78.71875 31.5625 C 76.8966 28.451331 75.054073 24.872818 73.1875 21.5 C 71.320931 18.127181 69.432115 14.937187 67.75 12.8125 C 66.278149 10.953399 64.977414 10.290268 64.8125 10.15625 z "
id="path3718" />
style="fill:url(#linearGradient2245);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2247);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 2.5,34 C 9,31.5 20,29 24,33 C 28,29 39,31.5 45.5,34 L 42.5,10.5 C 37,8 27.5,6 24,9 C 20,6 12,8 5.5,10.5 L 2.5,34 z "
id="path2182"
sodipodi:nodetypes="ccccccc" />
<path
style="opacity:0.41393443;fill:url(#linearGradient3739);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:6.803;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
d="M 64.8125 10.15625 C 64.576492 10.314406 63.313255 10.966975 61.84375 12.71875 C 60.102119 14.794928 58.148874 17.931415 56.1875 21.25 C 54.226123 24.568584 52.253305 28.097951 50.34375 31.15625 C 48.434193 34.21455 46.808554 36.749206 44.28125 38.53125 C 41.753946 40.313295 38.771972 41.009688 35.25 41.78125 C 31.728028 42.55281 27.753292 43.204545 23.96875 43.9375 C 20.184208 44.670458 16.571749 45.463025 14.03125 46.40625 C 11.848007 47.216834 10.828455 48.199264 10.625 48.34375 C 10.62496 48.346283 10.625145 48.371753 10.625 48.375 C 10.695609 48.571986 10.868176 49.989276 12.125 52 C 13.561369 54.297967 15.949938 57.140373 18.5 60.03125 C 20.422509 62.210702 22.440722 64.427292 24.3125 66.5625 C 25.752576 66.713901 27.204929 66.896788 28.65625 67.09375 C 42.328845 56.623879 60.733777 43.188439 78.53125 31.25 C 76.771363 28.21678 74.98888 24.755017 73.1875 21.5 C 71.320931 18.127181 69.432115 14.937187 67.75 12.8125 C 66.278149 10.953399 64.977414 10.290268 64.8125 10.15625 z M 99.34375 43.90625 C 86.79565 53.381359 75.792347 63.914843 66.25 75.09375 C 76.032927 77.504442 85.901575 79.871772 95.75 81.53125 C 95.830132 80.186335 96.067405 78.894893 96.5 77.625 C 97.497182 74.697786 99.510418 72.413122 101.90625 69.71875 C 104.30206 67.024383 107.11905 64.161224 109.75 61.34375 C 112.38092 58.526279 114.78037 55.725104 116.28125 53.46875 C 117.57108 51.529696 117.85422 50.140276 117.9375 49.90625 C 117.93747 49.903618 117.93766 49.878251 117.9375 49.875 C 117.73626 49.725328 116.7219 48.747109 114.5625 47.875 C 112.04974 46.860181 108.481 45.933629 104.71875 45.09375 C 102.94925 44.698729 101.13165 44.292609 99.34375 43.90625 z "
id="path3736" />
<path
id="path3741"
d="M 64.8125,10.15625 C 64.576492,10.314406 63.313255,10.966975 61.84375,12.71875 C 60.102119,14.794928 58.148874,17.931415 56.1875,21.25 C 54.226123,24.568584 52.253305,28.097951 50.34375,31.15625 C 48.434193,34.21455 46.808554,36.749206 44.28125,38.53125 C 41.753946,40.313295 38.771972,41.009688 35.25,41.78125 C 31.728028,42.55281 27.753292,43.204545 23.96875,43.9375 C 20.184208,44.670458 16.571749,45.463025 14.03125,46.40625 C 11.848007,47.216834 10.828455,48.199264 10.625,48.34375 C 10.62496,48.346283 10.625145,48.371753 10.625,48.375 C 10.695609,48.571986 10.868176,49.989276 12.125,52 C 13.561369,54.297967 60.733777,43.188439 78.53125,31.25 C 76.771363,28.21678 74.98888,24.755017 73.1875,21.5 C 71.320931,18.127181 69.432115,14.937187 67.75,12.8125 C 66.278149,10.953399 64.977414,10.290268 64.8125,10.15625 z M 99.34375,43.90625 C 68.470207,67.487324 85.901575,79.871772 95.75,81.53125 C 95.830132,80.186335 96.067405,78.894893 96.5,77.625 C 97.497182,74.697786 99.510418,72.413122 101.90625,69.71875 C 104.30206,67.024383 107.11905,64.161224 109.75,61.34375 C 112.38092,58.526279 114.78037,55.725104 116.28125,53.46875 C 117.57108,51.529696 117.85422,50.140276 117.9375,49.90625 C 117.93747,49.903618 117.93766,49.878251 117.9375,49.875 C 117.73626,49.725328 116.7219,48.747109 114.5625,47.875 C 112.04974,46.860181 108.481,45.933629 104.71875,45.09375 C 102.94925,44.698729 101.13165,44.292609 99.34375,43.90625 z "
style="opacity:0.34836066;fill:url(#linearGradient3739);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:6.803;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
sodipodi:nodetypes="csssssssssscsscccssssssssc" />
<path
sodipodi:type="arc"
style="opacity:0.35655739;fill:url(#radialGradient3753);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:0.43089432"
id="path3745"
sodipodi:cx="5.7531347"
sodipodi:cy="-45.41592"
sodipodi:rx="124.10334"
sodipodi:ry="11.780229"
d="M 129.85647 -45.41592 A 124.10334 11.780229 0 1 1 -118.35021,-45.41592 A 124.10334 11.780229 0 1 1 129.85647 -45.41592 z"
transform="matrix(0.126835,-5.623734e-2,-3.870485e-2,-9.211943e-2,44.81196,106.2565)" />
<path
transform="matrix(-0.126834,-5.702883e-2,3.870485e-2,-9.341592e-2,81.95911,106.3126)"
d="M 129.85647 -45.41592 A 124.10334 11.780229 0 1 1 -118.35021,-45.41592 A 124.10334 11.780229 0 1 1 129.85647 -45.41592 z"
sodipodi:ry="11.780229"
sodipodi:rx="124.10334"
sodipodi:cy="-45.41592"
sodipodi:cx="5.7531347"
id="path3755"
style="opacity:0.49590164;fill:url(#radialGradient3757);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:0.43089432"
sodipodi:type="arc" />
<path
transform="matrix(-6.548665e-3,-0.135343,-9.988208e-2,2.696531e-3,91.9485,98.93228)"
d="M 129.85647 -45.41592 A 124.10334 11.780229 0 1 1 -118.35021,-45.41592 A 124.10334 11.780229 0 1 1 129.85647 -45.41592 z"
sodipodi:ry="11.780229"
sodipodi:rx="124.10334"
sodipodi:cy="-45.41592"
sodipodi:cx="5.7531347"
id="path3759"
style="opacity:0.27459016;fill:url(#radialGradient3761);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:0.43089432"
sodipodi:type="arc" />
<path
style="opacity:0.17;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:14.80892944;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
d="M 126.314,45.945281 C 127.57715,54.014451 105.05512,70.888621 102.47025,78.476531 C 99.826558,86.237151 107.76438,114.43949 101.06401,119.16403 C 94.363618,123.88859 70.449248,106.96767 62.251508,106.85153 C 54.053768,106.73539 29.690348,122.98275 23.126508,118.07028 C 22.815738,117.8377 22.558998,117.52665 22.314008,117.19528 C 22.708398,118.50348 23.279848,119.53038 24.126508,120.16403 C 30.690348,125.0765 55.053768,108.82913 63.251508,108.94528 C 71.449248,109.06142 95.363618,126.01358 102.064,121.28903 C 108.76438,116.56449 100.82656,88.362141 103.47025,80.601531 C 106.11395,72.840911 129.61178,55.340191 127.189,47.507781 C 127.02007,46.961651 126.72727,46.430131 126.314,45.945281 z M 1.5015079,49.851531 C 4.5831579,57.838661 18.613888,70.110761 22.845258,77.320281 C 20.896748,71.159061 6.3960679,58.682221 1.5015079,49.851531 z "
id="path3308" />
<path
style="opacity:0.17;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:14.80892944;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
d="M 127.1265,47.382781 C 127.77543,55.569451 105.80307,72.111371 103.2515,79.601531 C 100.60781,87.362151 108.54563,115.56449 101.84525,120.28903 C 95.144868,125.01357 71.261748,108.06142 63.064008,107.94528 C 54.866278,107.82913 30.471598,124.10775 23.907758,119.19528 C 22.913828,118.45141 22.292008,117.15904 21.907758,115.50778 C 22.250148,117.65334 22.937778,119.30561 24.126508,120.19528 C 30.690348,125.10775 55.053778,108.82913 63.251508,108.94528 C 71.449248,109.06142 95.363638,126.01357 102.064,121.28903 C 108.76438,116.56449 100.82655,88.362151 103.47025,80.601531 C 106.11395,72.840911 129.61177,55.340181 127.189,47.507781 C 127.17552,47.464201 127.14164,47.425951 127.1265,47.382781 z M 0.93900787,47.757781 C 1.9815279,56.300511 21.645828,72.265141 23.876508,79.476531 C 23.903658,79.564291 23.914628,79.665031 23.939008,79.757781 C 23.870988,79.288551 23.775168,78.856101 23.657758,78.476531 C 21.511968,71.539581 3.2557579,56.495971 0.93900787,47.757781 z "
id="path3303" />
<path
style="fill:url(#radialGradient3771);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.55327869"
d="M 25.088207,80.21837 C 25.534474,90.747814 22.054583,105.95279 22.237274,111.46459 L 24.632057,111.69267 C 26.600057,101.69251 28.017156,91.508728 28.167214,80.902594 L 25.088207,80.21837 z "
id="path3763"
style="color:#000000;fill:url(#linearGradient2219);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:17.85;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
d="M 24,9.5 C 22,8 19.5,7.5 16,8 L 16,30.5 C 18,29.5 22,30.5 24,32.5 L 24,9.5 z "
id="rect2192"
sodipodi:nodetypes="ccccc" />
<path
style="opacity:0.62;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:14.80892944;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
d="M 0.89521787,47.070281 C 0.89114787,55.417331 21.603498,72.067851 23.895208,79.476531 C 24.122348,80.210811 24.248638,81.111361 24.301458,82.164031 C 24.258118,80.995191 24.141798,79.961201 23.895208,79.164031 C 21.629398,71.839061 1.3489179,55.506151 0.89521787,47.070281 z M 127.36395,48.789031 C 126.76815,57.193121 105.96742,73.013441 103.48895,80.289031 C 103.13757,81.320501 102.96318,82.732101 102.92645,84.382781 C 102.97549,82.859581 103.15849,81.571601 103.48895,80.601531 C 105.99802,73.236121 127.27213,57.108781 127.36395,48.789031 z M 63.270208,108.63278 C 55.072468,108.51664 30.709048,124.79525 24.145208,119.88278 C 22.709368,118.80818 21.987678,116.61813 21.738958,113.78903 C 21.963318,116.76637 22.658218,119.08239 24.145208,120.19528 C 30.709048,125.10775 55.072468,108.82913 63.270208,108.94528 C 71.467938,109.06142 95.382328,126.01357 102.0827,121.28903 C 103.80587,120.07399 104.52313,117.30046 104.73895,113.72653 C 104.49958,117.15646 103.75779,119.79539 102.0827,120.97653 C 95.382328,125.70107 71.467938,108.74892 63.270208,108.63278 z "
id="path3296" />
style="color:#000000;fill:url(#linearGradient2211);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:17.85;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
d="M 24,9.5 C 25.221264,8.803878 26.327771,7.9069322 28,8 L 29,30.5 C 27.5,30 25.5,31.5 24,32.5 L 24,9.5 z "
id="path2195"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:type="inkscape:offset"
inkscape:radius="-0.92850536"
inkscape:original="M 20.34375 7.625 C 16.101562 7.0390625 10.375 8.625 5.5 10.5 L 2.5 34 C 9 31.5 20 29 24 33 C 28 29 39 31.5 45.5 34 L 42.5 10.5 C 37 8 27.5 6 24 9 C 23 8.25 21.757812 7.8203125 20.34375 7.625 z "
xlink:href="#path2182"
style="opacity:0.65098039;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path2243"
inkscape:href="#path2182"
d="M 17.03125,8.375 C 14.611845,8.6563261 11.827815,9.5624782 8.78125,10.71875 L 4.25,32.59375 C 7.5567067,31.338728 11.345145,30.271354 14.90625,29.9375 C 16.969491,29.744071 18.927893,29.768608 20.625,30.125 C 21.963283,30.406039 23.09173,31.003906 24,31.8125 C 24.90827,31.003906 26.036717,30.406039 27.375,30.125 C 29.072107,29.768608 31.030509,29.744071 33.09375,29.9375 C 36.654855,30.271354 40.443293,31.338728 43.75,32.59375 L 39.1875,10.6875 C 36.612085,9.5579242 33.750698,8.6570052 31.15625,8.375 C 28.420939,8.0776836 26.053467,8.4675643 24.59375,9.71875 C 24.262671,9.9972426 23.783138,10.010203 23.4375,9.75 C 21.660341,8.417131 19.571761,8.0795918 17.03125,8.375 z " />
<path
style="fill:url(#linearGradient2264);fill-opacity:1.0;fill-rule:evenodd;stroke:url(#linearGradient2307);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="M 24.455357,8.7321429 C 24.5,20.5 34,20 33.5,30.5 L 32.5,34.5 L 34,34 L 35,35 L 35.5,31 C 36,20 24.544643,19.089286 24.5,8.5 L 24.455357,8.7321429 z "
id="path2227"
sodipodi:nodetypes="cccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 47 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 140 KiB

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2008-2010, Darko Miletic <darko.miletic at gmail.com>'
'''
@ -23,7 +22,14 @@ class Danas(BasicNewsRecipe):
language = 'sr'
publication_type = 'newspaper'
remove_empty_feeds = True
extra_css = '@font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} .article_description,body,.lokacija{font-family: Tahoma,Arial,Helvetica,sans1,sans-serif} .nadNaslov,h1,.preamble{font-family: Georgia,"Times New Roman",Times,serif1,serif} .antrfileText{border-left: 2px solid #999999; margin-left: 0.8em; padding-left: 1.2em; margin-bottom: 0; margin-top: 0} h2,.datum,.lokacija,.autor{font-size: small} .antrfileNaslov{border-left: 2px solid #999999; margin-left: 0.8em; padding-left: 1.2em; font-weight:bold; margin-bottom: 0; margin-top: 0} img{margin-bottom: 0.8em} '
extra_css = """ @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)}
@font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)}
.article_description,body,.lokacija{font-family: Tahoma,Arial,Helvetica,sans1,sans-serif}
.nadNaslov,h1,.preamble{font-family: Georgia,"Times New Roman",Times,serif1,serif}
.antrfileText{border-left: 2px solid #999999; margin-left: 0.8em; padding-left: 1.2em;
margin-bottom: 0; margin-top: 0} h2,.datum,.lokacija,.autor{font-size: small}
.antrfileNaslov{border-left: 2px solid #999999; margin-left: 0.8em; padding-left: 1.2em;
font-weight:bold; margin-bottom: 0; margin-top: 0} img{margin-bottom: 0.8em} """
conversion_options = {
'comment' : description
@ -42,19 +48,32 @@ class Danas(BasicNewsRecipe):
]
feeds = [
(u'Politika' , u'http://www.danas.rs/rss/rss.asp?column_id=27')
,(u'Hronika' , u'http://www.danas.rs/rss/rss.asp?column_id=2' )
,(u'Dru\xc5\xa1tvo', u'http://www.danas.rs/rss/rss.asp?column_id=24')
,(u'Dijalog' , u'http://www.danas.rs/rss/rss.asp?column_id=1' )
,(u'Ekonomija', u'http://www.danas.rs/rss/rss.asp?column_id=6' )
,(u'Svet' , u'http://www.danas.rs/rss/rss.asp?column_id=25')
,(u'Srbija' , u'http://www.danas.rs/rss/rss.asp?column_id=28')
,(u'Kultura' , u'http://www.danas.rs/rss/rss.asp?column_id=5' )
,(u'Sport' , u'http://www.danas.rs/rss/rss.asp?column_id=13')
,(u'Scena' , u'http://www.danas.rs/rss/rss.asp?column_id=42')
,(u'Feljton' , u'http://www.danas.rs/rss/rss.asp?column_id=19')
,(u'Periskop' , u'http://www.danas.rs/rss/rss.asp?column_id=4' )
,(u'Famozno' , u'http://www.danas.rs/rss/rss.asp?column_id=47')
(u'Politika' , u'http://www.danas.rs/rss/rss.asp?column_id=27')
,(u'Hronika' , u'http://www.danas.rs/rss/rss.asp?column_id=2' )
,(u'Drustvo' , u'http://www.danas.rs/rss/rss.asp?column_id=24')
,(u'Dijalog' , u'http://www.danas.rs/rss/rss.asp?column_id=1' )
,(u'Ekonomija' , u'http://www.danas.rs/rss/rss.asp?column_id=6' )
,(u'Svet' , u'http://www.danas.rs/rss/rss.asp?column_id=25')
,(u'Srbija' , u'http://www.danas.rs/rss/rss.asp?column_id=28')
,(u'Kultura' , u'http://www.danas.rs/rss/rss.asp?column_id=5' )
,(u'Sport' , u'http://www.danas.rs/rss/rss.asp?column_id=13')
,(u'Scena' , u'http://www.danas.rs/rss/rss.asp?column_id=42')
,(u'Feljton' , u'http://www.danas.rs/rss/rss.asp?column_id=19')
,(u'Periskop' , u'http://www.danas.rs/rss/rss.asp?column_id=4' )
,(u'Famozno' , u'http://www.danas.rs/rss/rss.asp?column_id=47')
,(u'Sluzbena beleska' , u'http://www.danas.rs/rss/rss.asp?column_id=48')
,(u'Suocavanja' , u'http://www.danas.rs/rss/rss.asp?column_id=49')
,(u'Moj Izbor' , u'http://www.danas.rs/rss/rss.asp?column_id=50')
,(u'Direktno' , u'http://www.danas.rs/rss/rss.asp?column_id=51')
,(u'I tome slicno' , u'http://www.danas.rs/rss/rss.asp?column_id=52')
,(u'No longer and not yet', u'http://www.danas.rs/rss/rss.asp?column_id=53')
,(u'Resetovanje' , u'http://www.danas.rs/rss/rss.asp?column_id=54')
,(u'Iza scene' , u'http://www.danas.rs/rss/rss.asp?column_id=60')
,(u'Drustvoslovlje' , u'http://www.danas.rs/rss/rss.asp?column_id=55')
,(u'Zvaka u pepeljari' , u'http://www.danas.rs/rss/rss.asp?column_id=56')
,(u'Vostani Serbie' , u'http://www.danas.rs/rss/rss.asp?column_id=57')
,(u'Med&Jad-a' , u'http://www.danas.rs/rss/rss.asp?column_id=58')
,(u'Svetlosti pozornice' , u'http://www.danas.rs/rss/rss.asp?column_id=59')
]
def preprocess_html(self, soup):
@ -65,3 +84,10 @@ class Danas(BasicNewsRecipe):
def print_version(self, url):
return url + '&action=print'
def get_cover_url(self):
cover_url = None
soup = self.index_to_soup('http://www.danas.rs/')
for citem in soup.findAll('img'):
if citem['src'].endswith('naslovna.jpg'):
return 'http://www.danas.rs' + citem['src']
return cover_url

View File

@ -0,0 +1,58 @@
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1271637235(BasicNewsRecipe):
title = u'Thairath'
__author__ = 'Anat R.'
language = 'th'
oldest_article = 7
max_articles_per_feed = 100
no_stylesheets = True
remove_javascript = True
use_embedded_content = False
feeds = [(u'News',
u'http://www.thairath.co.th/rss/news.xml'), (u'Politics',
u'http://www.thairath.co.th/rss/pol.xml'), (u'Economy',
u'http://www.thairath.co.th/rss/eco.xml'), (u'International',
u'http://www.thairath.co.th/rss/oversea.xml'), (u'Sports',
u'http://www.thairath.co.th/rss/sport.xml'), (u'Life',
u'http://www.thairath.co.th/rss/life.xml'), (u'Education',
u'http://www.thairath.co.th/rss/edu.xml'), (u'Tech',
u'http://www.thairath.co..th/rss/tech.xml'), (u'Entertainment',
u'http://www.thairath.co.th/rss/ent.xml')]
keep_only_tags = []
keep_only_tags.append(dict(name = 'h1', attrs = {'id' : 'title'}))
keep_only_tags.append(dict(name = 'ul', attrs = {'class' :
'detail-info'}))
keep_only_tags.append(dict(name = 'img', attrs = {'class' :
'detail-image'}))
keep_only_tags.append(dict(name = 'div', attrs = {'class' :
'entry'}))
remove_tags = []
remove_tags.append(dict(name = 'div', attrs = {'id':
'menu-holder'}))
remove_tags.append(dict(name = 'div', attrs = {'class':
'addthis_toolbox addthis_default_style'}))
remove_tags.append(dict(name = 'div', attrs = {'class': 'box top-item'}))
remove_tags.append(dict(name = 'div', attrs = {'class': 'column-200 column-margin-430'}))
remove_tags.append(dict(name = 'div', attrs = {'id':
'detail-related'}))
remove_tags.append(dict(name = 'div', attrs = {'id': 'related'}))
remove_tags.append(dict(name = 'id', attrs = {'class': 'footer'}))
remove_tags.append(dict(name = "ul",attrs =
{'id':'banner-highlights-images'}))

View File

@ -0,0 +1,44 @@
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1271596863(BasicNewsRecipe):
title = u'The Nation'
__author__ = 'Anat R.'
language = 'en_TH'
oldest_article = 7
max_articles_per_feed = 100
no_stylesheets = True
remove_javascript = True
use_embedded_content = False
feeds = [(u'Topstory',
u'http://www.nationmultimedia.com/home/rss/topstories.rss'),
(u'National', u'http://www.nationmultimedia.com/home/rss/national.rss'),
(u'Politics',
u'http://www.nationmultimedia.com/home/rss/politics.rss'), (u'Business',
u'http://www.nationmultimedia.com/home/rss/business.rss'),
(u'Regional', u'http://www.nationmultimedia.com/home/rss/regional.rss'),
(u'Sports', u'http://www.nationmultimedia.com/home/rss/sport.rss'),
(u'Travel', u'http://www.nationmultimedia.com/home/rss/travel.rss'),
(u'Life', u'http://www.nationmultimedia.com/home/rss/life.rss')]
keep_only_tags = []
keep_only_tags.append(dict(name = 'div', attrs = {'class' :
'pd10'}))
remove_tags = []
remove_tags.append(dict(name = 'div', attrs = {'class':
'WrapperHeaderCol2-2'}))
remove_tags.append(dict(name = 'div', attrs = {'class':
'LayoutMenu2'}))
remove_tags.append(dict(name = 'div', attrs = {'class':
'TextHeaderRight'}))
remove_tags.append(dict(name = "ul",attrs = {'id':'toolZoom'}))

View File

@ -436,7 +436,7 @@ from calibre.devices.blackberry.driver import BLACKBERRY
from calibre.devices.cybook.driver import CYBOOK
from calibre.devices.eb600.driver import EB600, COOL_ER, SHINEBOOK, \
POCKETBOOK360, GER2, ITALICA, ECLICTO, DBOOK, INVESBOOK, \
BOOQ, ELONEX
BOOQ, ELONEX, POCKETBOOK301
from calibre.devices.iliad.driver import ILIAD
from calibre.devices.irexdr.driver import IREXDR1000, IREXDR800
from calibre.devices.jetbook.driver import JETBOOK
@ -507,6 +507,7 @@ plugins += [
JETBOOK,
SHINEBOOK,
POCKETBOOK360,
POCKETBOOK301,
KINDLE,
KINDLE2,
KINDLE_DX,

View File

@ -201,4 +201,21 @@ class ELONEX(EB600):
def can_handle(cls, dev, debug=False):
return dev[3] == 'Elonex' and dev[4] == 'eBook'
class POCKETBOOK301(USBMS):
name = 'PocketBook 301 Device Interface'
description = _('Communicate with the PocketBook 301 reader.')
author = 'Kovid Goyal'
supported_platforms = ['windows', 'osx', 'linux']
FORMATS = ['epub', 'fb2', 'prc', 'mobi', 'pdf', 'djvu', 'rtf', 'chm', 'txt']
SUPPORTS_SUB_DIRS = True
MAIN_MEMORY_VOLUME_LABEL = 'PocketBook 301 Main Memory'
STORAGE_CARD_VOLUME_LABEL = 'PocketBook 301 Storage Card'
VENDOR_ID = [0x1]
PRODUCT_ID = [0x301]
BCD = [0x132]

View File

@ -385,14 +385,6 @@ class EPUBOutput(OutputFormatPlugin):
if val and not pval:
rule.style.setProperty('padding-left', val)
if stylesheet is not None:
stylesheet.data.add('a { color: inherit; text-decoration: inherit; '
'cursor: default; }')
stylesheet.data.add('a[href] { color: blue; '
'text-decoration: underline; cursor:pointer; }')
else:
self.oeb.log.warn('No stylesheet found')
# }}}
def workaround_sony_quirks(self): # {{{

View File

@ -223,6 +223,7 @@ class MetaInformation(object):
'isbn', 'tags', 'cover_data', 'application_id', 'guide',
'manifest', 'spine', 'toc', 'cover', 'language',
'book_producer', 'timestamp', 'lccn', 'lcc', 'ddc',
'author_sort_map',
'pubdate', 'rights', 'publication_type', 'uuid'):
if hasattr(mi, attr):
setattr(ans, attr, getattr(mi, attr))
@ -244,6 +245,7 @@ class MetaInformation(object):
self.tags = getattr(mi, 'tags', [])
#: mi.cover_data = (ext, data)
self.cover_data = getattr(mi, 'cover_data', (None, None))
self.author_sort_map = getattr(mi, 'author_sort_map', {})
for x in ('author_sort', 'title_sort', 'comments', 'category', 'publisher',
'series', 'series_index', 'rating', 'isbn', 'language',
@ -258,7 +260,7 @@ class MetaInformation(object):
'series', 'series_index', 'tags', 'rating', 'isbn', 'language',
'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover',
'book_producer', 'timestamp', 'lccn', 'lcc', 'ddc', 'pubdate',
'rights', 'publication_type', 'uuid'
'rights', 'publication_type', 'uuid', 'author_sort_map'
):
prints(x, getattr(self, x, 'None'))
@ -288,6 +290,9 @@ class MetaInformation(object):
self.tags += mi.tags
self.tags = list(set(self.tags))
if mi.author_sort_map:
self.author_sort_map.update(mi.author_sort_map)
if getattr(mi, 'cover_data', False):
other_cover = mi.cover_data[-1]
self_cover = self.cover_data[-1] if self.cover_data else ''

View File

@ -35,6 +35,8 @@ PUBLICATION_METADATA_FIELDS = frozenset([
'title_sort',
# Ordered list of authors. Must never be None, can be [_('Unknown')]
'authors',
# Map of sort strings for each author
'author_sort_map',
# Pseudo field that can be set, but if not set is auto generated
# from authors and languages
'author_sort',

View File

@ -16,6 +16,7 @@ NULL_VALUES = {
'classifiers' : {},
'languages' : [],
'device_collections': [],
'author_sort_map': {},
'authors' : [_('Unknown')],
'title' : _('Unknown'),
}

View File

@ -43,8 +43,8 @@ def _config():
help=_('Notify when a new version is available'))
c.add_opt('use_roman_numerals_for_series_number', default=True,
help=_('Use Roman numerals for series number'))
c.add_opt('sort_by_popularity', default=False,
help=_('Sort tags list by popularity'))
c.add_opt('sort_tags_by', default='name',
help=_('Sort tags list by name, popularity, or rating'))
c.add_opt('cover_flow_queue_length', default=6,
help=_('Number of covers to show in the cover browsing mode'))
c.add_opt('LRF_conversion_defaults', default=[],

View File

@ -62,11 +62,13 @@ def render_rows(data):
class CoverView(QWidget): # {{{
def __init__(self, parent=None):
def __init__(self, vertical, parent=None):
QWidget.__init__(self, parent)
self.setMaximumSize(QSize(120, 120))
self.setMinimumSize(QSize(120, 1))
self.setMinimumSize(QSize(120 if vertical else 20, 120 if vertical else
20))
self._current_pixmap_size = self.maximumSize()
self.vertical = vertical
self.animation = QPropertyAnimation(self, 'current_pixmap_size', self)
self.animation.setEasingCurve(QEasingCurve(QEasingCurve.OutExpo))
@ -74,7 +76,8 @@ class CoverView(QWidget): # {{{
self.animation.setStartValue(QSize(0, 0))
self.animation.valueChanged.connect(self.value_changed)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.setSizePolicy(QSizePolicy.Expanding if vertical else
QSizePolicy.Minimum, QSizePolicy.Expanding)
self.default_pixmap = QPixmap(I('book.svg'))
self.pixmap = self.default_pixmap
@ -98,8 +101,12 @@ class CoverView(QWidget): # {{{
self.animation.setEndValue(self.current_pixmap_size)
def relayout(self, parent_size):
self.setMaximumSize(parent_size.width(),
min(int(parent_size.height()/2.),int(4/3. * parent_size.width())+1))
if self.vertical:
self.setMaximumSize(parent_size.width(),
min(int(parent_size.height()/2.),int(4/3. * parent_size.width())+1))
else:
self.setMaximumSize(1+int(3/4. * parent_size.height()),
parent_size.height())
self.resize(self.maximumSize())
self.animation.stop()
self.do_layout()
@ -109,8 +116,7 @@ class CoverView(QWidget): # {{{
def show_data(self, data):
self.animation.stop()
if data.get('id', None) == self.data.get('id', None):
return
same_item = data.get('id', True) == self.data.get('id', False)
self.data = {'id':data.get('id', None)}
if data.has_key('cover'):
self.pixmap = QPixmap.fromImage(data.pop('cover'))
@ -120,7 +126,8 @@ class CoverView(QWidget): # {{{
self.pixmap = self.default_pixmap
self.do_layout()
self.update()
self.animation.start()
if not same_item:
self.animation.start()
def paintEvent(self, event):
canvas_size = self.rect()
@ -147,6 +154,7 @@ class CoverView(QWidget): # {{{
# }}}
# Book Info {{{
class Label(QLabel):
mr = pyqtSignal(object)
@ -174,8 +182,9 @@ class Label(QLabel):
class BookInfo(QScrollArea):
def __init__(self, parent=None):
def __init__(self, vertical, parent=None):
QScrollArea.__init__(self, parent)
self.vertical = vertical
self.setWidgetResizable(True)
self.label = Label()
self.setWidget(self.label)
@ -188,13 +197,25 @@ class BookInfo(QScrollArea):
rows = render_rows(data)
rows = u'\n'.join([u'<tr><td valign="top"><b>%s:</b></td><td valign="top">%s</td></tr>'%(k,t) for
k, t in rows])
if _('Comments') in data and data[_('Comments')]:
comments = comments_to_html(data[_('Comments')])
rows += u'<tr><td colspan="2">%s</td></tr>'%comments
if self.vertical:
if _('Comments') in data and data[_('Comments')]:
comments = comments_to_html(data[_('Comments')])
rows += u'<tr><td colspan="2">%s</td></tr>'%comments
self.label.setText(u'<table>%s</table>'%rows)
else:
comments = ''
if _('Comments') in data:
comments = comments_to_html(data[_('Comments')])
left_pane = u'<table>%s</table>'%rows
right_pane = u'<div>%s</div>'%comments
self.label.setText(u'<table><tr><td valign="top" '
'style="padding-right:2em">%s</td><td valign="top">%s</td></tr></table>'
% (left_pane, right_pane))
self.label.setText(u'<table>%s</table>'%rows)
class BookDetails(QWidget):
# }}}
class BookDetails(QWidget): # {{{
resized = pyqtSignal(object)
show_book_info = pyqtSignal()
@ -234,20 +255,26 @@ class BookDetails(QWidget):
# }}}
def __init__(self, parent=None):
def __init__(self, vertical, parent=None):
QWidget.__init__(self, parent)
self.setAcceptDrops(True)
self._layout = QVBoxLayout()
if not vertical:
self._layout.setDirection(self._layout.LeftToRight)
self.setLayout(self._layout)
self.cover_view = CoverView(self)
self.cover_view = CoverView(vertical, self)
self.cover_view.relayout(self.size())
self.resized.connect(self.cover_view.relayout, type=Qt.QueuedConnection)
self._layout.addWidget(self.cover_view, alignment=Qt.AlignHCenter)
self.book_info = BookInfo(self)
self._layout.addWidget(self.cover_view)
self.book_info = BookInfo(vertical, self)
self._layout.addWidget(self.book_info)
self.book_info.link_clicked.connect(self._link_clicked)
self.book_info.mr.connect(self.mouseReleaseEvent)
self.setMinimumSize(QSize(190, 200))
if vertical:
self.setMinimumSize(QSize(190, 200))
else:
self.setMinimumSize(120, 120)
self.setCursor(Qt.PointingHandCursor)
def _link_clicked(self, link):
@ -258,8 +285,7 @@ class BookDetails(QWidget):
id_, fmt = val.split(':')
self.view_specific_format.emit(int(id_), fmt)
elif typ == 'devpath':
path = os.path.dirname(val)
QDesktopServices.openUrl(QUrl.fromLocalFile(path))
QDesktopServices.openUrl(QUrl.fromLocalFile(val))
def mouseReleaseEvent(self, ev):
@ -275,10 +301,8 @@ class BookDetails(QWidget):
self.setToolTip('<p>'+_('Click to open Book Details window') +
'<br><br>' + _('Path') + ': ' + data.get(_('Path'), ''))
def reset_info(self):
self.show_data({})
# }}}

View File

@ -7,7 +7,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>884</width>
<width>1000</width>
<height>730</height>
</rect>
</property>
@ -89,7 +89,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>604</width>
<width>720</width>
<height>679</height>
</rect>
</property>
@ -370,7 +370,7 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="show_avg_rating">
<property name="text">
<string>Show &amp;average ratings in the tags browser</string>

View File

@ -8,17 +8,18 @@ __docformat__ = 'restructuredtext en'
import functools
from PyQt4.Qt import QMenu, Qt, pyqtSignal, QToolButton, QIcon, QStackedWidget, \
QWidget, QHBoxLayout, QToolBar, QSize, QSizePolicy
QSize, QSizePolicy, QStatusBar
from calibre.utils.config import prefs
from calibre.ebooks import BOOK_EXTENSIONS
from calibre.constants import isosx, __appname__
from calibre.constants import isosx, __appname__, preferred_encoding
from calibre.gui2 import config, is_widescreen
from calibre.gui2.library.views import BooksView, DeviceBooksView
from calibre.gui2.widgets import Splitter
from calibre.gui2.tag_view import TagBrowserWidget
from calibre.gui2.status import StatusBar, HStatusBar
from calibre.gui2.book_details import BookDetails
from calibre.gui2.notify import get_notifier
_keep_refs = []
@ -332,26 +333,24 @@ class Stack(QStackedWidget): # {{{
# }}}
class SideBar(QToolBar): # {{{
class StatusBar(QStatusBar): # {{{
def initialize(self, systray=None):
self.systray = systray
self.notifier = get_notifier(systray)
def __init__(self, splitters, jobs_button, parent=None):
QToolBar.__init__(self, _('Side bar'), parent)
self.setOrientation(Qt.Vertical)
self.setMovable(False)
self.setFloatable(False)
self.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.setIconSize(QSize(48, 48))
self.spacer = QWidget(self)
self.spacer.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
for s in splitters:
self.addWidget(s.button)
self.addWidget(self.spacer)
self.addWidget(jobs_button)
def show_message(self, msg, timeout=0):
QStatusBar.showMessage(self, msg, timeout)
if self.notifier is not None and not config['disable_tray_notification']:
if isosx and isinstance(msg, unicode):
try:
msg = msg.encode(preferred_encoding)
except UnicodeEncodeError:
msg = msg.encode('utf-8')
self.notifier(msg)
for ch in self.children():
if isinstance(ch, QToolButton):
ch.setCursor(Qt.PointingHandCursor)
def clear_message(self):
QStatusBar.clearMessage(self)
# }}}
@ -361,45 +360,46 @@ class LayoutMixin(object): # {{{
self.setupUi(self)
self.setWindowTitle(__appname__)
if config['gui_layout'] == 'narrow':
self.status_bar = self.book_details = StatusBar(self)
if config['gui_layout'] == 'narrow': # narrow {{{
self.book_details = BookDetails(False, self)
self.stack = Stack(self)
self.bd_splitter = Splitter('book_details_splitter',
_('Book Details'), I('book.svg'),
orientation=Qt.Vertical, parent=self, side_index=1)
self._layout_mem = [QWidget(self), QHBoxLayout()]
self._layout_mem[0].setLayout(self._layout_mem[1])
l = self._layout_mem[1]
l.addWidget(self.stack)
self.sidebar = SideBar([getattr(self, x+'_splitter')
for x in ('bd', 'tb', 'cb')], self.jobs_button, parent=self)
l.addWidget(self.sidebar)
self.bd_splitter.addWidget(self._layout_mem[0])
self.bd_splitter.addWidget(self.status_bar)
self.bd_splitter.addWidget(self.stack)
self.bd_splitter.addWidget(self.book_details)
self.bd_splitter.setCollapsible(self.bd_splitter.other_index, False)
self.centralwidget.layout().addWidget(self.bd_splitter)
else:
self.status_bar = HStatusBar(self)
self.setStatusBar(self.status_bar)
# }}}
else: # wide {{{
self.bd_splitter = Splitter('book_details_splitter',
_('Book Details'), I('book.svg'), initial_side_size=200,
orientation=Qt.Horizontal, parent=self, side_index=1)
self.stack = Stack(self)
self.bd_splitter.addWidget(self.stack)
self.book_details = BookDetails(self)
self.book_details = BookDetails(True, self)
self.bd_splitter.addWidget(self.book_details)
self.bd_splitter.setCollapsible(self.bd_splitter.other_index, False)
self.bd_splitter.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,
QSizePolicy.Expanding))
self.centralwidget.layout().addWidget(self.bd_splitter)
# }}}
for x in ('cb', 'tb', 'bd'):
button = getattr(self, x+'_splitter').button
button.setIconSize(QSize(22, 22))
self.status_bar.addPermanentWidget(button)
self.status_bar.addPermanentWidget(self.jobs_button)
self.status_bar = StatusBar(self)
for x in ('cb', 'tb', 'bd'):
button = getattr(self, x+'_splitter').button
button.setIconSize(QSize(24, 24))
self.status_bar.addPermanentWidget(button)
self.status_bar.addPermanentWidget(self.jobs_button)
self.setStatusBar(self.status_bar)
def finalize_layout(self):
self.status_bar.initialize(self.system_tray_icon)
self.book_details.show_book_info.connect(self.show_book_info)
self.book_details.files_dropped.connect(self.files_dropped_on_book)
self.book_details.open_containing_folder.connect(self.view_folder_for_id)
self.book_details.view_specific_format.connect(self.view_format_by_id)
m = self.library_view.model()
if m.rowCount(None) > 0:
self.library_view.set_current_row(0)

View File

@ -1,254 +0,0 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import os
from PyQt4.Qt import QStatusBar, QLabel, QWidget, QHBoxLayout, QPixmap, \
QSizePolicy, QScrollArea, Qt, QSize, pyqtSignal, \
QPropertyAnimation, QEasingCurve, QDesktopServices, QUrl
from calibre import fit_image, preferred_encoding, isosx
from calibre.gui2 import config
from calibre.gui2.widgets import IMAGE_EXTENSIONS
from calibre.gui2.notify import get_notifier
from calibre.ebooks import BOOK_EXTENSIONS
from calibre.library.comments import comments_to_html
from calibre.gui2.book_details import render_rows
class BookInfoDisplay(QWidget):
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS
files_dropped = pyqtSignal(object, object)
@classmethod
def paths_from_event(cls, event):
'''
Accept a drop event and return a list of paths that can be read from
and represent files with extensions.
'''
if event.mimeData().hasFormat('text/uri-list'):
urls = [unicode(u.toLocalFile()) for u in event.mimeData().urls()]
urls = [u for u in urls if os.path.splitext(u)[1] and os.access(u, os.R_OK)]
return [u for u in urls if os.path.splitext(u)[1][1:].lower() in cls.DROPABBLE_EXTENSIONS]
def dragEnterEvent(self, event):
if int(event.possibleActions() & Qt.CopyAction) + \
int(event.possibleActions() & Qt.MoveAction) == 0:
return
paths = self.paths_from_event(event)
if paths:
event.acceptProposedAction()
def dropEvent(self, event):
paths = self.paths_from_event(event)
event.setDropAction(Qt.CopyAction)
self.files_dropped.emit(event, paths)
def dragMoveEvent(self, event):
event.acceptProposedAction()
class BookCoverDisplay(QLabel): # {{{
def __init__(self, coverpath=I('book.svg')):
QLabel.__init__(self)
self.animation = QPropertyAnimation(self, 'size', self)
self.animation.setEasingCurve(QEasingCurve(QEasingCurve.OutExpo))
self.animation.setDuration(1000)
self.animation.setStartValue(QSize(0, 0))
self.setMaximumWidth(81)
self.setMaximumHeight(108)
self.default_pixmap = QPixmap(coverpath)
self.setScaledContents(True)
self.statusbar_height = 120
self.setPixmap(self.default_pixmap)
def do_layout(self):
self.animation.stop()
pixmap = self.pixmap()
pwidth, pheight = pixmap.width(), pixmap.height()
width, height = fit_image(pwidth, pheight,
pwidth, self.statusbar_height-20)[1:]
self.setMaximumHeight(height)
try:
aspect_ratio = pwidth/float(pheight)
except ZeroDivisionError:
aspect_ratio = 1
self.setMaximumWidth(int(aspect_ratio*self.maximumHeight()))
self.animation.setEndValue(self.maximumSize())
def setPixmap(self, pixmap):
QLabel.setPixmap(self, pixmap)
self.do_layout()
self.animation.start()
def sizeHint(self):
return QSize(self.maximumWidth(), self.maximumHeight())
def relayout(self, statusbar_size):
self.statusbar_height = statusbar_size.height()
self.do_layout()
# }}}
class BookDataDisplay(QLabel):
mr = pyqtSignal(object)
link_clicked = pyqtSignal(object)
def __init__(self):
QLabel.__init__(self)
self.setText('')
self.setWordWrap(True)
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
self.linkActivated.connect(self.link_activated)
self._link_clicked = False
def mouseReleaseEvent(self, ev):
QLabel.mouseReleaseEvent(self, ev)
if not self._link_clicked:
self.mr.emit(ev)
self._link_clicked = False
def link_activated(self, link):
self._link_clicked = True
link = unicode(link)
self.link_clicked.emit(link)
show_book_info = pyqtSignal()
def __init__(self, clear_message):
QWidget.__init__(self)
self.setCursor(Qt.PointingHandCursor)
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
self._layout = QHBoxLayout()
self.setLayout(self._layout)
self.clear_message = clear_message
self.cover_display = BookInfoDisplay.BookCoverDisplay()
self._layout.addWidget(self.cover_display)
self.book_data = BookInfoDisplay.BookDataDisplay()
self.book_data.mr.connect(self.mouseReleaseEvent)
self._layout.addWidget(self.book_data)
self.data = {}
self.setVisible(False)
self._layout.setAlignment(self.cover_display, Qt.AlignTop|Qt.AlignLeft)
def mouseReleaseEvent(self, ev):
ev.accept()
self.show_book_info.emit()
def show_data(self, data):
if data.has_key('cover'):
self.cover_display.setPixmap(QPixmap.fromImage(data.pop('cover')))
else:
self.cover_display.setPixmap(self.cover_display.default_pixmap)
rows, comments = [], ''
self.book_data.setText('')
self.data = data.copy()
rows = render_rows(self.data)
rows = '\n'.join([u'<tr><td valign="top"><b>%s:</b></td><td valign="top">%s</td></tr>'%(k,t) for
k, t in rows])
if _('Comments') in self.data:
comments = comments_to_html(self.data[_('Comments')])
comments = ('<b>%s:</b>'%_('Comments'))+comments
left_pane = u'<table>%s</table>'%rows
right_pane = u'<div>%s</div>'%comments
self.book_data.setText(u'<table><tr><td valign="top" '
'style="padding-right:2em">%s</td><td valign="top">%s</td></tr></table>'
% (left_pane, right_pane))
self.clear_message()
self.book_data.updateGeometry()
self.updateGeometry()
self.setVisible(True)
self.setToolTip('<p>'+_('Click to open Book Details window') +
'<br><br>' + _('Path') + ': ' + data.get(_('Path'), ''))
class StatusBarInterface(object):
def initialize(self, systray=None):
self.systray = systray
self.notifier = get_notifier(systray)
def show_message(self, msg, timeout=0):
QStatusBar.showMessage(self, msg, timeout)
if self.notifier is not None and not config['disable_tray_notification']:
if isosx and isinstance(msg, unicode):
try:
msg = msg.encode(preferred_encoding)
except UnicodeEncodeError:
msg = msg.encode('utf-8')
self.notifier(msg)
def clear_message(self):
QStatusBar.clearMessage(self)
class BookDetailsInterface(object):
# These signals must be defined in the class implementing this interface
files_dropped = None
show_book_info = None
open_containing_folder = None
view_specific_format = None
def reset_info(self):
raise NotImplementedError()
def show_data(self, data):
raise NotImplementedError()
class HStatusBar(QStatusBar, StatusBarInterface):
pass
class StatusBar(QStatusBar, StatusBarInterface, BookDetailsInterface):
files_dropped = pyqtSignal(object, object)
show_book_info = pyqtSignal()
open_containing_folder = pyqtSignal(int)
view_specific_format = pyqtSignal(int, object)
resized = pyqtSignal(object)
def initialize(self, systray=None):
StatusBarInterface.initialize(self, systray=systray)
self.book_info = BookInfoDisplay(self.clear_message)
self.book_info.setAcceptDrops(True)
self.scroll_area = QScrollArea()
self.scroll_area.setWidget(self.book_info)
self.scroll_area.setWidgetResizable(True)
self.book_info.show_book_info.connect(self.show_book_info.emit,
type=Qt.QueuedConnection)
self.book_info.files_dropped.connect(self.files_dropped.emit,
type=Qt.QueuedConnection)
self.book_info.book_data.link_clicked.connect(self._link_clicked)
self.addWidget(self.scroll_area, 100)
self.setMinimumHeight(120)
self.resized.connect(self.book_info.cover_display.relayout)
self.book_info.cover_display.relayout(self.size())
def _link_clicked(self, link):
typ, _, val = link.partition(':')
if typ == 'path':
self.open_containing_folder.emit(int(val))
elif typ == 'format':
id_, fmt = val.split(':')
self.view_specific_format.emit(int(id_), fmt)
elif typ == 'devpath':
path = os.path.dirname(val)
QDesktopServices.openUrl(QUrl.fromLocalFile(path))
def resizeEvent(self, ev):
self.resized.emit(self.size())
def reset_info(self):
self.book_info.show_data({})
def show_data(self, data):
self.book_info.show_data(data)

View File

@ -10,14 +10,13 @@ Browsing book collection by tags.
from itertools import izip
from functools import partial
from PyQt4.Qt import Qt, QTreeView, QApplication, pyqtSignal, QCheckBox, \
from PyQt4.Qt import Qt, QTreeView, QApplication, pyqtSignal, \
QFont, QSize, QIcon, QPoint, QVBoxLayout, QComboBox, \
QAbstractItemModel, QVariant, QModelIndex, QMenu, \
QPushButton, QWidget, QItemDelegate, QString, QPen, \
QColor, QLinearGradient, QBrush
QPushButton, QWidget, QItemDelegate
from calibre.gui2 import config, NONE
from calibre.utils.config import prefs, tweaks
from calibre.utils.config import prefs
from calibre.library.field_metadata import TagsIcons
from calibre.utils.search_query_parser import saved_searches
from calibre.gui2 import error_dialog
@ -25,12 +24,7 @@ from calibre.gui2.dialogs.tag_categories import TagCategories
from calibre.gui2.dialogs.tag_list_editor import TagListEditor
from calibre.gui2.dialogs.edit_authors_dialog import EditAuthorsDialog
class TagDelegate(QItemDelegate):
def __init__(self, parent):
QItemDelegate.__init__(self, parent)
self._parent = parent
self.icon = QIcon(I('star.png'))
class TagDelegate(QItemDelegate): # {{{
def paint(self, painter, option, index):
item = index.internalPointer()
@ -38,51 +32,29 @@ class TagDelegate(QItemDelegate):
QItemDelegate.paint(self, painter, option, index)
return
r = option.rect
# Paint the decoration icon
icon = self._parent.model().data(index, Qt.DecorationRole).toPyObject()
icon.paint(painter, r, Qt.AlignLeft)
model = self.parent().model()
icon = model.data(index, Qt.DecorationRole).toPyObject()
painter.save()
if item.tag.state != 0 or not config['show_avg_rating'] or \
item.tag.avg_rating is None:
icon.paint(painter, r, Qt.AlignLeft)
else:
painter.setOpacity(0.3)
icon.paint(painter, r, Qt.AlignLeft)
painter.setOpacity(1)
rating = item.tag.avg_rating
painter.setClipRect(r.left(), r.bottom()-int(r.height()*(rating/5.0)),
r.width(), r.height())
icon.paint(painter, r, Qt.AlignLeft)
painter.setClipRect(r)
# Paint the rating, if any. The decoration icon is assumed to be square,
# filling the row top to bottom. The three is arbitrary, there to
# provide a little space between the icon and what follows
r.setLeft(r.left()+r.height()+3)
rating = item.tag.avg_rating
if config['show_avg_rating'] and item.tag.avg_rating is not None:
painter.save()
if tweaks['render_avg_rating_using'] == 'star':
painter.setClipRect(r.left(), r.top(),
int(r.height()*(rating/5.0)), r.height())
self.icon.paint(painter, r, Qt.AlignLeft | Qt.AlignVCenter)
r.setLeft(r.left() + r.height())
else:
painter.translate(r.left(), r.top())
# Compute factor so sizes can be expressed in percentages of the
# box defined by the row height
factor = r.height()/100.
width = 20
height = 80
left_offset = 5
top_offset = 10
if r > 0.0:
color = QColor(100, 100, 255) #medium blue, less glare
pen = QPen(color, 5, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
painter.setPen(pen)
painter.scale(factor, factor)
painter.drawRect(left_offset, top_offset, width, height)
fill_height = height*(rating/5.0)
gradient = QLinearGradient(0, 0, 0, 100)
gradient.setColorAt(0.0, color)
gradient.setColorAt(1.0, color)
painter.setBrush(QBrush(gradient))
painter.drawRect(left_offset, top_offset+(height-fill_height),
width, fill_height)
# The '3' is arbitrary, there because we need a little space
# between the rectangle and the text.
r.setLeft(r.left() + ((width+left_offset*2)*factor) + 3)
painter.restore()
# Paint the text
r.setLeft(r.left()+r.height()+3)
painter.drawText(r, Qt.AlignLeft|Qt.AlignVCenter,
QString('[%d] %s'%(item.tag.count, item.tag.name)))
model.data(index, Qt.DisplayRole).toString())
painter.restore()
# }}}
class TagsView(QTreeView): # {{{
@ -107,12 +79,12 @@ class TagsView(QTreeView): # {{{
self.setHeaderHidden(True)
self.setItemDelegate(TagDelegate(self))
def set_database(self, db, tag_match, popularity):
def set_database(self, db, tag_match, sort_by):
self.hidden_categories = config['tag_browser_hidden_categories']
self._model = TagsModel(db, parent=self,
hidden_categories=self.hidden_categories,
search_restriction=None)
self.popularity = popularity
self.sort_by = sort_by
self.tag_match = tag_match
self.db = db
self.search_restriction = None
@ -120,8 +92,9 @@ class TagsView(QTreeView): # {{{
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.clicked.connect(self.toggle)
self.customContextMenuRequested.connect(self.show_context_menu)
self.popularity.setChecked(config['sort_by_popularity'])
self.popularity.stateChanged.connect(self.sort_changed)
pop = config['sort_tags_by']
self.sort_by.setCurrentIndex(self.db.CATEGORY_SORTS.index(pop))
self.sort_by.currentIndexChanged.connect(self.sort_changed)
self.refresh_required.connect(self.recount, type=Qt.QueuedConnection)
db.add_listener(self.database_changed)
@ -132,8 +105,8 @@ class TagsView(QTreeView): # {{{
def match_all(self):
return self.tag_match and self.tag_match.currentIndex() > 0
def sort_changed(self, state):
config.set('sort_by_popularity', state == Qt.Checked)
def sort_changed(self, pop):
config.set('sort_tags_by', self.db.CATEGORY_SORTS[pop])
self.recount()
def set_search_restriction(self, s):
@ -372,11 +345,7 @@ class TagTreeItem(object): # {{{
if self.tag.count == 0:
return QVariant('%s'%(self.tag.name))
else:
if self.tag.avg_rating is None:
return QVariant('[%d] %s'%(self.tag.count, self.tag.name))
else:
return QVariant('[%d][%3.1f] %s'%(self.tag.count,
self.tag.avg_rating, self.tag.name))
return QVariant('[%d] %s'%(self.tag.count, self.tag.name))
if role == Qt.EditRole:
return QVariant(self.tag.name)
if role == Qt.DecorationRole:
@ -420,7 +389,7 @@ class TagsModel(QAbstractItemModel): # {{{
self.row_map = []
# get_node_tree cannot return None here, because row_map is empty
data = self.get_node_tree(config['sort_by_popularity'])
data = self.get_node_tree(config['sort_tags_by'])
self.root_item = TagTreeItem()
for i, r in enumerate(self.row_map):
if self.hidden_categories and self.categories[i] in self.hidden_categories:
@ -464,11 +433,11 @@ class TagsModel(QAbstractItemModel): # {{{
# Now get the categories
if self.search_restriction:
data = self.db.get_categories(sort_on_count=sort,
data = self.db.get_categories(sort=sort,
icon_map=self.category_icon_map,
ids=self.db.search('', return_matches=True))
else:
data = self.db.get_categories(sort_on_count=sort, icon_map=self.category_icon_map)
data = self.db.get_categories(sort=sort, icon_map=self.category_icon_map)
tb_categories = self.db.field_metadata
for category in tb_categories:
@ -482,7 +451,7 @@ class TagsModel(QAbstractItemModel): # {{{
return data
def refresh(self):
data = self.get_node_tree(config['sort_by_popularity']) # get category data
data = self.get_node_tree(config['sort_tags_by']) # get category data
if data is None:
return False
row_index = -1
@ -691,7 +660,7 @@ class TagBrowserMixin(object): # {{{
def __init__(self, db):
self.library_view.model().count_changed_signal.connect(self.tags_view.recount)
self.tags_view.set_database(self.library_view.model().db,
self.tag_match, self.popularity)
self.tag_match, self.sort_by)
self.tags_view.tags_marked.connect(self.search.search_from_tags)
self.tags_view.tags_marked.connect(self.saved_search.clear_to_help)
self.tags_view.tag_list_edit.connect(self.do_tags_list_edit)
@ -752,9 +721,13 @@ class TagBrowserWidget(QWidget): # {{{
parent.tags_view = TagsView(parent)
self._layout.addWidget(parent.tags_view)
parent.popularity = QCheckBox(parent)
parent.popularity.setText(_('Sort by &popularity'))
self._layout.addWidget(parent.popularity)
parent.sort_by = QComboBox(parent)
# Must be in the same order as db2.CATEGORY_SORTS
for x in (_('Sort by name'), _('Sort by popularity'),
_('Sort by average rating')):
parent.sort_by.addItem(x)
parent.sort_by.setCurrentIndex(0)
self._layout.addWidget(parent.sort_by)
parent.tag_match = QComboBox(parent)
for x in (_('Match any'), _('Match all')):

View File

@ -126,8 +126,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
# Jobs Button {{{
self.job_manager = JobManager()
self.jobs_dialog = JobsDialog(self, self.job_manager)
self.jobs_button = JobsButton(horizontal=config['gui_layout'] !=
'narrow')
self.jobs_button = JobsButton(horizontal=True)
self.jobs_button.initialize(self.jobs_dialog, self.job_manager)
# }}}
@ -216,12 +215,6 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
self.vanity.setText(self.vanity_template%dict(version=' ', device=' '))
self.device_info = ' '
UpdateMixin.__init__(self, opts)
####################### Status Bar #####################
self.status_bar.initialize(self.system_tray_icon)
self.book_details.show_book_info.connect(self.show_book_info)
self.book_details.files_dropped.connect(self.files_dropped_on_book)
self.book_details.open_containing_folder.connect(self.view_folder_for_id)
self.book_details.view_specific_format.connect(self.view_format_by_id)
####################### Setup Toolbar #####################
ToolbarMixin.__init__(self)
@ -430,7 +423,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
self.book_on_device(None, reset=True)
db.set_book_on_device_func(self.book_on_device)
self.library_view.set_database(db)
self.tags_view.set_database(db, self.tag_match, self.popularity)
self.tags_view.set_database(db, self.tag_match, self.sort_by)
self.library_view.model().set_book_on_device_func(self.book_on_device)
self.status_bar.clear_message()
self.search.clear_to_help()

View File

@ -64,6 +64,10 @@ class Tag(object):
self.state = state
self.avg_rating = avg/2.0 if avg is not None else 0
self.sort = sort
if self.avg_rating > 0:
if tooltip:
tooltip = tooltip + ': '
tooltip = _('%sAverage rating is %3.1f')%(tooltip, self.avg_rating)
self.tooltip = tooltip
self.icon = icon
@ -429,7 +433,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if aum: aum = [a.strip().replace('|', ',') for a in aum.split(',')]
mi = MetaInformation(self.title(idx, index_is_id=index_is_id), aum)
mi.author_sort = self.author_sort(idx, index_is_id=index_is_id)
mi.authors_sort_strings = self.authors_sort_strings(idx, index_is_id)
if mi.authors:
mi.author_sort_map = {}
for name, sort in zip(mi.authors, self.authors_sort_strings(idx,
index_is_id)):
mi.author_sort_map[name] = sort
mi.comments = self.comments(idx, index_is_id=index_is_id)
mi.publisher = self.publisher(idx, index_is_id=index_is_id)
mi.timestamp = self.timestamp(idx, index_is_id=index_is_id)
@ -687,7 +695,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
tn=field['table'], col=field['link_column']), (id_,))
return set(x[0] for x in ans)
def get_categories(self, sort_on_count=False, ids=None, icon_map=None):
CATEGORY_SORTS = ('name', 'popularity', 'rating')
def get_categories(self, sort='name', ids=None, icon_map=None):
self.books_list_filter.change([] if not ids else ids)
categories = {}
@ -711,10 +721,12 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
else:
query = '''SELECT id, {0}, count, avg_rating, sort
FROM tag_browser_filtered_{1}'''.format(cn, tn)
if sort_on_count:
query += ' ORDER BY count DESC'
else:
if sort == 'popularity':
query += ' ORDER BY count DESC, sort ASC'
elif sort == 'name':
query += ' ORDER BY sort ASC'
else:
query += ' ORDER BY avg_rating DESC, sort ASC'
data = self.conn.get(query)
# icon_map is not None if get_categories is to store an icon and
@ -770,11 +782,10 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if count > 0:
categories['formats'].append(Tag(fmt, count=count, icon=icon))
if sort_on_count:
categories['formats'].sort(cmp=lambda x,y:cmp(x.count, y.count),
reverse=True)
else:
categories['formats'].sort(cmp=lambda x,y:cmp(x.name, y.name))
if sort == 'popularity':
categories['formats'].sort(key=lambda x: x.count, reverse=True)
else: # no ratings exist to sort on
categories['formats'].sort(key = lambda x:x.name)
#### Now do the user-defined categories. ####
user_categories = prefs['user_categories']
@ -799,12 +810,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
# Not a problem if we accumulate entries in the icon map
if icon_map is not None:
icon_map[cat_name] = icon_map[':user']
if sort_on_count:
if sort == 'popularity':
categories[cat_name] = \
sorted(items, cmp=(lambda x, y: cmp(y.count, x.count)))
sorted(items, key=lambda x: x.count, reverse=True)
elif sort == 'name':
categories[cat_name] = \
sorted(items, key=lambda x: x.sort.lower())
else:
categories[cat_name] = \
sorted(items, cmp=(lambda x, y: cmp(x.name.lower(), y.name.lower())))
sorted(items, key=lambda x:x.avg_rating, reverse=True)
#### Finally, the saved searches category ####
items = []

View File

@ -99,17 +99,20 @@ def html_to_lxml(raw):
raw = etree.tostring(root, encoding=None)
return etree.fromstring(raw)
def CATALOG_ENTRY(item, base_href, version, updated):
def CATALOG_ENTRY(item, base_href, version, updated, ignore_count=False):
id_ = 'calibre:category:'+item.name
iid = 'N' + item.name
if item.id is not None:
iid = 'I' + str(item.id)
link = NAVLINK(href = base_href + '/' + hexlify(iid))
count = _('%d books')%item.count
if ignore_count:
count = ''
return E.entry(
TITLE(item.name),
ID(id_),
UPDATED(updated),
E.content(_('%d books')%item.count, type='text'),
E.content(count, type='text'),
link
)
@ -265,8 +268,12 @@ class CategoryFeed(NavFeed):
def __init__(self, items, which, id_, updated, version, offsets, page_url, up_url):
NavFeed.__init__(self, id_, updated, version, offsets, page_url, up_url)
base_href = self.base_href + '/category/' + hexlify(which)
ignore_count = False
if which == 'search':
ignore_count = True
for item in items:
self.root.append(CATALOG_ENTRY(item, base_href, version, updated))
self.root.append(CATALOG_ENTRY(item, base_href, version, updated,
ignore_count=ignore_count))
class CategoryGroupFeed(NavFeed):
@ -393,7 +400,7 @@ class OPDSServer(object):
owhich = hexlify('N'+which)
up_url = url_for('opdsnavcatalog', version, which=owhich)
items = categories[category]
items = [x for x in items if x.name.startswith(which)]
items = [x for x in items if getattr(x, 'sort', x.name).startswith(which)]
if not items:
raise cherrypy.HTTPError(404, 'No items in group %r:%r'%(category,
which))
@ -458,11 +465,11 @@ class OPDSServer(object):
def __init__(self, text, count):
self.text, self.count = text, count
starts = set([x.name[0] for x in items])
starts = set([getattr(x, 'sort', x.name)[0] for x in items])
category_groups = OrderedDict()
for x in sorted(starts, cmp=lambda x,y:cmp(x.lower(), y.lower())):
category_groups[x] = len([y for y in items if
y.name.startswith(x)])
getattr(y, 'sort', y.name).startswith(x)])
items = [Group(x, y) for x, y in category_groups.items()]
max_items = self.opts.max_opds_items
offsets = OPDSOffsets(offset, max_items, len(items))

View File

@ -103,6 +103,7 @@ _extra_lang_codes = {
'en_TH' : _('English (Thailand)'),
'en_CY' : _('English (Cyprus)'),
'en_PK' : _('English (Pakistan)'),
'en_IL' : _('English (Israel)'),
'en_SG' : _('English (Singapore)'),
'en_YE' : _('English (Yemen)'),
'en_IE' : _('English (Ireland)'),