mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
7613deb908
@ -251,8 +251,8 @@
|
|||||||
- title: Techcrunch and Pecat
|
- title: Techcrunch and Pecat
|
||||||
author: Darko Miletic
|
author: Darko Miletic
|
||||||
|
|
||||||
- title: Vio Mundo, IDG Now and Tojolaco
|
- title: "Vio Mundo, IDG Now! and Tojolaco"
|
||||||
author: Diniz Bortoletto
|
author: Diniz Bortolotto
|
||||||
|
|
||||||
- title: Geek and Poke, Automatiseringgids IT
|
- title: Geek and Poke, Automatiseringgids IT
|
||||||
author: DrMerry
|
author: DrMerry
|
||||||
|
912
imgsrc/keyboard-prefs.svg
Normal file
912
imgsrc/keyboard-prefs.svg
Normal file
@ -0,0 +1,912 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
|
||||||
|
<svg
|
||||||
|
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#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
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"
|
||||||
|
version="1.0"
|
||||||
|
id="Livello_1"
|
||||||
|
width="128"
|
||||||
|
height="128"
|
||||||
|
viewBox="0 0 144 94"
|
||||||
|
overflow="visible"
|
||||||
|
enable-background="new 0 0 144 94"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.45+devel"
|
||||||
|
sodipodi:docname="preferences-desktop-keyboard.svgz"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svgz.inkscape"
|
||||||
|
style="overflow:visible"><metadata
|
||||||
|
id="metadata224"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs222"><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#XMLID_35_"
|
||||||
|
id="linearGradient2719"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)"
|
||||||
|
x1="72.000504"
|
||||||
|
y1="83.799797"
|
||||||
|
x2="72.000504"
|
||||||
|
y2="5.8003001" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#rect3941_1_"
|
||||||
|
id="linearGradient2721"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.474754,0,0,-0.465075,-255.92554,-542.49842)"
|
||||||
|
x1="780.77576"
|
||||||
|
y1="-1248.1824"
|
||||||
|
x2="780.81049"
|
||||||
|
y2="-1195.5962" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#rect3941_1_"
|
||||||
|
id="linearGradient2723"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.474754,0,0,-0.465075,-263.1733,-542.49842)"
|
||||||
|
x1="708.36438"
|
||||||
|
y1="-1248.1824"
|
||||||
|
x2="708.39648"
|
||||||
|
y2="-1195.5962" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#rect3941_1_"
|
||||||
|
id="linearGradient2725"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.474754,0,0,-0.465075,-270.42218,-542.49842)"
|
||||||
|
x1="635.95538"
|
||||||
|
y1="-1248.1824"
|
||||||
|
x2="635.9834"
|
||||||
|
y2="-1195.5962" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#rect3941_1_"
|
||||||
|
id="linearGradient2727"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.474754,0,0,-0.465075,-253.92268,-535.12325)"
|
||||||
|
x1="790.77502"
|
||||||
|
y1="-1324.245"
|
||||||
|
x2="790.81049"
|
||||||
|
y2="-1271.6509" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#rect3941_1_"
|
||||||
|
id="linearGradient2729"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.474754,0,0,-0.465075,-261.17157,-535.12325)"
|
||||||
|
x1="718.36609"
|
||||||
|
y1="-1324.245"
|
||||||
|
x2="718.39838"
|
||||||
|
y2="-1271.6509" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#rect3941_1_"
|
||||||
|
id="linearGradient2731"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.474754,0,0,-0.465075,-268.41933,-535.12325)"
|
||||||
|
x1="645.95471"
|
||||||
|
y1="-1324.245"
|
||||||
|
x2="645.9834"
|
||||||
|
y2="-1271.6509" /><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.36659993"
|
||||||
|
width="1.7331999"
|
||||||
|
y="-0.17839379"
|
||||||
|
height="1.3567876"
|
||||||
|
id="filter3416"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.51430916"
|
||||||
|
id="feGaussianBlur3418" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.36972603"
|
||||||
|
width="1.7394521"
|
||||||
|
y="-0.17766281"
|
||||||
|
height="1.3553256"
|
||||||
|
id="filter3424"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.51984026"
|
||||||
|
id="feGaussianBlur3426" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.22179123"
|
||||||
|
width="1.4435825"
|
||||||
|
y="-0.10660794"
|
||||||
|
height="1.2132159"
|
||||||
|
id="filter3444"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.31193415"
|
||||||
|
id="feGaussianBlur3446" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.21995996"
|
||||||
|
width="1.4399199"
|
||||||
|
y="-0.10703628"
|
||||||
|
height="1.2140726"
|
||||||
|
id="filter3448"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.30858549"
|
||||||
|
id="feGaussianBlur3450" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.22183562"
|
||||||
|
width="1.4436712"
|
||||||
|
y="-0.10659768"
|
||||||
|
height="1.2131954"
|
||||||
|
id="filter3452"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.31190415"
|
||||||
|
id="feGaussianBlur3454" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.21995996"
|
||||||
|
width="1.4399199"
|
||||||
|
y="-0.10703628"
|
||||||
|
height="1.2140726"
|
||||||
|
id="filter3456"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.30858549"
|
||||||
|
id="feGaussianBlur3458" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.22179123"
|
||||||
|
width="1.4435825"
|
||||||
|
y="-0.10660794"
|
||||||
|
height="1.2132159"
|
||||||
|
id="filter3460"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.31193415"
|
||||||
|
id="feGaussianBlur3462" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.21991603"
|
||||||
|
width="1.4398321"
|
||||||
|
y="-0.10704668"
|
||||||
|
height="1.2140934"
|
||||||
|
id="filter3464"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.30861549"
|
||||||
|
id="feGaussianBlur3466" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.22179123"
|
||||||
|
width="1.4435825"
|
||||||
|
y="-0.10660794"
|
||||||
|
height="1.2132159"
|
||||||
|
id="filter3468"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.31193415"
|
||||||
|
id="feGaussianBlur3470" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.21995996"
|
||||||
|
width="1.4399199"
|
||||||
|
y="-0.10703628"
|
||||||
|
height="1.2140726"
|
||||||
|
id="filter3472"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.30858549"
|
||||||
|
id="feGaussianBlur3474" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.22183562"
|
||||||
|
width="1.4436712"
|
||||||
|
y="-0.10659768"
|
||||||
|
height="1.2131954"
|
||||||
|
id="filter3476"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.31190415"
|
||||||
|
id="feGaussianBlur3478" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.21995996"
|
||||||
|
width="1.4399199"
|
||||||
|
y="-0.10703628"
|
||||||
|
height="1.2140726"
|
||||||
|
id="filter3484"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.30858549"
|
||||||
|
id="feGaussianBlur3486" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.02891983"
|
||||||
|
width="1.0578397"
|
||||||
|
y="-0.14107949"
|
||||||
|
height="1.282159"
|
||||||
|
id="filter3492"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.33591005"
|
||||||
|
id="feGaussianBlur3494" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.02891983"
|
||||||
|
width="1.0578397"
|
||||||
|
y="-0.14107949"
|
||||||
|
height="1.282159"
|
||||||
|
id="filter3496"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.33591005"
|
||||||
|
id="feGaussianBlur3498" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.028919654"
|
||||||
|
width="1.0578393"
|
||||||
|
y="-0.14108369"
|
||||||
|
height="1.2821674"
|
||||||
|
id="filter3500"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.33592005"
|
||||||
|
id="feGaussianBlur3502" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.02891983"
|
||||||
|
width="1.0578397"
|
||||||
|
y="-0.14107949"
|
||||||
|
height="1.282159"
|
||||||
|
id="filter3504"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.33591005"
|
||||||
|
id="feGaussianBlur3506" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.02891983"
|
||||||
|
width="1.0578397"
|
||||||
|
y="-0.14107949"
|
||||||
|
height="1.282159"
|
||||||
|
id="filter3508"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.33591005"
|
||||||
|
id="feGaussianBlur3510" /></filter><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
x="-0.02891983"
|
||||||
|
width="1.0578397"
|
||||||
|
y="-0.14107949"
|
||||||
|
height="1.282159"
|
||||||
|
id="filter3512"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.33591005"
|
||||||
|
id="feGaussianBlur3514" /></filter><linearGradient
|
||||||
|
id="XMLID_31_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="69.333504"
|
||||||
|
y1="17.6504"
|
||||||
|
x2="69.333504"
|
||||||
|
y2="9.7958002"
|
||||||
|
xlink:href="#XMLID_32_">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
id="stop169" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#DDDDDD"
|
||||||
|
id="stop171" />
|
||||||
|
</linearGradient><linearGradient
|
||||||
|
id="XMLID_32_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="106.334"
|
||||||
|
y1="17.6504"
|
||||||
|
x2="106.334"
|
||||||
|
y2="9.7958002">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
id="stop186" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#DDDDDD"
|
||||||
|
id="stop188" />
|
||||||
|
</linearGradient><linearGradient
|
||||||
|
id="XMLID_30_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="31.742201"
|
||||||
|
y1="17.6504"
|
||||||
|
x2="31.742201"
|
||||||
|
y2="9.7958002">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
id="stop152" /><stop
|
||||||
|
id="stop3366"
|
||||||
|
style="stop-color:#eaeaea;stop-opacity:1;"
|
||||||
|
offset="0.68235296" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#c8c8c8;stop-opacity:1;"
|
||||||
|
id="stop154" />
|
||||||
|
</linearGradient><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#XMLID_30_"
|
||||||
|
id="linearGradient2945"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="69.333504"
|
||||||
|
y1="17.6504"
|
||||||
|
x2="69.333504"
|
||||||
|
y2="9.7958002" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#XMLID_30_"
|
||||||
|
id="linearGradient2947"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="106.334"
|
||||||
|
y1="17.6504"
|
||||||
|
x2="106.334"
|
||||||
|
y2="9.7958002" /><linearGradient
|
||||||
|
xlink:href="#XMLID_30_"
|
||||||
|
id="XMLID_28_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="38.033699"
|
||||||
|
y1="55.649399"
|
||||||
|
x2="38.033699"
|
||||||
|
y2="47.795502"
|
||||||
|
spreadMethod="pad">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
id="stop118" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#DDDDDD"
|
||||||
|
id="stop120" />
|
||||||
|
</linearGradient><linearGradient
|
||||||
|
id="XMLID_29_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="75.333"
|
||||||
|
y1="55.649399"
|
||||||
|
x2="75.333"
|
||||||
|
y2="47.795502">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
id="stop135" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#DDDDDD"
|
||||||
|
id="stop137" />
|
||||||
|
</linearGradient><linearGradient
|
||||||
|
id="XMLID_33_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="112.334"
|
||||||
|
y1="55.649399"
|
||||||
|
x2="112.334"
|
||||||
|
y2="47.795502">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
id="stop203" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#DDDDDD"
|
||||||
|
id="stop205" />
|
||||||
|
</linearGradient><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#XMLID_30_"
|
||||||
|
id="linearGradient2979"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
spreadMethod="pad"
|
||||||
|
x1="38.033699"
|
||||||
|
y1="55.649399"
|
||||||
|
x2="38.033699"
|
||||||
|
y2="47.795502" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#XMLID_30_"
|
||||||
|
id="linearGradient2981"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="75.333"
|
||||||
|
y1="55.649399"
|
||||||
|
x2="75.333"
|
||||||
|
y2="47.795502" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#XMLID_30_"
|
||||||
|
id="linearGradient2983"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="112.334"
|
||||||
|
y1="55.649399"
|
||||||
|
x2="112.334"
|
||||||
|
y2="47.795502" /><filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="filter3372"><feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.3179705"
|
||||||
|
id="feGaussianBlur3374" /></filter><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#XMLID_30_"
|
||||||
|
id="linearGradient3378"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="106.334"
|
||||||
|
y1="17.6504"
|
||||||
|
x2="106.334"
|
||||||
|
y2="9.7958002" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#XMLID_30_"
|
||||||
|
id="linearGradient3380"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="31.742201"
|
||||||
|
y1="17.6504"
|
||||||
|
x2="31.742201"
|
||||||
|
y2="9.7958002" /></defs><sodipodi:namedview
|
||||||
|
inkscape:window-height="696"
|
||||||
|
inkscape:window-width="998"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
guidetolerance="10.0"
|
||||||
|
gridtolerance="10.0"
|
||||||
|
objecttolerance="10.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base"
|
||||||
|
height="128px"
|
||||||
|
width="128px"
|
||||||
|
inkscape:zoom="2.8284271"
|
||||||
|
inkscape:cx="65.761733"
|
||||||
|
inkscape:cy="68.182683"
|
||||||
|
inkscape:window-x="26"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:current-layer="g2620" />
|
||||||
|
<filter
|
||||||
|
id="AI_Sfocatura_2">
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="2"
|
||||||
|
id="feGaussianBlur4" />
|
||||||
|
</filter>
|
||||||
|
<path
|
||||||
|
display="none"
|
||||||
|
d="M 89.758,1.8 C 88.983,1.8 88.229,1.945 87.501,2.17 C 86.774,1.945 86.022,1.8 85.248,1.8 L 52.752,1.8 C 51.978,1.8 51.226,1.945 50.499,2.17 C 49.772,1.944 49.02,1.8 48.245,1.8 L 15.755,1.8 C 11.479,1.8 8,5.275 8,9.546 L 8,42.054 C 8,45.72 10.57,48.783 14,49.582 C 14,53.16 14,80.057 14,80.057 C 14,84.327 17.478,87.8 21.752,87.8 L 54.248,87.8 C 55.022,87.8 55.774,87.655 56.5,87.431 C 57.227,87.656 57.979,87.8 58.754,87.8 L 91.241,87.8 C 92.017,87.8 92.77,87.655 93.498,87.431 C 94.225,87.655 94.977,87.8 95.751,87.8 L 128.241,87.8 C 132.518,87.8 135.999,84.326 135.999,80.057 L 135.999,47.546 C 135.999,43.881 133.43,40.818 129.999,40.019 C 129.999,36.442 129.999,9.546 129.999,9.546 C 129.999,5.275 126.521,1.8 122.247,1.8 L 89.758,1.8 L 89.758,1.8 z"
|
||||||
|
id="path6"
|
||||||
|
style="fill:#ff00bf;display:none" />
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
id="XMLID_35_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="72.000504"
|
||||||
|
y1="83.799797"
|
||||||
|
x2="72.000504"
|
||||||
|
y2="5.8003001">
|
||||||
|
<stop
|
||||||
|
offset="0.0059"
|
||||||
|
style="stop-color:#888888"
|
||||||
|
id="stop13" />
|
||||||
|
<stop
|
||||||
|
offset="0.5"
|
||||||
|
style="stop-color:#555555"
|
||||||
|
id="stop15" />
|
||||||
|
<stop
|
||||||
|
offset="0.54"
|
||||||
|
style="stop-color:#888888"
|
||||||
|
id="stop17" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#555555"
|
||||||
|
id="stop19" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
id="rect3785_1_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="780.81049"
|
||||||
|
y1="-1240.9404"
|
||||||
|
x2="780.81049"
|
||||||
|
y2="-1195.5962"
|
||||||
|
gradientTransform="matrix(0.422,0,0,-0.4134,-223.4874,-472.1986)">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#BEBEBE"
|
||||||
|
id="stop24" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#EDEDED"
|
||||||
|
id="stop26" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
id="rect3791_1_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="708.39648"
|
||||||
|
y1="-1240.9404"
|
||||||
|
x2="708.39648"
|
||||||
|
y2="-1195.5962"
|
||||||
|
gradientTransform="matrix(0.422,0,0,-0.4134,-229.9298,-472.1986)">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#BEBEBE"
|
||||||
|
id="stop38" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#EDEDED"
|
||||||
|
id="stop40" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
id="rect3797_1_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="635.9834"
|
||||||
|
y1="-1240.9404"
|
||||||
|
x2="635.9834"
|
||||||
|
y2="-1195.5962"
|
||||||
|
gradientTransform="matrix(0.422,0,0,-0.4134,-236.3732,-472.1986)">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#BEBEBE"
|
||||||
|
id="stop52" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#EDEDED"
|
||||||
|
id="stop54" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
id="rect3929_1_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="790.81049"
|
||||||
|
y1="-1316.9951"
|
||||||
|
x2="790.81049"
|
||||||
|
y2="-1271.6509"
|
||||||
|
gradientTransform="matrix(0.422,0,0,-0.4134,-221.7071,-465.6429)">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#BEBEBE"
|
||||||
|
id="stop66" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#EDEDED"
|
||||||
|
id="stop68" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
id="rect3935_1_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="718.39838"
|
||||||
|
y1="-1316.9951"
|
||||||
|
x2="718.39838"
|
||||||
|
y2="-1271.6509"
|
||||||
|
gradientTransform="matrix(0.422,0,0,-0.4134,-228.1505,-465.6429)">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#BEBEBE"
|
||||||
|
id="stop80" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#EDEDED"
|
||||||
|
id="stop82" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
id="rect3941_1_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="645.9834"
|
||||||
|
y1="-1316.9951"
|
||||||
|
x2="645.9834"
|
||||||
|
y2="-1271.6509"
|
||||||
|
gradientTransform="matrix(0.422,0,0,-0.4134,-234.5929,-465.6429)">
|
||||||
|
<stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#e4e4e4;stop-opacity:1;"
|
||||||
|
id="stop94" /><stop
|
||||||
|
id="stop3516"
|
||||||
|
style="stop-color:#bebebe;stop-opacity:1;"
|
||||||
|
offset="0.18012393" /><stop
|
||||||
|
offset="0.61417598"
|
||||||
|
style="stop-color:#cdcdcd;stop-opacity:1;"
|
||||||
|
id="stop3376" />
|
||||||
|
<stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#b3b3b3;stop-opacity:1;"
|
||||||
|
id="stop96" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<g
|
||||||
|
id="g8"
|
||||||
|
style="opacity:0.8;filter:url(#AI_Sfocatura_2)"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-9.0001128,-12.4)">
|
||||||
|
<path
|
||||||
|
d="M 128.242,45.8 L 125.547,45.8 C 125.826,45.276 126,44.688 126,44.054 L 126,11.546 C 126,9.481 124.316,7.8 122.248,7.8 L 89.758,7.8 C 88.907,7.8 88.131,8.093 87.501,8.57 C 86.872,8.093 86.097,7.8 85.248,7.8 L 52.752,7.8 C 51.903,7.8 51.128,8.093 50.499,8.57 C 49.869,8.094 49.094,7.8 48.245,7.8 L 15.755,7.8 C 13.685,7.8 12,9.48 12,11.546 L 12,44.054 C 12,46.119 13.685,47.8 15.755,47.8 L 18.453,47.8 C 18.173,48.323 18,48.912 18,49.546 L 18,82.057 C 18,84.121 19.683,85.8 21.752,85.8 L 54.248,85.8 C 55.097,85.8 55.872,85.507 56.5,85.031 C 57.13,85.507 57.905,85.8 58.754,85.8 L 91.241,85.8 C 92.092,85.8 92.868,85.507 93.498,85.03 C 94.127,85.507 94.902,85.8 95.751,85.8 L 128.241,85.8 C 130.313,85.8 131.999,84.121 131.999,82.057 L 131.999,49.546 C 132,47.48 130.314,45.8 128.242,45.8 z"
|
||||||
|
id="path10"
|
||||||
|
style="opacity:0.8" />
|
||||||
|
</g><g
|
||||||
|
id="g2620"
|
||||||
|
transform="translate(-4.5,0)"><path
|
||||||
|
style="fill:url(#linearGradient2721);fill-opacity:1"
|
||||||
|
d="M 96.478481,-2.5 L 133.03004,-2.5 C 134.11905,-2.5 135.00105,-1.621375 135.00105,-0.53575 L 135.00105,36.03575 C 135.00105,37.121374 134.11905,38 133.03004,38 L 96.478481,38 C 95.382722,38 94.500715,37.121374 94.500715,36.03575 L 94.500715,-0.53575 C 94.500715,-1.621375 95.382722,-2.5 96.478481,-2.5 z"
|
||||||
|
id="rect3785" /><g
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)"
|
||||||
|
nodetypes="cccsssssscccc"
|
||||||
|
id="path3787">
|
||||||
|
|
||||||
|
<radialGradient
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.6404,-8.5e-3,-7.7e-3,-0.6279,-240.4975,-567.9111)"
|
||||||
|
r="40.036301"
|
||||||
|
cy="-971.75677"
|
||||||
|
cx="527.62299"
|
||||||
|
id="XMLID_17_">
|
||||||
|
<stop
|
||||||
|
id="stop31"
|
||||||
|
style="stop-color:#E8E8E8"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop33"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
offset="1" />
|
||||||
|
</radialGradient>
|
||||||
|
<path
|
||||||
|
style="fill:url(#XMLID_17_)"
|
||||||
|
id="path35"
|
||||||
|
d="M 91.145,9.856 L 89.924,35.848 L 89.852,37.041 C 91.107,37.752 92.344,38.38 93.661,38.908 C 93.683,38.914 93.717,38.9 93.738,38.908 C 97.663,40.465 101.819,41.179 105.966,41.145 C 106.662,41.14 107.359,41.12 108.055,41.072 C 109.436,40.973 110.852,40.816 112.223,40.55 C 113.593,40.285 114.914,39.932 116.252,39.504 C 118.259,38.861 120.26,38.043 122.15,37.042 L 122.077,35.849 L 120.928,9.857 L 91.145,9.857 L 91.145,9.856 z" />
|
||||||
|
</g><path
|
||||||
|
style="fill:url(#linearGradient2723);fill-opacity:1"
|
||||||
|
d="M 54.846383,-2.5 L 91.404689,-2.5 C 92.492573,-2.5 93.375705,-1.621375 93.375705,-0.53575 L 93.375705,36.03575 C 93.375705,37.121374 92.492573,38 91.404689,38 L 54.846383,38 C 53.758499,38 52.875367,37.121374 52.875367,36.03575 L 52.875367,-0.53575 C 52.875367,-1.621375 53.758499,-2.5 54.846383,-2.5 z"
|
||||||
|
id="rect3791" /><g
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)"
|
||||||
|
nodetypes="cccsssssscccc"
|
||||||
|
id="path3793">
|
||||||
|
|
||||||
|
<radialGradient
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.6404,-8.5e-3,-7.7e-3,-0.6279,-247.2058,-567.9111)"
|
||||||
|
r="40.036098"
|
||||||
|
cy="-971.12653"
|
||||||
|
cx="480.29791"
|
||||||
|
id="XMLID_19_">
|
||||||
|
<stop
|
||||||
|
id="stop45"
|
||||||
|
style="stop-color:#E8E8E8"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop47"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
offset="1" />
|
||||||
|
</radialGradient>
|
||||||
|
<path
|
||||||
|
style="fill:url(#XMLID_19_)"
|
||||||
|
id="path49"
|
||||||
|
d="M 54.145,9.856 L 52.921,35.848 L 52.849,37.041 C 54.109,37.752 55.348,38.38 56.663,38.908 C 56.682,38.914 56.715,38.9 56.734,38.908 C 60.662,40.465 64.821,41.179 68.962,41.145 C 69.658,41.14 70.355,41.12 71.048,41.072 C 72.433,40.973 73.848,40.816 75.218,40.55 C 76.589,40.285 77.909,39.932 79.253,39.504 C 81.254,38.861 83.255,38.043 85.147,37.042 L 85.08,35.849 L 83.927,9.856 L 54.145,9.856 z" />
|
||||||
|
</g><path
|
||||||
|
style="fill:url(#linearGradient2725);fill-opacity:1"
|
||||||
|
d="M 13.224411,-2.5 L 49.775966,-2.5 C 50.867225,-2.5 51.750357,-1.621375 51.750357,-0.53575 L 51.750357,36.03575 C 51.750357,37.121374 50.867225,38 49.775966,38 L 13.224411,38 C 12.133151,38 11.250019,37.121374 11.250019,36.03575 L 11.250019,-0.53575 C 11.250019,-1.621375 12.133151,-2.5 13.224411,-2.5 z"
|
||||||
|
id="rect3797" /><g
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)"
|
||||||
|
nodetypes="cccsssssscccc"
|
||||||
|
id="path3799">
|
||||||
|
|
||||||
|
<radialGradient
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.6403,-8.5e-3,-7.7e-3,-0.6279,-253.8748,-567.9111)"
|
||||||
|
r="40.033199"
|
||||||
|
cy="-970.48578"
|
||||||
|
cx="432.98141"
|
||||||
|
id="XMLID_24_">
|
||||||
|
<stop
|
||||||
|
id="stop59"
|
||||||
|
style="stop-color:#E8E8E8"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop61"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
offset="1" />
|
||||||
|
</radialGradient>
|
||||||
|
<path
|
||||||
|
style="fill:url(#XMLID_24_)"
|
||||||
|
id="path63"
|
||||||
|
d="M 17.146,9.856 L 15.924,35.848 L 15.852,37.041 C 17.109,37.752 18.348,38.38 19.663,38.908 C 19.682,38.914 19.716,38.9 19.735,38.908 C 23.662,40.465 27.821,41.179 31.964,41.145 C 32.657,41.14 33.357,41.12 34.05,41.072 C 35.435,40.973 36.85,40.816 38.22,40.55 C 39.591,40.285 40.909,39.932 42.249,39.504 C 44.258,38.861 46.254,38.043 48.146,37.042 L 48.075,35.849 L 46.925,9.857 L 17.146,9.857 L 17.146,9.856 z" />
|
||||||
|
</g><path
|
||||||
|
style="fill:url(#linearGradient2727);fill-opacity:1"
|
||||||
|
d="M 103.22179,40.25 L 139.77334,40.25 C 140.8691,40.25 141.75111,41.128625 141.75111,42.21425 L 141.75111,78.789125 C 141.75111,79.87475 140.8691,80.75 139.77334,80.75 L 103.22179,80.75 C 102.13278,80.75 101.25077,79.873625 101.25077,78.789125 L 101.25077,42.21425 C 101.25077,41.128625 102.13278,40.25 103.22179,40.25 z"
|
||||||
|
id="rect3929" /><g
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)"
|
||||||
|
nodetypes="cccsssssscccc"
|
||||||
|
id="path3931">
|
||||||
|
|
||||||
|
<radialGradient
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.6404,-8.5e-3,-7.7e-3,-0.6279,-238.6489,-561.7972)"
|
||||||
|
r="40.036499"
|
||||||
|
cy="-1022.5366"
|
||||||
|
cx="533.49512"
|
||||||
|
id="XMLID_25_">
|
||||||
|
<stop
|
||||||
|
id="stop73"
|
||||||
|
style="stop-color:#E8E8E8"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop75"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
offset="1" />
|
||||||
|
</radialGradient>
|
||||||
|
<path
|
||||||
|
style="fill:url(#XMLID_25_)"
|
||||||
|
id="path77"
|
||||||
|
d="M 97.145,47.856 L 95.918,73.85 L 95.851,75.04 C 97.113,75.751 98.35,76.383 99.665,76.908 C 99.682,76.914 99.716,76.902 99.731,76.908 C 103.661,78.47 107.824,79.181 111.963,79.148 C 112.654,79.142 113.357,79.125 114.047,79.075 C 115.434,78.979 116.849,78.821 118.221,78.55 C 119.591,78.29 120.912,77.936 122.25,77.506 C 124.262,76.863 126.252,76.045 128.147,75.04 L 128.075,73.85 L 126.926,47.857 L 97.145,47.857 L 97.145,47.856 z" />
|
||||||
|
</g><path
|
||||||
|
style="fill:url(#linearGradient2729);fill-opacity:1"
|
||||||
|
d="M 61.599815,40.25 L 98.148,40.25 C 99.24263,40.25 100.12576,41.128625 100.12576,42.21425 L 100.12576,78.789125 C 100.12576,79.87475 99.24263,80.75 98.148,80.75 L 61.599815,80.75 C 60.511931,80.75 59.625423,79.873625 59.625423,78.789125 L 59.625423,42.21425 C 59.625423,41.128625 60.511931,40.25 61.599815,40.25 z"
|
||||||
|
id="rect3935" /><g
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)"
|
||||||
|
nodetypes="cccsssssscccc"
|
||||||
|
id="path3937">
|
||||||
|
|
||||||
|
<radialGradient
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.6403,-8.5e-3,-7.7e-3,-0.6279,-245.3333,-561.7972)"
|
||||||
|
r="40.038898"
|
||||||
|
cy="-1021.9087"
|
||||||
|
cx="486.17969"
|
||||||
|
id="XMLID_26_">
|
||||||
|
<stop
|
||||||
|
id="stop87"
|
||||||
|
style="stop-color:#E8E8E8"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop89"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
offset="1" />
|
||||||
|
</radialGradient>
|
||||||
|
<path
|
||||||
|
style="fill:url(#XMLID_26_)"
|
||||||
|
id="path91"
|
||||||
|
d="M 60.145,47.856 L 58.923,73.85 L 58.852,75.04 C 60.112,75.751 61.347,76.383 62.663,76.908 C 62.684,76.914 62.715,76.902 62.735,76.908 C 66.662,78.47 70.824,79.181 74.964,79.148 C 75.654,79.142 76.357,79.125 77.048,79.075 C 78.441,78.979 79.856,78.821 81.227,78.55 C 82.597,78.29 83.913,77.936 85.25,77.506 C 87.263,76.863 89.258,76.045 91.153,75.04 L 91.076,73.85 L 89.926,47.857 L 60.145,47.857 L 60.145,47.856 z" />
|
||||||
|
</g><path
|
||||||
|
style="fill:url(#linearGradient2731)"
|
||||||
|
d="M 19.971092,40.25 L 56.529397,40.25 C 57.617282,40.25 58.500414,41.128625 58.500414,42.21425 L 58.500414,78.789125 C 58.500414,79.87475 57.617282,80.75 56.529397,80.75 L 19.971092,80.75 C 18.883208,80.75 18.000075,79.873625 18.000075,78.789125 L 18.000075,42.21425 C 18.000075,41.128625 18.883208,40.25 19.971092,40.25 z"
|
||||||
|
id="rect3941" /><g
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)"
|
||||||
|
nodetypes="cccsssssscccc"
|
||||||
|
id="path3943"
|
||||||
|
style="filter:url(#filter3372)">
|
||||||
|
|
||||||
|
<radialGradient
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.6404,-8.5e-3,-7.7e-3,-0.6279,-252.0475,-561.7972)"
|
||||||
|
r="40.039001"
|
||||||
|
cy="-1021.27"
|
||||||
|
cx="438.85059"
|
||||||
|
id="XMLID_27_">
|
||||||
|
<stop
|
||||||
|
id="stop101"
|
||||||
|
style="stop-color:#E8E8E8"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop103"
|
||||||
|
style="stop-color:#FFFFFF"
|
||||||
|
offset="0.5858" />
|
||||||
|
</radialGradient>
|
||||||
|
<path
|
||||||
|
style="fill:url(#XMLID_27_)"
|
||||||
|
id="path105"
|
||||||
|
d="M 23.146,47.856 L 21.921,73.85 L 21.849,75.04 C 23.11,75.751 24.348,76.383 25.663,76.908 C 25.682,76.914 25.715,76.902 25.734,76.908 C 29.662,78.47 33.821,79.181 37.965,79.148 C 38.658,79.142 39.358,79.125 40.049,79.075 C 41.436,78.979 42.851,78.821 44.222,78.55 C 45.593,78.29 46.911,77.936 48.252,77.506 C 50.262,76.863 52.257,76.045 54.15,75.04 L 54.078,73.85 L 52.926,47.857 L 23.146,47.857 L 23.146,47.856 z" />
|
||||||
|
</g><g
|
||||||
|
style="filter:url(#filter3460)"
|
||||||
|
id="g109"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 22.213,81.018 L 23.666,76.231 C 23.666,76.231 23.743,74.036 21.849,75.041 L 21.921,76.231 L 20.291,81.018 C 20.605,81.49 21.142,81.8 21.752,81.8 L 23.515,81.8 C 22.971,81.8 22.493,81.489 22.213,81.018 z"
|
||||||
|
id="path111"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><g
|
||||||
|
style="filter:url(#filter3464)"
|
||||||
|
id="g113"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 54.079,76.23 L 54.151,75.04 C 52.89,74.329 52.333,76.23 52.333,76.23 L 53.779,81.033 C 53.498,81.496 53.023,81.8 52.485,81.8 L 54.249,81.8 C 54.853,81.8 55.386,81.496 55.701,81.033 L 54.079,76.23 z"
|
||||||
|
id="path115"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><path
|
||||||
|
d="M 24.1,48.856 C 23.693,57.45 52.262,55.434 51.971,48.856 C 42.68,48.856 33.39,48.856 24.1,48.856"
|
||||||
|
id="path122"
|
||||||
|
style="fill:url(#linearGradient2979);fill-opacity:1;filter:url(#filter3500)"
|
||||||
|
transform="matrix(1.1250094,0,0,1.7718407,-4.5001124,-41.815049)" /><g
|
||||||
|
style="filter:url(#filter3468)"
|
||||||
|
id="g126"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 59.513,81.018 L 60.966,76.231 C 60.966,76.231 61.043,74.036 59.149,75.041 L 59.221,76.231 L 57.591,81.018 C 57.905,81.49 58.442,81.8 59.052,81.8 L 60.815,81.8 C 60.271,81.8 59.792,81.489 59.513,81.018 z"
|
||||||
|
id="path128"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><g
|
||||||
|
style="filter:url(#filter3472)"
|
||||||
|
id="g130"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 91.379,76.23 L 91.451,75.04 C 90.189,74.329 89.633,76.23 89.633,76.23 L 91.078,81.033 C 90.797,81.496 90.322,81.8 89.784,81.8 L 91.548,81.8 C 92.152,81.8 92.685,81.496 93,81.033 L 91.379,76.23 z"
|
||||||
|
id="path132"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><path
|
||||||
|
d="M 61.399,48.856 C 60.992,57.45 89.56,55.434 89.269,48.856 C 79.98,48.856 70.689,48.856 61.399,48.856"
|
||||||
|
id="path139"
|
||||||
|
style="fill:url(#linearGradient2981);filter:url(#filter3496)"
|
||||||
|
transform="matrix(1.1250094,0,0,1.7718407,-4.5001124,-41.815049)" /><g
|
||||||
|
id="g143"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 15.921,43.018 L 17.374,38.231 C 17.374,38.231 17.451,36.036 15.557,37.041 L 15.629,38.231 L 14,43.018 C 14.314,43.49 14.851,43.8 15.461,43.8 L 17.224,43.8 C 16.68,43.8 16.201,43.489 15.921,43.018 z"
|
||||||
|
id="path145"
|
||||||
|
style="fill:#ffffff;filter:url(#filter3424)" />
|
||||||
|
</g><path
|
||||||
|
id="path149"
|
||||||
|
d="M 47.788,38.23 L 47.86,37.04 C 46.598,36.329 46.042,38.23 46.042,38.23 L 47.487,43.033 C 47.206,43.496 46.731,43.8 46.193,43.8 L 47.957,43.8 C 48.561,43.8 49.094,43.496 49.409,43.033 L 47.788,38.23 z"
|
||||||
|
style="fill:#ffffff;filter:url(#filter3416)"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)" /><path
|
||||||
|
d="M 17.808,10.856 C 17.401,19.45 45.969,17.434 45.678,10.856 C 36.389,10.856 27.098,10.856 17.808,10.856"
|
||||||
|
id="path156"
|
||||||
|
style="fill:url(#linearGradient3380);fill-opacity:1;filter:url(#filter3504)"
|
||||||
|
transform="matrix(1.1250094,0,0,1.7718407,-4.5001124,-17.235103)" /><g
|
||||||
|
style="filter:url(#filter3444)"
|
||||||
|
id="g160"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 53.513,43.018 L 54.966,38.231 C 54.966,38.231 55.043,36.036 53.149,37.041 L 53.221,38.231 L 51.591,43.018 C 51.905,43.49 52.442,43.8 53.052,43.8 L 54.815,43.8 C 54.271,43.8 53.792,43.489 53.513,43.018 z"
|
||||||
|
id="path162"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><g
|
||||||
|
style="filter:url(#filter3448)"
|
||||||
|
id="g164"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 85.379,38.23 L 85.451,37.04 C 84.189,36.329 83.633,38.23 83.633,38.23 L 85.078,43.033 C 84.797,43.496 84.322,43.8 83.784,43.8 L 85.548,43.8 C 86.152,43.8 86.685,43.496 87,43.033 L 85.379,38.23 z"
|
||||||
|
id="path166"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><path
|
||||||
|
d="M 55.399,10.856 C 54.992,19.45 83.56,17.434 83.269,10.856 C 73.98,10.856 64.689,10.856 55.399,10.856"
|
||||||
|
id="path173"
|
||||||
|
style="fill:url(#linearGradient2945);fill-opacity:1;filter:url(#filter3508)"
|
||||||
|
transform="matrix(1.1250094,0,0,1.7718407,-4.5001124,-17.235103)" /><g
|
||||||
|
style="filter:url(#filter3452)"
|
||||||
|
id="g177"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 90.513,43.018 L 91.966,38.231 C 91.966,38.231 92.043,36.036 90.149,37.041 L 90.221,38.231 L 88.592,43.018 C 88.905,43.49 89.442,43.8 90.053,43.8 L 91.815,43.8 C 91.271,43.8 90.793,43.489 90.513,43.018 z"
|
||||||
|
id="path179"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><g
|
||||||
|
style="filter:url(#filter3456)"
|
||||||
|
id="g181"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 122.379,38.23 L 122.451,37.04 C 121.189,36.329 120.633,38.23 120.633,38.23 L 122.078,43.033 C 121.797,43.496 121.322,43.8 120.784,43.8 L 122.548,43.8 C 123.152,43.8 123.685,43.496 124,43.033 L 122.379,38.23 z"
|
||||||
|
id="path183"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><path
|
||||||
|
d="M 92.399,10.856 C 91.992,19.45 120.56,17.434 120.269,10.856 C 110.98,10.856 101.689,10.856 92.399,10.856"
|
||||||
|
id="path190"
|
||||||
|
style="fill:url(#linearGradient3378);fill-opacity:1;filter:url(#filter3512)"
|
||||||
|
transform="matrix(1.1250094,0,0,1.7718407,-4.5001124,-17.235103)" /><g
|
||||||
|
style="filter:url(#filter3476)"
|
||||||
|
id="g194"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 96.513,81.018 L 97.966,76.231 C 97.966,76.231 98.043,74.036 96.149,75.041 L 96.221,76.231 L 94.592,81.018 C 94.905,81.49 95.442,81.8 96.053,81.8 L 97.815,81.8 C 97.271,81.8 96.793,81.489 96.513,81.018 z"
|
||||||
|
id="path196"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><g
|
||||||
|
style="filter:url(#filter3484)"
|
||||||
|
id="g198"
|
||||||
|
transform="matrix(1.1250094,0,0,1.125,-4.5001124,-11.275)">
|
||||||
|
<path
|
||||||
|
d="M 128.379,76.23 L 128.451,75.04 C 127.189,74.329 126.633,76.23 126.633,76.23 L 128.078,81.033 C 127.797,81.496 127.322,81.8 126.784,81.8 L 128.548,81.8 C 129.152,81.8 129.685,81.496 130,81.033 L 128.379,76.23 z"
|
||||||
|
id="path200"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</g><path
|
||||||
|
d="M 98.399,48.856 C 97.992,57.45 126.56,55.434 126.269,48.856 C 116.98,48.856 107.689,48.856 98.399,48.856"
|
||||||
|
id="path207"
|
||||||
|
style="fill:url(#linearGradient2983);filter:url(#filter3492)"
|
||||||
|
transform="matrix(1.1250094,0,0,1.7718407,-4.5001124,-41.815049)" /><path
|
||||||
|
style="fill:#323232"
|
||||||
|
id="path209"
|
||||||
|
d="M 21.99503,12.125 L 19.778139,23.842759 C 19.61869,24.635599 19.540614,25.268992 19.540614,25.848502 C 19.540614,27.088895 20.172912,27.749779 21.150501,27.749779 C 22.470079,27.749779 23.261827,26.799689 23.788558,23.974716 L 26.058233,12.125 L 28.723782,12.125 L 26.533281,23.632728 C 25.715142,27.960908 24.079966,30.125 20.832702,30.125 C 18.27382,30.125 16.875066,28.645985 16.875066,26.112415 C 16.875066,25.399849 16.981732,24.502542 17.166473,23.47328 L 19.330582,12.125 L 21.99503,12.125 L 21.99503,12.125 z" /><path
|
||||||
|
style="fill:#323232"
|
||||||
|
id="path211"
|
||||||
|
d="M 64.643632,12.125 L 61.198712,30.125 L 58.500414,30.125 L 61.918629,12.125 L 64.643632,12.125 L 64.643632,12.125 z" /><path
|
||||||
|
style="fill:#323232"
|
||||||
|
id="path213"
|
||||||
|
d="M 111.34148,17.759442 C 111.34148,21.280968 110.11546,26.238278 107.82102,28.532705 C 106.7515,29.602206 105.57766,30.125 104.19402,30.125 C 100.56813,30.125 100.12576,26.368704 100.12576,24.464472 C 100.12576,20.995117 101.35178,16.037807 103.77666,13.664038 C 104.79508,12.672793 105.99394,12.125 107.35038,12.125 C 110.95129,12.125 111.34148,15.62044 111.34148,17.759442 z M 105.60374,15.124819 C 103.82883,16.899712 102.83867,21.985274 102.83867,24.593812 C 102.83867,25.793739 102.94301,27.802314 104.58532,27.802314 C 105.05486,27.802314 105.4983,27.567546 105.91676,27.15018 C 107.76775,25.270946 108.60358,19.585419 108.60358,17.629015 C 108.60358,16.089978 108.47315,14.446599 106.98627,14.446599 C 106.48956,14.447686 106.0211,14.681367 105.60374,15.124819 z" /><path
|
||||||
|
style="fill:#323232"
|
||||||
|
id="path215"
|
||||||
|
d="M 30.011882,54.875 L 32.678531,54.875 L 30.223015,67.727587 C 29.431267,71.819347 27.794991,72.875 25.182225,72.875 C 24.522435,72.875 23.91543,72.768335 23.625122,72.663868 L 24.073779,70.288648 C 24.443261,70.394213 24.785251,70.420605 25.287791,70.420605 C 26.450121,70.420605 27.161593,69.681647 27.531075,67.728687 L 30.011882,54.875 z" /><path
|
||||||
|
style="fill:#323232"
|
||||||
|
id="path217"
|
||||||
|
d="M 68.668474,54.876125 L 71.338789,54.876125 L 69.683194,63.422176 L 69.763303,63.422176 C 70.350773,62.407464 70.804726,61.659781 71.285383,60.885397 L 75.156227,54.877238 L 78.146981,54.877238 L 72.512615,62.72901 L 74.782383,72.876125 L 71.978553,72.876125 L 70.428657,64.732844 L 69.148018,66.387312 L 67.895195,72.875012 L 65.25047,72.875012 L 68.668474,54.876125 z" /><path
|
||||||
|
style="fill:#323232"
|
||||||
|
id="path219"
|
||||||
|
d="M 110.29425,54.873875 L 113.0183,54.873875 L 110.02717,70.523727 L 114.67522,70.523727 L 114.22121,72.873875 L 106.87582,72.873875 L 110.29425,54.873875 z" /></g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 34 KiB |
28
recipes/escrevinhador.recipe
Normal file
28
recipes/escrevinhador.recipe
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class Escrevinhador(BasicNewsRecipe):
|
||||||
|
title = 'Blog Escrevinhador'
|
||||||
|
__author__ = 'Diniz Bortolotto'
|
||||||
|
description = 'Posts do Blog Escrevinhador'
|
||||||
|
publisher = 'Rodrigo Viana'
|
||||||
|
oldest_article = 5
|
||||||
|
max_articles_per_feed = 20
|
||||||
|
category = 'news, politics, Brazil'
|
||||||
|
language = 'pt_BR'
|
||||||
|
publication_type = 'news and politics portal'
|
||||||
|
use_embedded_content = False
|
||||||
|
no_stylesheets = True
|
||||||
|
remove_javascript = True
|
||||||
|
|
||||||
|
feeds = [(u'Blog Escrevinhador', u'http://www.rodrigovianna.com.br/feed')]
|
||||||
|
|
||||||
|
reverse_article_order = True
|
||||||
|
|
||||||
|
remove_tags_after = [dict(name='div', attrs={'class':'text'})]
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(id='header'),
|
||||||
|
dict(name='p', attrs={'class':'tags'}),
|
||||||
|
dict(name='div', attrs={'class':'sociable'})
|
||||||
|
]
|
||||||
|
|
@ -11,7 +11,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="{prefix}/static/browse/browse.css" />
|
<link rel="stylesheet" type="text/css" href="{prefix}/static/browse/browse.css" />
|
||||||
<link type="text/css" href="{prefix}/static/jquery_ui/css/humanity-custom/jquery-ui-1.8.5.custom.css" rel="stylesheet" />
|
<link type="text/css" href="{prefix}/static/jquery_ui/css/humanity-custom/jquery-ui-1.8.5.custom.css" rel="stylesheet" />
|
||||||
<link rel="stylesheet" type="text/css" href="{prefix}/static/jquery.multiselect.css" />
|
<link rel="stylesheet" type="text/css" href="{prefix}/static/jquery.multiselect.css" />
|
||||||
<link rel="apple-touch-icon" href="/static/calibre.png" />
|
<link rel="apple-touch-icon" href="{prefix}/static/calibre.png" />
|
||||||
|
|
||||||
<script type="text/javascript" src="{prefix}/static/jquery.js"></script>
|
<script type="text/javascript" src="{prefix}/static/jquery.js"></script>
|
||||||
<script type="text/javascript" src="{prefix}/static/jquery.corner.js"></script>
|
<script type="text/javascript" src="{prefix}/static/jquery.corner.js"></script>
|
||||||
|
BIN
resources/images/keyboard-prefs.png
Normal file
BIN
resources/images/keyboard-prefs.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
BIN
resources/images/mimetypes/xps.png
Executable file
BIN
resources/images/mimetypes/xps.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@ -1029,7 +1029,7 @@ class TemplateFunctions(PreferencesPlugin):
|
|||||||
category = 'Advanced'
|
category = 'Advanced'
|
||||||
gui_category = _('Advanced')
|
gui_category = _('Advanced')
|
||||||
category_order = 5
|
category_order = 5
|
||||||
name_order = 4
|
name_order = 5
|
||||||
config_widget = 'calibre.gui2.preferences.template_functions'
|
config_widget = 'calibre.gui2.preferences.template_functions'
|
||||||
description = _('Create your own template functions')
|
description = _('Create your own template functions')
|
||||||
|
|
||||||
@ -1092,6 +1092,17 @@ class Tweaks(PreferencesPlugin):
|
|||||||
config_widget = 'calibre.gui2.preferences.tweaks'
|
config_widget = 'calibre.gui2.preferences.tweaks'
|
||||||
description = _('Fine tune how calibre behaves in various contexts')
|
description = _('Fine tune how calibre behaves in various contexts')
|
||||||
|
|
||||||
|
class Keyboard(PreferencesPlugin):
|
||||||
|
name = 'Keyboard'
|
||||||
|
icon = I('keyboard-prefs.png')
|
||||||
|
gui_name = _('Keyboard')
|
||||||
|
category = 'Advanced'
|
||||||
|
gui_category = _('Advanced')
|
||||||
|
category_order = 5
|
||||||
|
name_order = 4
|
||||||
|
config_widget = 'calibre.gui2.preferences.keyboard'
|
||||||
|
description = _('Customize the keyboard shortcuts used by calibre')
|
||||||
|
|
||||||
class Misc(PreferencesPlugin):
|
class Misc(PreferencesPlugin):
|
||||||
name = 'Misc'
|
name = 'Misc'
|
||||||
icon = I('exec.png')
|
icon = I('exec.png')
|
||||||
@ -1106,7 +1117,7 @@ class Misc(PreferencesPlugin):
|
|||||||
plugins += [LookAndFeel, Behavior, Columns, Toolbar, Search, InputOptions,
|
plugins += [LookAndFeel, Behavior, Columns, Toolbar, Search, InputOptions,
|
||||||
CommonOptions, OutputOptions, Adding, Saving, Sending, Plugboard,
|
CommonOptions, OutputOptions, Adding, Saving, Sending, Plugboard,
|
||||||
Email, Server, Plugins, Tweaks, Misc, TemplateFunctions,
|
Email, Server, Plugins, Tweaks, Misc, TemplateFunctions,
|
||||||
MetadataSources]
|
MetadataSources, Keyboard]
|
||||||
|
|
||||||
#}}}
|
#}}}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class FOLDER_DEVICE_FOR_CONFIG(USBMS):
|
|||||||
description = _('Use an arbitrary folder as a device.')
|
description = _('Use an arbitrary folder as a device.')
|
||||||
author = 'John Schember/Charles Haley'
|
author = 'John Schember/Charles Haley'
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
FORMATS = BOOK_EXTENSIONS
|
FORMATS = list(BOOK_EXTENSIONS)
|
||||||
|
|
||||||
VENDOR_ID = [0xffff]
|
VENDOR_ID = [0xffff]
|
||||||
PRODUCT_ID = [0xffff]
|
PRODUCT_ID = [0xffff]
|
||||||
|
@ -169,7 +169,9 @@ def _config(): # {{{
|
|||||||
c.add_opt('scheduler_search_history', default=[],
|
c.add_opt('scheduler_search_history', default=[],
|
||||||
help='Search history for the recipe scheduler')
|
help='Search history for the recipe scheduler')
|
||||||
c.add_opt('plugin_search_history', default=[],
|
c.add_opt('plugin_search_history', default=[],
|
||||||
help='Search history for the recipe scheduler')
|
help='Search history for the plugin preferences')
|
||||||
|
c.add_opt('shortcuts_search_history', default=[],
|
||||||
|
help='Search history for the keyboard preferences')
|
||||||
c.add_opt('worker_limit', default=6,
|
c.add_opt('worker_limit', default=6,
|
||||||
help=_(
|
help=_(
|
||||||
'Maximum number of simultaneous conversion/news download jobs. '
|
'Maximum number of simultaneous conversion/news download jobs. '
|
||||||
@ -425,6 +427,8 @@ class FileIconProvider(QFileIconProvider):
|
|||||||
'snb' : 'snb',
|
'snb' : 'snb',
|
||||||
'djv' : 'djvu',
|
'djv' : 'djvu',
|
||||||
'djvu' : 'djvu',
|
'djvu' : 'djvu',
|
||||||
|
'xps' : 'xps',
|
||||||
|
'oxps' : 'xps',
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -8,9 +8,13 @@ __docformat__ = 'restructuredtext en'
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from PyQt4.Qt import QToolButton, QAction, QIcon, QObject, QMenu
|
from PyQt4.Qt import (QToolButton, QAction, QIcon, QObject, QMenu,
|
||||||
|
QKeySequence)
|
||||||
|
|
||||||
|
from calibre import prints
|
||||||
from calibre.gui2 import Dispatcher
|
from calibre.gui2 import Dispatcher
|
||||||
|
from calibre.gui2.keyboard import NameConflict
|
||||||
|
|
||||||
|
|
||||||
class InterfaceAction(QObject):
|
class InterfaceAction(QObject):
|
||||||
|
|
||||||
@ -108,7 +112,10 @@ class InterfaceAction(QObject):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_name(self):
|
def unique_name(self):
|
||||||
return u'%s(%s)'%(self.__class__.__name__, self.name)
|
bn = self.__class__.__name__
|
||||||
|
if getattr(self.interface_action_base_plugin, 'name'):
|
||||||
|
bn = self.interface_action_base_plugin.name
|
||||||
|
return u'Interface Action: %s (%s)'%(bn, self.name)
|
||||||
|
|
||||||
def create_action(self, spec=None, attr='qaction'):
|
def create_action(self, spec=None, attr='qaction'):
|
||||||
if spec is None:
|
if spec is None:
|
||||||
@ -129,7 +136,6 @@ class InterfaceAction(QObject):
|
|||||||
a.setToolTip(text)
|
a.setToolTip(text)
|
||||||
a.setStatusTip(text)
|
a.setStatusTip(text)
|
||||||
a.setWhatsThis(text)
|
a.setWhatsThis(text)
|
||||||
keys = ()
|
|
||||||
shortcut_action = action
|
shortcut_action = action
|
||||||
desc = tooltip if tooltip else None
|
desc = tooltip if tooltip else None
|
||||||
if attr == 'qaction':
|
if attr == 'qaction':
|
||||||
@ -138,9 +144,22 @@ class InterfaceAction(QObject):
|
|||||||
keys = ((shortcut,) if isinstance(shortcut, basestring) else
|
keys = ((shortcut,) if isinstance(shortcut, basestring) else
|
||||||
tuple(shortcut))
|
tuple(shortcut))
|
||||||
|
|
||||||
self.gui.keyboard.register_shortcut(self.unique_name + ' - ' + attr,
|
if spec[0] and not (attr=='qaction' and self.popup_type ==
|
||||||
unicode(shortcut_action.text()), default_keys=keys,
|
QToolButton.InstantPopup):
|
||||||
action=shortcut_action, description=desc)
|
try:
|
||||||
|
self.gui.keyboard.register_shortcut(self.unique_name + ' - ' + attr,
|
||||||
|
unicode(spec[0]), default_keys=keys,
|
||||||
|
action=shortcut_action, description=desc,
|
||||||
|
group=self.action_spec[0])
|
||||||
|
except NameConflict as e:
|
||||||
|
try:
|
||||||
|
prints(unicode(e))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
shortcut_action.setShortcuts([QKeySequence(key,
|
||||||
|
QKeySequence.PortableText) for key in keys])
|
||||||
|
|
||||||
|
|
||||||
if attr is not None:
|
if attr is not None:
|
||||||
setattr(self, attr, action)
|
setattr(self, attr, action)
|
||||||
if attr == 'qaction' and self.action_add_menu:
|
if attr == 'qaction' and self.action_add_menu:
|
||||||
@ -166,10 +185,11 @@ class InterfaceAction(QObject):
|
|||||||
ac.setToolTip(description)
|
ac.setToolTip(description)
|
||||||
ac.setStatusTip(description)
|
ac.setStatusTip(description)
|
||||||
ac.setWhatsThis(description)
|
ac.setWhatsThis(description)
|
||||||
|
|
||||||
if shortcut is not False:
|
if shortcut is not False:
|
||||||
self.gui.keyboard.register_shortcut(unique_name,
|
self.gui.keyboard.register_shortcut(unique_name,
|
||||||
unicode(text), default_keys=keys,
|
unicode(text), default_keys=keys,
|
||||||
action=ac, description=description)
|
action=ac, description=description, group=self.action_spec[0])
|
||||||
if triggered is not None:
|
if triggered is not None:
|
||||||
ac.triggered.connect(triggered)
|
ac.triggered.connect(triggered)
|
||||||
return ac
|
return ac
|
||||||
|
@ -8,13 +8,14 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import os
|
import os
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from PyQt4.Qt import QMenu, Qt, QInputDialog, QToolButton
|
from PyQt4.Qt import (QMenu, Qt, QInputDialog, QToolButton, QDialog,
|
||||||
|
QDialogButtonBox, QGridLayout, QLabel, QLineEdit, QIcon, QSize)
|
||||||
|
|
||||||
from calibre import isbytestring
|
from calibre import isbytestring
|
||||||
from calibre.constants import filesystem_encoding, iswindows
|
from calibre.constants import filesystem_encoding, iswindows
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.gui2 import (gprefs, warning_dialog, Dispatcher, error_dialog,
|
from calibre.gui2 import (gprefs, warning_dialog, Dispatcher, error_dialog,
|
||||||
question_dialog, info_dialog, open_local_file)
|
question_dialog, info_dialog, open_local_file, choose_dir)
|
||||||
from calibre.library.database2 import LibraryDatabase2
|
from calibre.library.database2 import LibraryDatabase2
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
|
|
||||||
@ -76,16 +77,73 @@ class LibraryUsageStats(object): # {{{
|
|||||||
self.write_stats()
|
self.write_stats()
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
class MovedDialog(QDialog): # {{{
|
||||||
|
|
||||||
|
def __init__(self, stats, location, parent=None):
|
||||||
|
QDialog.__init__(self, parent)
|
||||||
|
self.setWindowTitle(_('No library found'))
|
||||||
|
self._l = l = QGridLayout(self)
|
||||||
|
self.setLayout(l)
|
||||||
|
self.stats, self.location = stats, location
|
||||||
|
|
||||||
|
loc = self.oldloc = location.replace('/', os.sep)
|
||||||
|
self.header = QLabel(_('No existing calibre library was found at %s. '
|
||||||
|
'If the library was moved, select its new location below. '
|
||||||
|
'Otherwise calibre will forget this library.')%loc)
|
||||||
|
self.header.setWordWrap(True)
|
||||||
|
ncols = 2
|
||||||
|
l.addWidget(self.header, 0, 0, 1, ncols)
|
||||||
|
self.cl = QLabel('<br><b>'+_('New location of this library:'))
|
||||||
|
l.addWidget(self.cl, 1, 0, 1, ncols)
|
||||||
|
self.loc = QLineEdit(loc, self)
|
||||||
|
l.addWidget(self.loc, 2, 0, 1, 1)
|
||||||
|
self.cd = QToolButton(self)
|
||||||
|
self.cd.setIcon(QIcon(I('document_open.png')))
|
||||||
|
self.cd.clicked.connect(self.choose_dir)
|
||||||
|
l.addWidget(self.cd, 2, 1, 1, 1)
|
||||||
|
self.bb = QDialogButtonBox(self)
|
||||||
|
b = self.bb.addButton(_('Library moved'), self.bb.AcceptRole)
|
||||||
|
b.setIcon(QIcon(I('ok.png')))
|
||||||
|
b = self.bb.addButton(_('Forget library'), self.bb.RejectRole)
|
||||||
|
b.setIcon(QIcon(I('edit-clear.png')))
|
||||||
|
self.bb.accepted.connect(self.accept)
|
||||||
|
self.bb.rejected.connect(self.reject)
|
||||||
|
l.addWidget(self.bb, 3, 0, 1, ncols)
|
||||||
|
self.resize(self.sizeHint() + QSize(100, 50))
|
||||||
|
|
||||||
|
def choose_dir(self):
|
||||||
|
d = choose_dir(self, 'library moved choose new loc',
|
||||||
|
_('New library location'), default_dir=self.oldloc)
|
||||||
|
if d is not None:
|
||||||
|
self.loc.setText(d)
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
self.stats.remove(self.location)
|
||||||
|
QDialog.reject(self)
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
newloc = unicode(self.loc.text())
|
||||||
|
if not LibraryDatabase2.exists_at(newloc):
|
||||||
|
error_dialog(self, _('No library found'),
|
||||||
|
_('No existing calibre library found at %s')%newloc,
|
||||||
|
show=True)
|
||||||
|
return
|
||||||
|
self.stats.rename(self.location, newloc)
|
||||||
|
self.newloc = newloc
|
||||||
|
QDialog.accept(self)
|
||||||
|
# }}}
|
||||||
|
|
||||||
class ChooseLibraryAction(InterfaceAction):
|
class ChooseLibraryAction(InterfaceAction):
|
||||||
|
|
||||||
name = 'Choose Library'
|
name = 'Choose Library'
|
||||||
action_spec = (_('%d books'), 'lt.png',
|
action_spec = (_('Choose Library'), 'lt.png',
|
||||||
_('Choose calibre library to work with'), None)
|
_('Choose calibre library to work with'), None)
|
||||||
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
|
||||||
action_add_menu = True
|
action_add_menu = True
|
||||||
action_menu_clone_qaction = _('Switch/create library...')
|
action_menu_clone_qaction = _('Switch/create library...')
|
||||||
|
|
||||||
def genesis(self):
|
def genesis(self):
|
||||||
|
self.base_text = _('%d books')
|
||||||
self.count_changed(0)
|
self.count_changed(0)
|
||||||
self.qaction.triggered.connect(self.choose_library,
|
self.qaction.triggered.connect(self.choose_library,
|
||||||
type=Qt.QueuedConnection)
|
type=Qt.QueuedConnection)
|
||||||
@ -338,14 +396,14 @@ class ChooseLibraryAction(InterfaceAction):
|
|||||||
loc = location.replace('/', os.sep)
|
loc = location.replace('/', os.sep)
|
||||||
exists = self.gui.library_view.model().db.exists_at(loc)
|
exists = self.gui.library_view.model().db.exists_at(loc)
|
||||||
if not exists:
|
if not exists:
|
||||||
warning_dialog(self.gui, _('No library found'),
|
d = MovedDialog(self.stats, location, self.gui)
|
||||||
_('No existing calibre library was found at %s.'
|
ret = d.exec_()
|
||||||
' It will be removed from the list of known'
|
|
||||||
' libraries.')%loc, show=True)
|
|
||||||
self.stats.remove(location)
|
|
||||||
self.build_menus()
|
self.build_menus()
|
||||||
self.gui.iactions['Copy To Library'].build_menus()
|
self.gui.iactions['Copy To Library'].build_menus()
|
||||||
return
|
if ret == d.Accepted:
|
||||||
|
loc = d.newloc.replace('/', os.sep)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
prefs['library_path'] = loc
|
prefs['library_path'] = loc
|
||||||
#from calibre.utils.mem import memory
|
#from calibre.utils.mem import memory
|
||||||
@ -376,7 +434,7 @@ class ChooseLibraryAction(InterfaceAction):
|
|||||||
self.switch_requested(self.qs_locations[idx])
|
self.switch_requested(self.qs_locations[idx])
|
||||||
|
|
||||||
def count_changed(self, new_count):
|
def count_changed(self, new_count):
|
||||||
text = self.action_spec[0]%new_count
|
text = self.base_text%new_count
|
||||||
a = self.qaction
|
a = self.qaction
|
||||||
a.setText(text)
|
a.setText(text)
|
||||||
tooltip = self.action_spec[2] + '\n\n' + text
|
tooltip = self.action_spec[2] + '\n\n' + text
|
||||||
|
@ -12,7 +12,7 @@ from threading import Thread
|
|||||||
from PyQt4.Qt import QToolButton
|
from PyQt4.Qt import QToolButton
|
||||||
|
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
from calibre.gui2 import error_dialog, Dispatcher, warning_dialog
|
from calibre.gui2 import error_dialog, Dispatcher, warning_dialog, gprefs
|
||||||
from calibre.gui2.dialogs.progress import ProgressDialog
|
from calibre.gui2.dialogs.progress import ProgressDialog
|
||||||
from calibre.utils.config import prefs, tweaks
|
from calibre.utils.config import prefs, tweaks
|
||||||
|
|
||||||
@ -65,14 +65,37 @@ class Worker(Thread): # {{{
|
|||||||
as_path=True)
|
as_path=True)
|
||||||
if p:
|
if p:
|
||||||
paths.append(p)
|
paths.append(p)
|
||||||
added = False
|
automerged = False
|
||||||
if prefs['add_formats_to_existing']:
|
if prefs['add_formats_to_existing']:
|
||||||
identical_book_list = newdb.find_identical_books(mi)
|
identical_book_list = newdb.find_identical_books(mi)
|
||||||
if identical_book_list: # books with same author and nearly same title exist in newdb
|
if identical_book_list: # books with same author and nearly same title exist in newdb
|
||||||
added = True
|
automerged = True
|
||||||
|
seen_fmts = set()
|
||||||
for identical_book in identical_book_list:
|
for identical_book in identical_book_list:
|
||||||
self.add_formats(identical_book, paths, newdb, replace=False)
|
ib_fmts = newdb.formats(identical_book, index_is_id=True)
|
||||||
if not added:
|
if ib_fmts:
|
||||||
|
seen_fmts |= set(ib_fmts.split(','))
|
||||||
|
replace = gprefs['automerge'] == 'overwrite'
|
||||||
|
self.add_formats(identical_book, paths, newdb,
|
||||||
|
replace=replace)
|
||||||
|
|
||||||
|
if gprefs['automerge'] == 'new record':
|
||||||
|
incoming_fmts = \
|
||||||
|
set([os.path.splitext(path)[-1].replace('.',
|
||||||
|
'').upper() for path in paths])
|
||||||
|
|
||||||
|
if incoming_fmts.intersection(seen_fmts):
|
||||||
|
# There was at least one duplicate format
|
||||||
|
# so create a new record and put the
|
||||||
|
# incoming formats into it
|
||||||
|
# We should arguably put only the duplicate
|
||||||
|
# formats, but no real harm is done by having
|
||||||
|
# all formats
|
||||||
|
newdb.import_book(mi, paths, notify=False, import_hooks=False,
|
||||||
|
apply_import_tags=tweaks['add_new_book_tags_when_importing_books'],
|
||||||
|
preserve_uuid=False)
|
||||||
|
|
||||||
|
if not automerged:
|
||||||
newdb.import_book(mi, paths, notify=False, import_hooks=False,
|
newdb.import_book(mi, paths, notify=False, import_hooks=False,
|
||||||
apply_import_tags=tweaks['add_new_book_tags_when_importing_books'],
|
apply_import_tags=tweaks['add_new_book_tags_when_importing_books'],
|
||||||
preserve_uuid=self.delete_after)
|
preserve_uuid=self.delete_after)
|
||||||
|
@ -63,11 +63,15 @@ class ShareConnMenu(QMenu): # {{{
|
|||||||
if hasattr(parent, 'keyboard'):
|
if hasattr(parent, 'keyboard'):
|
||||||
r = parent.keyboard.register_shortcut
|
r = parent.keyboard.register_shortcut
|
||||||
prefix = 'Share/Connect Menu '
|
prefix = 'Share/Connect Menu '
|
||||||
|
gr = ConnectShareAction.action_spec[0]
|
||||||
for attr in ('folder', 'bambook', 'itunes'):
|
for attr in ('folder', 'bambook', 'itunes'):
|
||||||
if not (iswindows or isosx) and attr == 'itunes':
|
if not (iswindows or isosx) and attr == 'itunes':
|
||||||
continue
|
continue
|
||||||
ac = getattr(self, 'connect_to_%s_action'%attr)
|
ac = getattr(self, 'connect_to_%s_action'%attr)
|
||||||
r(prefix + attr, unicode(ac.text()), action=ac)
|
r(prefix + attr, unicode(ac.text()), action=ac,
|
||||||
|
group=gr)
|
||||||
|
r(prefix+' content server', _('Start/stop content server'),
|
||||||
|
action=self.toggle_server_action, group=gr)
|
||||||
|
|
||||||
def server_state_changed(self, running):
|
def server_state_changed(self, running):
|
||||||
text = _('Start Content Server')
|
text = _('Start Content Server')
|
||||||
|
@ -11,7 +11,7 @@ from calibre.gui2.actions import InterfaceAction
|
|||||||
class RestartAction(InterfaceAction):
|
class RestartAction(InterfaceAction):
|
||||||
|
|
||||||
name = 'Restart'
|
name = 'Restart'
|
||||||
action_spec = (_('&Restart'), None, None, _('Ctrl+R'))
|
action_spec = (_('Restart'), None, None, _('Ctrl+R'))
|
||||||
|
|
||||||
def genesis(self):
|
def genesis(self):
|
||||||
self.qaction.triggered.connect(self.restart)
|
self.qaction.triggered.connect(self.restart)
|
||||||
|
@ -193,6 +193,7 @@ class SchedulerDialog(QDialog, Ui_Dialog):
|
|||||||
self.recipe_model = recipe_model
|
self.recipe_model = recipe_model
|
||||||
self.recipe_model.do_refresh()
|
self.recipe_model.do_refresh()
|
||||||
self.count_label.setText(
|
self.count_label.setText(
|
||||||
|
# NOTE: Number of news sources
|
||||||
_('%s news sources') %
|
_('%s news sources') %
|
||||||
self.recipe_model.showing_count)
|
self.recipe_model.showing_count)
|
||||||
|
|
||||||
|
@ -8,32 +8,97 @@ __copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from PyQt4.Qt import (QObject, QKeySequence)
|
from PyQt4.Qt import (QObject, QKeySequence, QAbstractItemModel, QModelIndex,
|
||||||
|
Qt, QStyledItemDelegate, QTextDocument, QStyle, pyqtSignal, QFrame,
|
||||||
|
QApplication, QSize, QRectF, QWidget, QTreeView,
|
||||||
|
QGridLayout, QLabel, QRadioButton, QPushButton, QToolButton, QIcon)
|
||||||
|
|
||||||
from calibre.utils.config import JSONConfig
|
from calibre.utils.config import JSONConfig
|
||||||
from calibre.constants import DEBUG
|
from calibre.constants import DEBUG
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
|
from calibre.utils.icu import sort_key, lower
|
||||||
|
from calibre.gui2 import NONE, error_dialog, info_dialog
|
||||||
|
from calibre.utils.search_query_parser import SearchQueryParser
|
||||||
|
from calibre.gui2.search_box import SearchBox2
|
||||||
|
|
||||||
|
ROOT = QModelIndex()
|
||||||
|
|
||||||
class NameConflict(ValueError):
|
class NameConflict(ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Manager(QObject):
|
def finalize(shortcuts, custom_keys_map={}): # {{{
|
||||||
|
'''
|
||||||
|
Resolve conflicts and assign keys to every action in shorcuts, which must
|
||||||
|
be a OrderedDict. User specified mappings of unique names to keys (as a
|
||||||
|
list of strings) should be passed in in custom_keys_map. Return a mapping
|
||||||
|
of unique names to resolved keys. Also sets the set_to_defaul member
|
||||||
|
correctly for each shortcut.
|
||||||
|
'''
|
||||||
|
seen, keys_map = {}, {}
|
||||||
|
for unique_name, shortcut in shortcuts.iteritems():
|
||||||
|
custom_keys = custom_keys_map.get(unique_name, None)
|
||||||
|
if custom_keys is None:
|
||||||
|
candidates = shortcut['default_keys']
|
||||||
|
shortcut['set_to_default'] = True
|
||||||
|
else:
|
||||||
|
candidates = custom_keys
|
||||||
|
shortcut['set_to_default'] = False
|
||||||
|
keys = []
|
||||||
|
for x in candidates:
|
||||||
|
ks = QKeySequence(x, QKeySequence.PortableText)
|
||||||
|
x = unicode(ks.toString(QKeySequence.PortableText))
|
||||||
|
if x in seen:
|
||||||
|
if DEBUG:
|
||||||
|
prints('Key %r for shortcut %s is already used by'
|
||||||
|
' %s, ignoring'%(x, shortcut['name'], seen[x]['name']))
|
||||||
|
continue
|
||||||
|
seen[x] = shortcut
|
||||||
|
keys.append(ks)
|
||||||
|
keys = tuple(keys)
|
||||||
|
#print (111111, unique_name, candidates, keys)
|
||||||
|
|
||||||
|
keys_map[unique_name] = keys
|
||||||
|
ac = shortcut['action']
|
||||||
|
if ac is not None:
|
||||||
|
ac.setShortcuts(list(keys))
|
||||||
|
|
||||||
|
return keys_map
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class Manager(QObject): # {{{
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QObject.__init__(self, parent)
|
QObject.__init__(self, parent)
|
||||||
|
|
||||||
self.config = JSONConfig('shortcuts/main')
|
self.config = JSONConfig('shortcuts/main')
|
||||||
self.custom_keys_map = {}
|
|
||||||
self.shortcuts = OrderedDict()
|
self.shortcuts = OrderedDict()
|
||||||
self.keys_map = {}
|
self.keys_map = {}
|
||||||
|
self.groups = {}
|
||||||
for unique_name, keys in self.config.get(
|
|
||||||
'map', {}).iteritems():
|
|
||||||
self.custom_keys_map[unique_name] = tuple(keys)
|
|
||||||
|
|
||||||
def register_shortcut(self, unique_name, name, default_keys=(),
|
def register_shortcut(self, unique_name, name, default_keys=(),
|
||||||
description=None, action=None):
|
description=None, action=None, group=None):
|
||||||
|
'''
|
||||||
|
Register a shortcut with calibre. calibre will manage the shortcut,
|
||||||
|
automatically resolving conflicts and allowing the user to customize
|
||||||
|
it.
|
||||||
|
|
||||||
|
:param unique_name: A string that uniquely identifies this shortcut
|
||||||
|
:param name: A user visible name describing the action performed by
|
||||||
|
this shortcut
|
||||||
|
:param default_keys: A tuple of keys that trigger this shortcut. Each
|
||||||
|
key must be a string. For example: ('Ctrl+A', 'Alt+B', 'C',
|
||||||
|
'Shift+Meta+D'). These keys will be assigned to the
|
||||||
|
shortcut unless there is a conflict.
|
||||||
|
:param action: A QAction object. The shortcut will cause this QAction
|
||||||
|
to be triggered. Connect to its triggered signal in your code to
|
||||||
|
respond to the shortcut.
|
||||||
|
:param group: A string describing what "group" this shortcut belongs
|
||||||
|
to. This is used to organize the list of shortcuts when the user is
|
||||||
|
customizing them.
|
||||||
|
'''
|
||||||
if unique_name in self.shortcuts:
|
if unique_name in self.shortcuts:
|
||||||
name = self.shortcuts[unique_name]['name']
|
name = self.shortcuts[unique_name]['name']
|
||||||
raise NameConflict('Shortcut for %r already registered by %s'%(
|
raise NameConflict('Shortcut for %r already registered by %s'%(
|
||||||
@ -41,31 +106,517 @@ class Manager(QObject):
|
|||||||
shortcut = {'name':name, 'desc':description, 'action': action,
|
shortcut = {'name':name, 'desc':description, 'action': action,
|
||||||
'default_keys':tuple(default_keys)}
|
'default_keys':tuple(default_keys)}
|
||||||
self.shortcuts[unique_name] = shortcut
|
self.shortcuts[unique_name] = shortcut
|
||||||
|
group = group if group else _('Miscellaneous')
|
||||||
|
self.groups[group] = self.groups.get(group, []) + [unique_name]
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
seen = {}
|
custom_keys_map = {un:tuple(keys) for un, keys in self.config.get(
|
||||||
for unique_name, shortcut in self.shortcuts.iteritems():
|
'map', {}).iteritems()}
|
||||||
custom_keys = self.custom_keys_map.get(unique_name, None)
|
self.keys_map = finalize(self.shortcuts, custom_keys_map=custom_keys_map)
|
||||||
if custom_keys is None:
|
|
||||||
candidates = shortcut['default_keys']
|
# }}}
|
||||||
|
|
||||||
|
# Model {{{
|
||||||
|
|
||||||
|
class Node(object):
|
||||||
|
|
||||||
|
def __init__(self, group_map, shortcut_map, name=None, shortcut=None):
|
||||||
|
self.data = name if name is not None else shortcut
|
||||||
|
self.is_shortcut = shortcut is not None
|
||||||
|
self.children = []
|
||||||
|
if name is not None:
|
||||||
|
self.children = [Node(None, None, shortcut=shortcut_map[uname])
|
||||||
|
for uname in group_map[name]]
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.children)
|
||||||
|
|
||||||
|
def __getitem__(self, row):
|
||||||
|
return self.children[row]
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for child in self.children:
|
||||||
|
yield child
|
||||||
|
|
||||||
|
class ConfigModel(QAbstractItemModel, SearchQueryParser):
|
||||||
|
|
||||||
|
def __init__(self, keyboard, parent=None):
|
||||||
|
QAbstractItemModel.__init__(self, parent)
|
||||||
|
SearchQueryParser.__init__(self, ['all'])
|
||||||
|
|
||||||
|
self.keyboard = keyboard
|
||||||
|
groups = sorted(keyboard.groups, key=sort_key)
|
||||||
|
shortcut_map = {k:v.copy() for k, v in
|
||||||
|
self.keyboard.shortcuts.iteritems()}
|
||||||
|
for un, s in shortcut_map.iteritems():
|
||||||
|
s['keys'] = tuple(self.keyboard.keys_map[un])
|
||||||
|
s['unique_name'] = un
|
||||||
|
s['group'] = [g for g, names in self.keyboard.groups.iteritems() if un in
|
||||||
|
names][0]
|
||||||
|
|
||||||
|
group_map = {group:sorted(names, key=lambda x:
|
||||||
|
sort_key(shortcut_map[x]['name'])) for group, names in
|
||||||
|
self.keyboard.groups.iteritems()}
|
||||||
|
|
||||||
|
self.data = [Node(group_map, shortcut_map, group) for group in groups]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_shortcuts(self):
|
||||||
|
for group in self.data:
|
||||||
|
for sc in group:
|
||||||
|
yield sc
|
||||||
|
|
||||||
|
def rowCount(self, parent=ROOT):
|
||||||
|
ip = parent.internalPointer()
|
||||||
|
if ip is None:
|
||||||
|
return len(self.data)
|
||||||
|
return len(ip)
|
||||||
|
|
||||||
|
def columnCount(self, parent=ROOT):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def index(self, row, column, parent=ROOT):
|
||||||
|
ip = parent.internalPointer()
|
||||||
|
if ip is None:
|
||||||
|
ip = self.data
|
||||||
|
try:
|
||||||
|
return self.createIndex(row, column, ip[row])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return ROOT
|
||||||
|
|
||||||
|
def parent(self, index):
|
||||||
|
ip = index.internalPointer()
|
||||||
|
if ip is None or not ip.is_shortcut:
|
||||||
|
return ROOT
|
||||||
|
group = ip.data['group']
|
||||||
|
for i, g in enumerate(self.data):
|
||||||
|
if g.data == group:
|
||||||
|
return self.index(i, 0)
|
||||||
|
return ROOT
|
||||||
|
|
||||||
|
def data(self, index, role=Qt.DisplayRole):
|
||||||
|
ip = index.internalPointer()
|
||||||
|
if ip is not None and role == Qt.UserRole:
|
||||||
|
return ip
|
||||||
|
return NONE
|
||||||
|
|
||||||
|
def flags(self, index):
|
||||||
|
ans = QAbstractItemModel.flags(self, index)
|
||||||
|
ip = index.internalPointer()
|
||||||
|
if getattr(ip, 'is_shortcut', False):
|
||||||
|
ans |= Qt.ItemIsEditable
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def restore_defaults(self):
|
||||||
|
shortcut_map = {}
|
||||||
|
for node in self.all_shortcuts:
|
||||||
|
sc = node.data
|
||||||
|
shortcut_map[sc['unique_name']] = sc
|
||||||
|
shortcuts = OrderedDict([(un, shortcut_map[un]) for un in
|
||||||
|
self.keyboard.shortcuts])
|
||||||
|
keys_map = finalize(shortcuts)
|
||||||
|
for node in self.all_shortcuts:
|
||||||
|
s = node.data
|
||||||
|
s['keys'] = tuple(keys_map[s['unique_name']])
|
||||||
|
for r in xrange(self.rowCount()):
|
||||||
|
group = self.index(r, 0)
|
||||||
|
num = self.rowCount(group)
|
||||||
|
if num > 0:
|
||||||
|
self.dataChanged.emit(self.index(0, 0, group),
|
||||||
|
self.index(num-1, 0, group))
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
kmap = {}
|
||||||
|
for node in self.all_shortcuts:
|
||||||
|
sc = node.data
|
||||||
|
if sc['set_to_default']: continue
|
||||||
|
keys = [unicode(k.toString(k.PortableText)) for k in sc['keys']]
|
||||||
|
kmap[sc['unique_name']] = keys
|
||||||
|
self.keyboard.config['map'] = kmap
|
||||||
|
|
||||||
|
def universal_set(self):
|
||||||
|
ans = set()
|
||||||
|
for i, group in enumerate(self.data):
|
||||||
|
ans.add((i, -1))
|
||||||
|
for j, sc in enumerate(group.children):
|
||||||
|
ans.add((i, j))
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def get_matches(self, location, query, candidates=None):
|
||||||
|
if candidates is None:
|
||||||
|
candidates = self.universal_set()
|
||||||
|
ans = set([])
|
||||||
|
if not query:
|
||||||
|
return ans
|
||||||
|
query = lower(query)
|
||||||
|
for c, p in candidates:
|
||||||
|
if p < 0:
|
||||||
|
if query in lower(self.data[c].data):
|
||||||
|
ans.add((c, p))
|
||||||
else:
|
else:
|
||||||
candidates = custom_keys
|
try:
|
||||||
keys = []
|
sc = self.data[c].children[p].data
|
||||||
for x in candidates:
|
except:
|
||||||
ks = QKeySequence(x, QKeySequence.PortableText)
|
|
||||||
x = unicode(ks.toString(QKeySequence.PortableText))
|
|
||||||
if x in seen:
|
|
||||||
if DEBUG:
|
|
||||||
prints('Key %r for shortcut %s is already used by'
|
|
||||||
' %s, ignoring'%(x, shortcut['name'], seen[x]['name']))
|
|
||||||
continue
|
continue
|
||||||
seen[x] = shortcut
|
if query in lower(sc['name']):
|
||||||
keys.append(ks)
|
ans.add((c, p))
|
||||||
keys = tuple(keys)
|
return ans
|
||||||
#print (111111, unique_name, candidates, keys)
|
|
||||||
|
|
||||||
self.keys_map[unique_name] = keys
|
def find(self, query):
|
||||||
ac = shortcut['action']
|
query = query.strip()
|
||||||
if ac is not None:
|
if not query:
|
||||||
ac.setShortcuts(list(keys))
|
return ROOT
|
||||||
|
matches = self.parse(query)
|
||||||
|
if not matches:
|
||||||
|
return ROOT
|
||||||
|
matches = list(sorted(matches))
|
||||||
|
c, p = matches[0]
|
||||||
|
cat_idx = self.index(c, 0)
|
||||||
|
if p == -1:
|
||||||
|
return cat_idx
|
||||||
|
return self.index(p, 0, cat_idx)
|
||||||
|
|
||||||
|
def find_next(self, idx, query, backwards=False):
|
||||||
|
query = query.strip()
|
||||||
|
if not query:
|
||||||
|
return idx
|
||||||
|
matches = self.parse(query)
|
||||||
|
if not matches:
|
||||||
|
return idx
|
||||||
|
if idx.parent().isValid():
|
||||||
|
loc = (idx.parent().row(), idx.row())
|
||||||
|
else:
|
||||||
|
loc = (idx.row(), -1)
|
||||||
|
if loc not in matches:
|
||||||
|
return self.find(query)
|
||||||
|
if len(matches) == 1:
|
||||||
|
return ROOT
|
||||||
|
matches = list(sorted(matches))
|
||||||
|
i = matches.index(loc)
|
||||||
|
if backwards:
|
||||||
|
ans = i - 1 if i - 1 >= 0 else len(matches)-1
|
||||||
|
else:
|
||||||
|
ans = i + 1 if i + 1 < len(matches) else 0
|
||||||
|
|
||||||
|
ans = matches[ans]
|
||||||
|
|
||||||
|
return (self.index(ans[0], 0) if ans[1] < 0 else
|
||||||
|
self.index(ans[1], 0, self.index(ans[0], 0)))
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class Editor(QFrame): # {{{
|
||||||
|
|
||||||
|
editing_done = pyqtSignal(object)
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QFrame.__init__(self, parent)
|
||||||
|
self.setFocusPolicy(Qt.StrongFocus)
|
||||||
|
self.setAutoFillBackground(True)
|
||||||
|
self.capture = 0
|
||||||
|
|
||||||
|
self.setFrameShape(self.StyledPanel)
|
||||||
|
self.setFrameShadow(self.Raised)
|
||||||
|
self._layout = l = QGridLayout(self)
|
||||||
|
self.setLayout(l)
|
||||||
|
|
||||||
|
self.header = QLabel('')
|
||||||
|
l.addWidget(self.header, 0, 0, 1, 2)
|
||||||
|
|
||||||
|
self.use_default = QRadioButton('')
|
||||||
|
self.use_custom = QRadioButton(_('Custom'))
|
||||||
|
l.addWidget(self.use_default, 1, 0, 1, 3)
|
||||||
|
l.addWidget(self.use_custom, 2, 0, 1, 3)
|
||||||
|
self.use_custom.toggled.connect(self.custom_toggled)
|
||||||
|
|
||||||
|
off = 2
|
||||||
|
for which in (1, 2):
|
||||||
|
text = _('&Shortcut:') if which == 1 else _('&Alternate shortcut:')
|
||||||
|
la = QLabel(text)
|
||||||
|
la.setStyleSheet('QLabel { margin-left: 1.5em }')
|
||||||
|
l.addWidget(la, off+which, 0, 1, 3)
|
||||||
|
setattr(self, 'label%d'%which, la)
|
||||||
|
button = QPushButton(_('None'), self)
|
||||||
|
button.clicked.connect(partial(self.capture_clicked, which=which))
|
||||||
|
button.keyPressEvent = partial(self.key_press_event, which=which)
|
||||||
|
setattr(self, 'button%d'%which, button)
|
||||||
|
clear = QToolButton(self)
|
||||||
|
clear.setIcon(QIcon(I('clear_left.png')))
|
||||||
|
clear.clicked.connect(partial(self.clear_clicked, which=which))
|
||||||
|
setattr(self, 'clear%d'%which, clear)
|
||||||
|
l.addWidget(button, off+which, 1, 1, 1)
|
||||||
|
l.addWidget(clear, off+which, 2, 1, 1)
|
||||||
|
la.setBuddy(button)
|
||||||
|
|
||||||
|
self.done_button = doneb = QPushButton(_('Done'), self)
|
||||||
|
l.addWidget(doneb, 0, 2, 1, 1)
|
||||||
|
doneb.clicked.connect(lambda : self.editing_done.emit(self))
|
||||||
|
l.setColumnStretch(0, 100)
|
||||||
|
|
||||||
|
self.custom_toggled(False)
|
||||||
|
|
||||||
|
def initialize(self, shortcut, all_shortcuts):
|
||||||
|
self.header.setText('<b>%s: %s</b>'%(_('Customize'), shortcut['name']))
|
||||||
|
self.all_shortcuts = all_shortcuts
|
||||||
|
self.shortcut = shortcut
|
||||||
|
|
||||||
|
self.default_keys = [QKeySequence(k, QKeySequence.PortableText) for k
|
||||||
|
in shortcut['default_keys']]
|
||||||
|
self.current_keys = list(shortcut['keys'])
|
||||||
|
default = ', '.join([unicode(k.toString(k.NativeText)) for k in
|
||||||
|
self.default_keys])
|
||||||
|
if not default: default = _('None')
|
||||||
|
current = ', '.join([unicode(k.toString(k.NativeText)) for k in
|
||||||
|
self.current_keys])
|
||||||
|
if not current: current = _('None')
|
||||||
|
|
||||||
|
self.use_default.setText(_('Default: %s [Currently not conflicting: %s]')%
|
||||||
|
(default, current))
|
||||||
|
|
||||||
|
if shortcut['set_to_default']:
|
||||||
|
self.use_default.setChecked(True)
|
||||||
|
else:
|
||||||
|
self.use_custom.setChecked(True)
|
||||||
|
for key, which in zip(self.current_keys, [1,2]):
|
||||||
|
button = getattr(self, 'button%d'%which)
|
||||||
|
button.setText(key.toString(key.NativeText))
|
||||||
|
|
||||||
|
def custom_toggled(self, checked):
|
||||||
|
for w in ('1', '2'):
|
||||||
|
for o in ('label', 'button', 'clear'):
|
||||||
|
getattr(self, o+w).setEnabled(checked)
|
||||||
|
|
||||||
|
def capture_clicked(self, which=1):
|
||||||
|
self.capture = which
|
||||||
|
button = getattr(self, 'button%d'%which)
|
||||||
|
button.setText(_('Press a key...'))
|
||||||
|
button.setFocus(Qt.OtherFocusReason)
|
||||||
|
button.setStyleSheet('QPushButton { font-weight: bold}')
|
||||||
|
|
||||||
|
def clear_clicked(self, which=0):
|
||||||
|
button = getattr(self, 'button%d'%which)
|
||||||
|
button.setText(_('None'))
|
||||||
|
|
||||||
|
def key_press_event(self, ev, which=0):
|
||||||
|
code = ev.key()
|
||||||
|
if self.capture == 0 or code in (0, Qt.Key_unknown,
|
||||||
|
Qt.Key_Shift, Qt.Key_Control, Qt.Key_Alt, Qt.Key_Meta,
|
||||||
|
Qt.Key_AltGr, Qt.Key_CapsLock, Qt.Key_NumLock, Qt.Key_ScrollLock):
|
||||||
|
return QWidget.keyPressEvent(self, ev)
|
||||||
|
button = getattr(self, 'button%d'%which)
|
||||||
|
button.setStyleSheet('QPushButton { font-weight: normal}')
|
||||||
|
sequence = QKeySequence(code|(int(ev.modifiers())&~Qt.KeypadModifier))
|
||||||
|
button.setText(sequence.toString(QKeySequence.NativeText))
|
||||||
|
self.capture = 0
|
||||||
|
dup_desc = self.dup_check(sequence)
|
||||||
|
if dup_desc is not None:
|
||||||
|
error_dialog(self, _('Already assigned'),
|
||||||
|
unicode(sequence.toString(QKeySequence.NativeText)) + ' ' +
|
||||||
|
_('already assigned to') + ' ' + dup_desc, show=True)
|
||||||
|
self.clear_clicked(which=which)
|
||||||
|
|
||||||
|
def dup_check(self, sequence):
|
||||||
|
for sc in self.all_shortcuts:
|
||||||
|
if sc is self.shortcut: continue
|
||||||
|
for k in sc['keys']:
|
||||||
|
if k == sequence:
|
||||||
|
return sc['name']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def custom_keys(self):
|
||||||
|
if self.use_default.isChecked():
|
||||||
|
return None
|
||||||
|
ans = []
|
||||||
|
for which in (1, 2):
|
||||||
|
button = getattr(self, 'button%d'%which)
|
||||||
|
t = unicode(button.text())
|
||||||
|
if t == _('None'):
|
||||||
|
continue
|
||||||
|
ks = QKeySequence(t, QKeySequence.NativeText)
|
||||||
|
if not ks.isEmpty():
|
||||||
|
ans.append(ks)
|
||||||
|
return tuple(ans)
|
||||||
|
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class Delegate(QStyledItemDelegate): # {{{
|
||||||
|
|
||||||
|
changed_signal = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QStyledItemDelegate.__init__(self, parent)
|
||||||
|
self.editing_index = None
|
||||||
|
self.closeEditor.connect(self.editing_done)
|
||||||
|
|
||||||
|
def to_doc(self, index):
|
||||||
|
data = index.data(Qt.UserRole).toPyObject()
|
||||||
|
if data.is_shortcut:
|
||||||
|
shortcut = data.data
|
||||||
|
# Shortcut
|
||||||
|
keys = [unicode(k.toString(k.NativeText)) for k in shortcut['keys']]
|
||||||
|
if not keys:
|
||||||
|
keys = _('None')
|
||||||
|
else:
|
||||||
|
keys = ', '.join(keys)
|
||||||
|
html = '<b>%s</b><br>%s: %s'%(shortcut['name'], _('Shortcuts'), keys)
|
||||||
|
else:
|
||||||
|
# Group
|
||||||
|
html = '<h3>%s</h3>'%data.data
|
||||||
|
doc = QTextDocument()
|
||||||
|
doc.setHtml(html)
|
||||||
|
return doc
|
||||||
|
|
||||||
|
def sizeHint(self, option, index):
|
||||||
|
if index == self.editing_index:
|
||||||
|
return QSize(200, 200)
|
||||||
|
ans = self.to_doc(index).size().toSize()
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def paint(self, painter, option, index):
|
||||||
|
painter.save()
|
||||||
|
painter.setClipRect(QRectF(option.rect))
|
||||||
|
if hasattr(QStyle, 'CE_ItemViewItem'):
|
||||||
|
QApplication.style().drawControl(QStyle.CE_ItemViewItem, option, painter)
|
||||||
|
elif option.state & QStyle.State_Selected:
|
||||||
|
painter.fillRect(option.rect, option.palette.highlight())
|
||||||
|
painter.translate(option.rect.topLeft())
|
||||||
|
self.to_doc(index).drawContents(painter)
|
||||||
|
painter.restore()
|
||||||
|
|
||||||
|
def createEditor(self, parent, option, index):
|
||||||
|
w = Editor(parent=parent)
|
||||||
|
w.editing_done.connect(self.editor_done)
|
||||||
|
self.editing_index = index
|
||||||
|
self.sizeHintChanged.emit(index)
|
||||||
|
return w
|
||||||
|
|
||||||
|
def editor_done(self, editor):
|
||||||
|
self.commitData.emit(editor)
|
||||||
|
|
||||||
|
def setEditorData(self, editor, index):
|
||||||
|
all_shortcuts = [x.data for x in index.model().all_shortcuts]
|
||||||
|
shortcut = index.internalPointer().data
|
||||||
|
editor.initialize(shortcut, all_shortcuts)
|
||||||
|
|
||||||
|
def setModelData(self, editor, model, index):
|
||||||
|
self.closeEditor.emit(editor, self.NoHint)
|
||||||
|
custom_keys = editor.custom_keys
|
||||||
|
sc = index.data(Qt.UserRole).toPyObject().data
|
||||||
|
if custom_keys is None:
|
||||||
|
candidates = []
|
||||||
|
for ckey in sc['default_keys']:
|
||||||
|
ckey = QKeySequence(ckey, QKeySequence.PortableText)
|
||||||
|
matched = False
|
||||||
|
for s in editor.all_shortcuts:
|
||||||
|
for k in s['keys']:
|
||||||
|
if k == ckey:
|
||||||
|
matched = True
|
||||||
|
break
|
||||||
|
if not matched:
|
||||||
|
candidates.append(ckey)
|
||||||
|
candidates = tuple(candidates)
|
||||||
|
sc['set_to_default'] = True
|
||||||
|
else:
|
||||||
|
sc['set_to_default'] = False
|
||||||
|
candidates = custom_keys
|
||||||
|
sc['keys'] = candidates
|
||||||
|
self.changed_signal.emit()
|
||||||
|
|
||||||
|
def updateEditorGeometry(self, editor, option, index):
|
||||||
|
editor.setGeometry(option.rect)
|
||||||
|
|
||||||
|
def editing_done(self, *args):
|
||||||
|
idx = self.editing_index
|
||||||
|
self.editing_index = None
|
||||||
|
if idx is not None:
|
||||||
|
self.sizeHintChanged.emit(idx)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class ShortcutConfig(QWidget): # {{{
|
||||||
|
|
||||||
|
changed_signal = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QWidget.__init__(self, parent)
|
||||||
|
self._layout = l = QGridLayout()
|
||||||
|
self.setLayout(self._layout)
|
||||||
|
self.header = QLabel(_('Double click on any entry to change the'
|
||||||
|
' keyboard shortcuts associated with it'))
|
||||||
|
l.addWidget(self.header, 0, 0, 1, 3)
|
||||||
|
self.view = QTreeView(self)
|
||||||
|
self.view.setAlternatingRowColors(True)
|
||||||
|
self.view.setHeaderHidden(True)
|
||||||
|
self.view.setAnimated(True)
|
||||||
|
l.addWidget(self.view, 1, 0, 1, 3)
|
||||||
|
self.delegate = Delegate()
|
||||||
|
self.view.setItemDelegate(self.delegate)
|
||||||
|
self.delegate.sizeHintChanged.connect(self.scrollTo)
|
||||||
|
self.delegate.changed_signal.connect(self.changed_signal)
|
||||||
|
self.search = SearchBox2(self)
|
||||||
|
self.search.initialize('shortcuts_search_history',
|
||||||
|
help_text=_('Search for a shortcut by name'))
|
||||||
|
self.search.search.connect(self.find)
|
||||||
|
l.addWidget(self.search, 2, 0, 1, 1)
|
||||||
|
self.nb = QPushButton(QIcon(I('arrow-down.png')), _('&Next'), self)
|
||||||
|
self.pb = QPushButton(QIcon(I('arrow-up.png')), _('&Previous'), self)
|
||||||
|
self.nb.clicked.connect(self.find_next)
|
||||||
|
self.pb.clicked.connect(self.find_previous)
|
||||||
|
l.addWidget(self.nb, 2, 1, 1, 1)
|
||||||
|
l.addWidget(self.pb, 2, 2, 1, 1)
|
||||||
|
l.setColumnStretch(0, 100)
|
||||||
|
|
||||||
|
def restore_defaults(self):
|
||||||
|
self._model.restore_defaults()
|
||||||
|
self.changed_signal.emit()
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
self._model.commit()
|
||||||
|
|
||||||
|
def initialize(self, keyboard):
|
||||||
|
self._model = ConfigModel(keyboard, parent=self)
|
||||||
|
self.view.setModel(self._model)
|
||||||
|
|
||||||
|
def scrollTo(self, index):
|
||||||
|
if index is not None:
|
||||||
|
self.view.scrollTo(index, self.view.PositionAtCenter)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_editing(self):
|
||||||
|
return self.view.state() == self.view.EditingState
|
||||||
|
|
||||||
|
def find(self, query):
|
||||||
|
idx = self._model.find(query)
|
||||||
|
if not idx.isValid():
|
||||||
|
return info_dialog(self, _('No matches'),
|
||||||
|
_('Could not find any matching shortcuts'), show=True,
|
||||||
|
show_copy_button=False)
|
||||||
|
self.highlight_index(idx)
|
||||||
|
|
||||||
|
def highlight_index(self, idx):
|
||||||
|
self.view.scrollTo(idx)
|
||||||
|
self.view.selectionModel().select(idx,
|
||||||
|
self.view.selectionModel().ClearAndSelect)
|
||||||
|
self.view.setCurrentIndex(idx)
|
||||||
|
|
||||||
|
def find_next(self, *args):
|
||||||
|
idx = self.view.currentIndex()
|
||||||
|
if not idx.isValid():
|
||||||
|
idx = self._model.index(0, 0)
|
||||||
|
idx = self._model.find_next(idx,
|
||||||
|
unicode(self.search.currentText()))
|
||||||
|
self.highlight_index(idx)
|
||||||
|
|
||||||
|
def find_previous(self, *args):
|
||||||
|
idx = self.view.currentIndex()
|
||||||
|
if not idx.isValid():
|
||||||
|
idx = self._model.index(0, 0)
|
||||||
|
idx = self._model.find_next(idx,
|
||||||
|
unicode(self.search.currentText()), backwards=True)
|
||||||
|
self.highlight_index(idx)
|
||||||
|
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
'rating' : _('Rating'),
|
'rating' : _('Rating'),
|
||||||
'publisher' : _("Publisher"),
|
'publisher' : _("Publisher"),
|
||||||
'tags' : _("Tags"),
|
'tags' : _("Tags"),
|
||||||
'series' : _("Series"),
|
'series' : ngettext("Series", 'Series', 1),
|
||||||
'last_modified' : _('Modified'),
|
'last_modified' : _('Modified'),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,7 +694,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
# we will get asked to display columns we don't know about. Must test for this.
|
# we will get asked to display columns we don't know about. Must test for this.
|
||||||
if col >= len(self.column_to_dc_map):
|
if col >= len(self.column_to_dc_map):
|
||||||
return NONE
|
return NONE
|
||||||
if role in (Qt.DisplayRole, Qt.EditRole):
|
if role in (Qt.DisplayRole, Qt.EditRole, Qt.ToolTipRole):
|
||||||
return self.column_to_dc_map[col](index.row())
|
return self.column_to_dc_map[col](index.row())
|
||||||
elif role == Qt.BackgroundRole:
|
elif role == Qt.BackgroundRole:
|
||||||
if self.id(index) in self.ids_to_highlight_set:
|
if self.id(index) in self.ids_to_highlight_set:
|
||||||
|
@ -719,7 +719,7 @@ class BooksView(QTableView): # {{{
|
|||||||
break
|
break
|
||||||
|
|
||||||
def set_current_row(self, row, select=True):
|
def set_current_row(self, row, select=True):
|
||||||
if row > -1:
|
if row > -1 and row < self.model().rowCount(QModelIndex()):
|
||||||
h = self.horizontalHeader()
|
h = self.horizontalHeader()
|
||||||
logical_indices = list(range(h.count()))
|
logical_indices = list(range(h.count()))
|
||||||
logical_indices = [x for x in logical_indices if not
|
logical_indices = [x for x in logical_indices if not
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QCheckBox" name="opt_read_file_metadata">
|
<widget class="QCheckBox" name="opt_read_file_metadata">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Read &metadata from &file contents rather than file name</string>
|
<string>Read &metadata from file contents rather than file name</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
44
src/calibre/gui2/preferences/keyboard.py
Normal file
44
src/calibre/gui2/preferences/keyboard.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
from __future__ import (unicode_literals, division, absolute_import,
|
||||||
|
print_function)
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
from PyQt4.Qt import QVBoxLayout
|
||||||
|
|
||||||
|
from calibre.gui2.preferences import (ConfigWidgetBase, test_widget)
|
||||||
|
from calibre.gui2.keyboard import ShortcutConfig
|
||||||
|
|
||||||
|
class ConfigWidget(ConfigWidgetBase):
|
||||||
|
|
||||||
|
def genesis(self, gui):
|
||||||
|
self.gui = gui
|
||||||
|
self.conf_widget = ShortcutConfig(self)
|
||||||
|
self.conf_widget.changed_signal.connect(self.changed_signal)
|
||||||
|
self._layout = l = QVBoxLayout()
|
||||||
|
self.setLayout(l)
|
||||||
|
l.addWidget(self.conf_widget)
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
ConfigWidgetBase.initialize(self)
|
||||||
|
self.conf_widget.initialize(self.gui.keyboard)
|
||||||
|
|
||||||
|
def restore_defaults(self):
|
||||||
|
ConfigWidgetBase.restore_defaults(self)
|
||||||
|
self.conf_widget.restore_defaults()
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
self.conf_widget.commit()
|
||||||
|
return ConfigWidgetBase.commit(self)
|
||||||
|
|
||||||
|
def refresh_gui(self, gui):
|
||||||
|
gui.keyboard.finalize()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from PyQt4.Qt import QApplication
|
||||||
|
app = QApplication([])
|
||||||
|
test_widget('Advanced', 'Keyboard')
|
||||||
|
|
@ -522,6 +522,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
self.card_a_view.reset()
|
self.card_a_view.reset()
|
||||||
self.card_b_view.reset()
|
self.card_b_view.reset()
|
||||||
self.device_manager.set_current_library_uuid(db.library_id)
|
self.device_manager.set_current_library_uuid(db.library_id)
|
||||||
|
self.library_view.set_current_row(0)
|
||||||
# Run a garbage collection now so that it does not freeze the
|
# Run a garbage collection now so that it does not freeze the
|
||||||
# interface later
|
# interface later
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
@ -979,6 +979,11 @@ class DocumentView(QWebView): # {{{
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
|
if not self.handle_key_press(event):
|
||||||
|
return QWebView.keyPressEvent(self, event)
|
||||||
|
|
||||||
|
def handle_key_press(self, event):
|
||||||
|
handled = True
|
||||||
key = self.shortcuts.get_match(event)
|
key = self.shortcuts.get_match(event)
|
||||||
func = self.goto_location_actions.get(key, None)
|
func = self.goto_location_actions.get(key, None)
|
||||||
if func is not None:
|
if func is not None:
|
||||||
@ -996,7 +1001,8 @@ class DocumentView(QWebView): # {{{
|
|||||||
elif key == 'Right':
|
elif key == 'Right':
|
||||||
self.scroll_by(x=15)
|
self.scroll_by(x=15)
|
||||||
else:
|
else:
|
||||||
return QWebView.keyPressEvent(self, event)
|
handled = False
|
||||||
|
return handled
|
||||||
|
|
||||||
def resizeEvent(self, event):
|
def resizeEvent(self, event):
|
||||||
ret = QWebView.resizeEvent(self, event)
|
ret = QWebView.resizeEvent(self, event)
|
||||||
|
@ -755,6 +755,12 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
if self.current_index > 0:
|
if self.current_index > 0:
|
||||||
self.load_path(self.iterator.spine[self.current_index-1], pos=1.0)
|
self.load_path(self.iterator.spine[self.current_index-1], pos=1.0)
|
||||||
|
|
||||||
|
def keyPressEvent(self, event):
|
||||||
|
MainWindow.keyPressEvent(self, event)
|
||||||
|
if not event.isAccepted():
|
||||||
|
if not self.view.handle_key_press(event):
|
||||||
|
event.ignore()
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -296,8 +296,8 @@ def do_save_book_to_disk(id_, mi, cover, plugboards,
|
|||||||
replace_whitespace=opts.replace_whitespace, safe_format=False)
|
replace_whitespace=opts.replace_whitespace, safe_format=False)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise ValueError(_('Failed to calculate path for '
|
raise ValueError(_('Failed to calculate path for '
|
||||||
'save to disk. Template: %s\n'
|
'save to disk. Template: %(templ)s\n'
|
||||||
'Error: %s'%(opts.template, e)))
|
'Error: %(err)s')%dict(templ=opts.template, err=e))
|
||||||
if opts.single_dir:
|
if opts.single_dir:
|
||||||
components = components[-1:]
|
components = components[-1:]
|
||||||
if not components:
|
if not components:
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user