Start work on preferences widget to set keyboard shortcuts

This commit is contained in:
Kovid Goyal 2011-08-09 11:24:37 -06:00
parent c05c7fa370
commit 8d14a2f98d
10 changed files with 1173 additions and 21 deletions

912
imgsrc/keyboard-prefs.svg Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -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]
#}}} #}}}

View File

@ -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 hasattr(self.interface_action_base_plugin, 'name'):
bn = self.interface_action_base_plugin.name
return u'%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

View File

@ -79,13 +79,14 @@ class LibraryUsageStats(object): # {{{
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)
@ -376,7 +377,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

View File

@ -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')

View File

@ -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)

View File

@ -9,16 +9,22 @@ __docformat__ = 'restructuredtext en'
from collections import OrderedDict from collections import OrderedDict
from PyQt4.Qt import (QObject, QKeySequence) from PyQt4.Qt import (QObject, QKeySequence, QAbstractItemModel, QModelIndex,
Qt, QStyledItemDelegate, QTextDocument, QStyle, pyqtSignal,
QApplication, QSize, QRectF, QWidget, QHBoxLayout, QTreeView)
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
from calibre.gui2 import NONE
ROOT = QModelIndex()
class NameConflict(ValueError): class NameConflict(ValueError):
pass pass
class Manager(QObject): class Manager(QObject): # {{{
def __init__(self, parent=None): def __init__(self, parent=None):
QObject.__init__(self, parent) QObject.__init__(self, parent)
@ -27,13 +33,10 @@ class Manager(QObject):
self.custom_keys_map = {} 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):
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,8 +44,13 @@ 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):
self.custom_keys_map = {un:tuple(keys) for un, keys in self.config.get(
'map', {}).iteritems()}
seen = {} seen = {}
for unique_name, shortcut in self.shortcuts.iteritems(): for unique_name, shortcut in self.shortcuts.iteritems():
custom_keys = self.custom_keys_map.get(unique_name, None) custom_keys = self.custom_keys_map.get(unique_name, None)
@ -69,3 +77,155 @@ class Manager(QObject):
if ac is not None: if ac is not None:
ac.setShortcuts(list(keys)) ac.setShortcuts(list(keys))
self.groups = {g:frozenset(v) for g, v in self.groups.iteritems()}
# }}}
# 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]
class ConfigModel(QAbstractItemModel):
def __init__(self, keyboard, parent=None):
QAbstractItemModel.__init__(self, parent)
self.keyboard = keyboard
groups = sorted(keyboard.groups, key=sort_key)
shortcut_map = {k:dict(v) 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]
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
# }}}
class Delegate(QStyledItemDelegate): # {{{
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
self.editing_indices = {}
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 = '<h4>%s</h4>%s: %s'%(shortcut['name'], _('Shortcuts'), keys)
else:
# Group
html = '<h2>%s</h2>'%data.data
doc = QTextDocument()
doc.setHtml(html)
return doc
def sizeHint(self, option, index):
if index.row() in self.editing_indices:
return QSize(200, 200)
ans = self.to_doc(index).size().toSize()
#ans.setHeight(ans.height()+10)
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()
# }}}
class ShortcutConfig(QWidget):
changed_signal = pyqtSignal()
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self._layout = QHBoxLayout()
self.setLayout(self._layout)
self.view = QTreeView(self)
self.view.setAlternatingRowColors(True)
self.view.setHeaderHidden(True)
self.view.setAnimated(True)
self._layout.addWidget(self.view)
self.delegate = Delegate()
self.view.setItemDelegate(self.delegate)
self.delegate.sizeHintChanged.connect(self.scrollTo)
def initialize(self, keyboard):
self._model = ConfigModel(keyboard, parent=self)
self.view.setModel(self._model)
def scrollTo(self, index):
self.view.scrollTo(index)
@property
def is_editing(self):
return self.view.state() == self.view.EditingState

View File

@ -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:

View 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')