KG updates

This commit is contained in:
GRiker 2010-09-06 12:41:24 -07:00
commit d823d4244a
50 changed files with 5320 additions and 8233 deletions

View File

@ -1,61 +1,211 @@
<?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 height="253.5" id="Layer_1" inkscape:version="0.40+cvs" sodipodi:docbase="F:\openclip\svg3" sodipodi:docname="Capitello modanatura moulure.svg" sodipodi:version="0.32" style="overflow:visible;enable-background:new 0 0 277.433 253.5;" version="1.0" viewBox="0 0 277.433 253.5" width="277.433" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xml="http://www.w3.org/XML/1998/namespace"><metadata><rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><cc:Work rdf:about=""><dc:title>Capitello modanatura modanature moulure moulures</dc:title><dc:description></dc:description><dc:subject><rdf:Bag><rdf:li>building</rdf:li></rdf:Bag></dc:subject><dc:publisher><cc:Agent rdf:about="http://www.openclipart.org"><dc:title>Architetto Francesco Rollandin</dc:title></cc:Agent></dc:publisher><dc:creator><cc:Agent><dc:title>Architetto Francesco Rollandin</dc:title></cc:Agent></dc:creator><dc:rights><cc:Agent><dc:title>Architetto Francesco Rollandin</dc:title></cc:Agent></dc:rights><dc:date></dc:date><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/><dc:language>en</dc:language></cc:Work><cc:License rdf:about="http://web.resource.org/cc/PublicDomain"><cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/><cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/><cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/></cc:License></rdf:RDF></metadata>
<defs id="defs56"></defs>
<sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="Layer_1" inkscape:cx="138.71651" inkscape:cy="126.75000" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="540" inkscape:window-width="640" inkscape:window-x="22" inkscape:window-y="22" inkscape:zoom="1.4911243" pagecolor="#ffffff"></sodipodi:namedview>
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<g id="g3">
<path d="M269.987,16.446c11.514,10.547,7.726,33.31,1.663,45.651c-9.559,19.459-32.822,21.546-51.841,19.009 c-2.021,22.636-2.369,45.377-2.399,68.09c-0.015,10.891,0.025,21.781,0.025,32.672c0,5.381,0,10.762,0,16.143 c0,4.35,1.145,5.354,5.544,5.098c2.975-0.172,12.557-3.239,12.893,1.706c0.221,3.245-2.241,9.014-0.016,11.713 c1.997,2.421,5.807,3.181,8.67,3.993c3.729,1.058,7.776,3.027,11.667,3.265c2.984,0.182,1.435,5.441,1.368,7.535 c-0.148,4.68,0.078,9.268,0.319,13.928c0.24,4.638-1.359,4.189-5.543,4.594c-21.966,2.125-44.538,0.341-66.583,0.291 c-22.807-0.052-45.619,0.078-68.409,1.014c-22.082,0.906-44.168,0.835-66.252,1.523c-9,0.28-18.09,0.771-27.071,0.831 c-3.313,0.022-3.382-1.347-2.935-4.079c0.726-4.434,0.467-8.914,0.467-13.398c0-2.373-1.074-7.706,1.34-9.398 c2.938-2.061,7.151-2.742,10.401-4.265c9.135-4.276,6.441-7.791,6.591-16.34c0.073-4.137,5.426-1.096,8.395-1.154 c4.361-0.087,2.593-4.402,2.559-7.859c-0.064-6.333-0.206-12.665-0.382-18.995c-0.639-23.031-1.182-46.073-2.019-69.097 c-0.196-5.4-0.352-10.801-0.472-16.204c-0.058-2.589,1.452-11.419-2.132-11.275c-8.722,0.349-17.113-0.684-25.05-4.56 C-12.651,60.547-3.602,8.372,32.616,2.474c9.309-1.516,19.017-0.612,28.399-0.511c11.773,0.126,23.546,0.163,35.32,0.157 c23.119-0.013,46.238-0.115,69.354-0.556C185.921,1.177,206.175-0.019,226.411,0C242.655,0.015,259.596,3.013,269.987,16.446" id="path5"></path>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="277.42999"
id="Layer_1"
inkscape:version="0.48.0 r9654"
sodipodi:docname="column.svg"
sodipodi:version="0.32"
style="overflow:visible"
version="1.0"
viewBox="0 0 277.42997 277.42999"
width="277.42999"
xml:space="preserve"><metadata
id="metadata3"><rdf:RDF><cc:Work
rdf:about=""><dc:title>Capitello modanatura modanature moulure moulures</dc:title><dc:description /><dc:subject><rdf:Bag><rdf:li>building</rdf:li></rdf:Bag></dc:subject><dc:publisher><cc:Agent
rdf:about="http://www.openclipart.org"><dc:title>Architetto Francesco Rollandin</dc:title></cc:Agent></dc:publisher><dc:creator><cc:Agent><dc:title>Architetto Francesco Rollandin</dc:title></cc:Agent></dc:creator><dc:rights><cc:Agent><dc:title>Architetto Francesco Rollandin</dc:title></cc:Agent></dc:rights><dc:date /><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license
rdf:resource="http://web.resource.org/cc/PublicDomain" /><dc:language>en</dc:language></cc:Work><cc:License
rdf:about="http://web.resource.org/cc/PublicDomain"><cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" /><cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" /><cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" /></cc:License></rdf:RDF></metadata>
<defs
id="defs56" />
<sodipodi:namedview
bordercolor="#666666"
borderopacity="1.0"
id="base"
inkscape:current-layer="Layer_1"
inkscape:cx="138.71675"
inkscape:cy="137.75228"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:window-height="997"
inkscape:window-width="1680"
inkscape:window-x="-4"
inkscape:window-y="30"
inkscape:zoom="1.4911243"
pagecolor="#ffffff"
showgrid="false"
fit-margin-top="12"
fit-margin-bottom="11"
fit-margin-left="0"
fit-margin-right="0"
inkscape:window-maximized="1" />
<path d="M263.497,12.805c17.229,17.231,13.408,52.826-9.883,63.111c-11.111,4.906-29.468,6.652-39.829-0.784 c-4.768-3.42-10.636-8.188-13.193-13.588c-2.79-5.893-0.708-14.659,1.955-20.272c5.144-10.839,15.963-19.15,28.248-18.245 c13.067,0.963,21.35,10.229,19.214,23.444c-1.684,10.42-12.965,22.841-24.252,15.978c-4.984-3.032-8.286-9.521-6.396-15.307 c1.08-3.303,8.425-8.779,10.105-2.996c-3.617-0.933-3.468,5.562-2.88,7.464c1.694,5.481,8.471,5.282,12.069,1.689 c10.924-10.907-4.807-28.457-17.827-22.066c-15.255,7.487-15.464,27.982-1.153,36.475c13.494,8.008,31.806,1.371,39.313-11.699 c6.751-11.753,4.543-29.552-5.98-38.545c-6.412-5.48-16.133-5.78-24.13-6.6C217.514,9.7,206.07,9.611,194.659,9.88 c-45.654,1.077-91.252,2.635-136.93,2.865c-10.516,0.053-26.706-3.068-35.7,3.59C13.072,22.966,7.624,34.89,8.907,45.965 c2.465,21.27,26.852,34.439,45.764,23.854C63.05,65.13,69.272,56.151,68.154,46.26c-1.048-9.266-8.71-17.296-18.334-17.278 c-10.437,0.02-18.804,10.469-13.622,20.189c2.062,3.867,8.494,5.687,11.636,1.998c2.241-2.63,1.254-7.959-2.931-7.419 c4.833-5.223,11.914,1.513,11.38,7.142c-0.623,6.566-7.648,11.135-13.593,12.024c-15.159,2.267-23.777-11.625-20.532-25.271 c3.998-16.809,21.359-21.542,36.573-17.014c17.902,5.329,19.484,20.76,13.54,36.295C59.813,89.49,7.194,84.666,2.164,49.499 c-2.4-16.776,6.42-36.324,22.822-42.628c7.058-2.713,14.77-2.768,22.225-2.692C58.154,4.29,69.098,4.427,80.042,4.491 c32.615,0.19,65.303,0.147,97.908-0.728c16.363-0.439,32.709-1.273,49.082-0.806C239.347,3.309,254.146,3.507,263.497,12.805" id="path7" style="fill:#BFBFBF;"></path>
<g
id="g3"
transform="translate(2.4435697e-4,12.927759)">
<path
d="m 269.987,16.446 c 11.514,10.547 7.726,33.31 1.663,45.651 -9.559,19.459 -32.822,21.546 -51.841,19.009 -2.021,22.636 -2.369,45.377 -2.399,68.09 -0.015,10.891 0.025,21.781 0.025,32.672 0,5.381 0,10.762 0,16.143 0,4.35 1.145,5.354 5.544,5.098 2.975,-0.172 12.557,-3.239 12.893,1.706 0.221,3.245 -2.241,9.014 -0.016,11.713 1.997,2.421 5.807,3.181 8.67,3.993 3.729,1.058 7.776,3.027 11.667,3.265 2.984,0.182 1.435,5.441 1.368,7.535 -0.148,4.68 0.078,9.268 0.319,13.928 0.24,4.638 -1.359,4.189 -5.543,4.594 -21.966,2.125 -44.538,0.341 -66.583,0.291 -22.807,-0.052 -45.619,0.078 -68.409,1.014 -22.082,0.906 -44.168,0.835 -66.252,1.523 -9,0.28 -18.09,0.771 -27.071,0.831 -3.313,0.022 -3.382,-1.347 -2.935,-4.079 0.726,-4.434 0.467,-8.914 0.467,-13.398 0,-2.373 -1.074,-7.706 1.34,-9.398 2.938,-2.061 7.151,-2.742 10.401,-4.265 9.135,-4.276 6.441,-7.791 6.591,-16.34 0.073,-4.137 5.426,-1.096 8.395,-1.154 4.361,-0.087 2.593,-4.402 2.559,-7.859 -0.064,-6.333 -0.206,-12.665 -0.382,-18.995 -0.639,-23.031 -1.182,-46.073 -2.019,-69.097 -0.196,-5.4 -0.352,-10.801 -0.472,-16.204 C 47.909,90.124 49.419,81.294 45.835,81.438 37.113,81.787 28.722,80.754 20.785,76.878 -12.651,60.547 -3.602,8.372 32.616,2.474 41.925,0.958 51.633,1.862 61.015,1.963 72.788,2.089 84.561,2.126 96.335,2.12 119.454,2.107 142.573,2.005 165.689,1.564 185.921,1.177 206.175,-0.019 226.411,0 c 16.244,0.015 33.185,3.013 43.576,16.446"
id="path5"
inkscape:connector-curvature="0" />
<path d="M258.749,31.246c3.035,11.892-0.551,27.027-11.674,33.584c-10.348,6.101-28.37,4.505-33.847-7.551 c-4.545-10.002,2.436-25.982,14.791-24.727c6.887,0.7,10.927,5.838,10.588,12.623c-0.167,3.326-0.945,6.588-4.631,7.439 c-3.448,0.796-6.992-1.519-4.906-5.223c4.045,5.535,5.103-6.75-1.358-8.312c-6.246-1.511-10.79,3.854-10.992,9.564 c-0.493,13.941,14.36,23.351,26.353,15.28c11.628-7.826,13.93-28.233,3.285-37.841c-6.293-5.681-15.592-6.508-23.673-6.923 c-11.101-0.57-22.227,0.536-33.31,1.041c-22.333,1.019-44.661,2.149-66.996,3.14c-10.522,0.466-21.048,0.829-31.577,1.124 c-5.074,0.142-10.148,0.27-15.223,0.378c-5.138,0.109-9.622-3.251-14.107-5.271c-13.721-6.181-33.438-2.347-40.341,11.952 c-5.646,11.696-1.719,30.13,12.218,33.742c10.756,2.788,31.213-5.459,25.068-19.708c-2.384-5.527-9.835-7.564-14.897-4.53 c-1.53,0.917-5.698,8.159-1.748,6.881c1.042-0.337,1.828-1.721,3.053-1.544c2.031,0.294,1.867,1.657,0.453,2.672 c-6.196,4.449-9.433-4.01-7.865-8.951c2.52-7.944,13.175-10.17,19.805-6.519c13.573,7.474,8.818,25.74-2.296,32.597 c-14.444,8.912-34.788,3.045-41.537-12.791C7.439,39.422,15.236,19.093,30.86,15.584c9.506-2.136,20.457-0.466,30.129-0.384 c12.077,0.103,24.155,0.117,36.232,0.044c23.102-0.14,46.172-0.626,69.248-1.748c19.153-0.93,38.758-2.352,57.946-1.18 C237.174,13.095,255.954,15.957,258.749,31.246" id="path9" style="fill:#808080;"></path>
<path
d="m 263.497,12.805 c 17.229,17.231 13.408,52.826 -9.883,63.111 -11.111,4.906 -29.468,6.652 -39.829,-0.784 -4.768,-3.42 -10.636,-8.188 -13.193,-13.588 -2.79,-5.893 -0.708,-14.659 1.955,-20.272 5.144,-10.839 15.963,-19.15 28.248,-18.245 13.067,0.963 21.35,10.229 19.214,23.444 -1.684,10.42 -12.965,22.841 -24.252,15.978 -4.984,-3.032 -8.286,-9.521 -6.396,-15.307 1.08,-3.303 8.425,-8.779 10.105,-2.996 -3.617,-0.933 -3.468,5.562 -2.88,7.464 1.694,5.481 8.471,5.282 12.069,1.689 10.924,-10.907 -4.807,-28.457 -17.827,-22.066 -15.255,7.487 -15.464,27.982 -1.153,36.475 13.494,8.008 31.806,1.371 39.313,-11.699 6.751,-11.753 4.543,-29.552 -5.98,-38.545 -6.412,-5.48 -16.133,-5.78 -24.13,-6.6 C 217.514,9.7 206.07,9.611 194.659,9.88 149.005,10.957 103.407,12.515 57.729,12.745 47.213,12.798 31.023,9.677 22.029,16.335 13.072,22.966 7.624,34.89 8.907,45.965 11.372,67.235 35.759,80.404 54.671,69.819 63.05,65.13 69.272,56.151 68.154,46.26 67.106,36.994 59.444,28.964 49.82,28.982 39.383,29.002 31.016,39.451 36.198,49.171 c 2.062,3.867 8.494,5.687 11.636,1.998 2.241,-2.63 1.254,-7.959 -2.931,-7.419 4.833,-5.223 11.914,1.513 11.38,7.142 C 55.66,57.458 48.635,62.027 42.69,62.916 27.531,65.183 18.913,51.291 22.158,37.645 26.156,20.836 43.517,16.103 58.731,20.631 76.633,25.96 78.215,41.391 72.271,56.926 59.813,89.49 7.194,84.666 2.164,49.499 -0.236,32.723 8.584,13.175 24.986,6.871 32.044,4.158 39.756,4.103 47.211,4.179 58.154,4.29 69.098,4.427 80.042,4.491 c 32.615,0.19 65.303,0.147 97.908,-0.728 16.363,-0.439 32.709,-1.273 49.082,-0.806 12.315,0.352 27.114,0.55 36.465,9.848"
id="path7"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
<path d="M216.96,22.065c-4.189,1.457-6.926,5.1-10.035,8.035c-3.926,3.706-7.758,3.477-12.894,3.057 c-13.75-1.124-27.989-0.009-41.786,0.081c-14.754,0.095-29.439,0.667-44.163,1.609c-7.355,0.471-14.71,0.961-22.071,1.337 c-3.388,0.173-7.721,1.855-8.424-1.65c-0.532-2.656-2.151-4.901-3.401-7.245c25.986-0.478,51.909-1.521,77.857-2.958 c12.748-0.706,25.585-1.691,38.35-1.883c5.152-0.078,10.293,0.221,15.423-0.352C209.098,21.729,213.818,20.556,216.96,22.065" id="path11" style="fill:#5E5E5E;"></path>
<path
d="m 258.749,31.246 c 3.035,11.892 -0.551,27.027 -11.674,33.584 -10.348,6.101 -28.37,4.505 -33.847,-7.551 -4.545,-10.002 2.436,-25.982 14.791,-24.727 6.887,0.7 10.927,5.838 10.588,12.623 -0.167,3.326 -0.945,6.588 -4.631,7.439 -3.448,0.796 -6.992,-1.519 -4.906,-5.223 4.045,5.535 5.103,-6.75 -1.358,-8.312 -6.246,-1.511 -10.79,3.854 -10.992,9.564 -0.493,13.941 14.36,23.351 26.353,15.28 11.628,-7.826 13.93,-28.233 3.285,-37.841 -6.293,-5.681 -15.592,-6.508 -23.673,-6.923 -11.101,-0.57 -22.227,0.536 -33.31,1.041 -22.333,1.019 -44.661,2.149 -66.996,3.14 -10.522,0.466 -21.048,0.829 -31.577,1.124 -5.074,0.142 -10.148,0.27 -15.223,0.378 C 70.441,24.951 65.957,21.591 61.472,19.571 47.751,13.39 28.034,17.224 21.131,31.523 15.485,43.219 19.412,61.653 33.349,65.265 44.105,68.053 64.562,59.806 58.417,45.557 56.033,40.03 48.582,37.993 43.52,41.027 c -1.53,0.917 -5.698,8.159 -1.748,6.881 1.042,-0.337 1.828,-1.721 3.053,-1.544 2.031,0.294 1.867,1.657 0.453,2.672 -6.196,4.449 -9.433,-4.01 -7.865,-8.951 2.52,-7.944 13.175,-10.17 19.805,-6.519 13.573,7.474 8.818,25.74 -2.296,32.597 C 40.478,75.075 20.134,69.208 13.385,53.372 7.439,39.422 15.236,19.093 30.86,15.584 40.366,13.448 51.317,15.118 60.989,15.2 c 12.077,0.103 24.155,0.117 36.232,0.044 23.102,-0.14 46.172,-0.626 69.248,-1.748 19.153,-0.93 38.758,-2.352 57.946,-1.18 12.759,0.779 31.539,3.641 34.334,18.93"
id="path9"
style="fill:#808080"
inkscape:connector-curvature="0" />
<path d="M202.556,35.282c-3.06,6.708-6.111,13.132-5.917,20.674c0.065,2.534,0.354,5.179,1.679,7.404 c1.462,2.459,4.185,3.993,4.92,6.893c1.413,5.582-0.519,12.133-0.678,17.817c-0.233,8.271-0.503,16.542-0.691,24.813 c-0.373,16.291-0.483,32.586-0.646,48.88c-0.081,8.149-0.175,16.3-0.321,24.449c-0.058,3.206,1.931,16.342-2.582,17.381 c-4.207,0.97-9.048,1.308-9.19-3.83c-0.206-7.431,0.059-14.804,0.187-22.237c0.296-17.278,0.149-34.562,0.442-51.841 c0.278-16.383,0.703-32.763,1.037-49.146c0.156-7.656,0.222-15.316,0.411-22.972c0.161-6.488-5.237-11.803-7.485-17.813 C189.794,33.726,196.337,35.792,202.556,35.282" id="path13" style="fill:#E3E3E3;"></path>
<path
d="m 216.96,22.065 c -4.189,1.457 -6.926,5.1 -10.035,8.035 -3.926,3.706 -7.758,3.477 -12.894,3.057 -13.75,-1.124 -27.989,-0.009 -41.786,0.081 -14.754,0.095 -29.439,0.667 -44.163,1.609 -7.355,0.471 -14.71,0.961 -22.071,1.337 -3.388,0.173 -7.721,1.855 -8.424,-1.65 -0.532,-2.656 -2.151,-4.901 -3.401,-7.245 25.986,-0.478 51.909,-1.521 77.857,-2.958 12.748,-0.706 25.585,-1.691 38.35,-1.883 5.152,-0.078 10.293,0.221 15.423,-0.352 3.282,-0.367 8.002,-1.54 11.144,-0.031"
id="path11"
style="fill:#5e5e5e"
inkscape:connector-curvature="0" />
<path d="M149.926,35.678c-1.179,5.098-7.83,6.24-8.979,10.95c-1.648,6.761-0.583,15.063-0.745,22.007 c-0.406,17.411-0.884,34.822-0.57,52.239c0.308,17.057,0.717,34.095,0.717,51.156c0,8.01,0,16.02,0,24.028 c0,7.207,0.133,7.996-7.093,7.5c-6.914-0.475-3.747-15.828-3.729-20.809c0.059-16.925,0.119-33.849,0.178-50.773 c0.061-17.404-0.096-34.828,0.439-52.226c0.247-8.041,0.696-16.035,0.593-24.084c-0.11-8.56-2.827-11.851-8.037-18.326 C131.735,36.181,140.884,36.717,149.926,35.678" id="path15" style="fill:#E3E3E3;"></path>
<path
d="m 202.556,35.282 c -3.06,6.708 -6.111,13.132 -5.917,20.674 0.065,2.534 0.354,5.179 1.679,7.404 1.462,2.459 4.185,3.993 4.92,6.893 1.413,5.582 -0.519,12.133 -0.678,17.817 -0.233,8.271 -0.503,16.542 -0.691,24.813 -0.373,16.291 -0.483,32.586 -0.646,48.88 -0.081,8.149 -0.175,16.3 -0.321,24.449 -0.058,3.206 1.931,16.342 -2.582,17.381 -4.207,0.97 -9.048,1.308 -9.19,-3.83 -0.206,-7.431 0.059,-14.804 0.187,-22.237 0.296,-17.278 0.149,-34.562 0.442,-51.841 0.278,-16.383 0.703,-32.763 1.037,-49.146 0.156,-7.656 0.222,-15.316 0.411,-22.972 0.161,-6.488 -5.237,-11.803 -7.485,-17.813 6.072,-2.028 12.615,0.038 18.834,-0.472"
id="path13"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path d="M180.872,35.678c-0.979,4.869-5.544,7.579-8.596,11.063c-4.358,4.976-2.346,12.479-2.414,18.523 c-0.192,17.04-1.516,33.989-1.317,51.069c0.191,16.582,0.597,33.16,0.705,49.742c0.054,8.282,0.034,16.565-0.123,24.847 c-0.069,3.652,0.211,7.544-0.281,11.169c-0.41,3.021-5.537,2.033-7.736,2.147c-1.793,0.094-1.443-80.056-1.404-87.238 c0.085-16.094,0.108-32.21,0.636-48.297c0.19-5.829,0.481-11.56,1.162-17.345c0.758-6.434-3.308-10.796-7.856-15.206 c3.301-1.833,8.131-0.664,11.682-0.447C170.432,36.017,175.776,36.123,180.872,35.678" id="path17" style="fill:#E3E3E3;"></path>
<path
d="m 149.926,35.678 c -1.179,5.098 -7.83,6.24 -8.979,10.95 -1.648,6.761 -0.583,15.063 -0.745,22.007 -0.406,17.411 -0.884,34.822 -0.57,52.239 0.308,17.057 0.717,34.095 0.717,51.156 0,8.01 0,16.02 0,24.028 0,7.207 0.133,7.996 -7.093,7.5 -6.914,-0.475 -3.747,-15.828 -3.729,-20.809 0.059,-16.925 0.119,-33.849 0.178,-50.773 0.061,-17.404 -0.096,-34.828 0.439,-52.226 0.247,-8.041 0.696,-16.035 0.593,-24.084 -0.11,-8.56 -2.827,-11.851 -8.037,-18.326 9.035,-1.159 18.184,-0.623 27.226,-1.662"
id="path15"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path d="M118.269,37.735c-1.283,2.154-2.983,4.106-4.986,5.619c-1.565,1.183-3.853,1.641-4.952,3.395 c-1.47,2.347,0.599,5.242,0.599,7.685c0,4.216-0.604,8.428-0.717,12.647c-0.438,16.338-0.463,32.68-0.272,49.021 c0.194,16.553,0.592,33.098,1.683,49.619c0.389,5.881,5.109,37.916-2.616,38.886c-3.479,0.438-8.817,1.344-9.113-3.157 c-0.499-7.577-0.5-15.216-0.751-22.806c-0.55-16.556-1.148-33.111-1.437-49.675c-0.284-16.31-0.281-32.628,0.23-48.934 c0.255-8.16,0.637-16.315,1.172-24.461c0.475-7.23-3.972-10.534-5.669-17.048C100.385,38.349,109.315,37.358,118.269,37.735" id="path19" style="fill:#E3E3E3;"></path>
<path
d="m 180.872,35.678 c -0.979,4.869 -5.544,7.579 -8.596,11.063 -4.358,4.976 -2.346,12.479 -2.414,18.523 -0.192,17.04 -1.516,33.989 -1.317,51.069 0.191,16.582 0.597,33.16 0.705,49.742 0.054,8.282 0.034,16.565 -0.123,24.847 -0.069,3.652 0.211,7.544 -0.281,11.169 -0.41,3.021 -5.537,2.033 -7.736,2.147 -1.793,0.094 -1.443,-80.056 -1.404,-87.238 0.085,-16.094 0.108,-32.21 0.636,-48.297 0.19,-5.829 0.481,-11.56 1.162,-17.345 0.758,-6.434 -3.308,-10.796 -7.856,-15.206 3.301,-1.833 8.131,-0.664 11.682,-0.447 5.102,0.312 10.446,0.418 15.542,-0.027"
id="path17"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path d="M158.395,46.125c-0.533,31.886-1.188,63.758-1.188,95.65c0,15.317,0,30.634,0,45.95 c0,4.617,0.757,9.24,0.664,13.833c-0.068,3.371-8.199,3.735-8.344,0.423c-1.413-32.226-1.844-64.548-1.556-96.803 c0.143-15.907,0.771-31.809,1.218-47.709c0.135-4.806-1.466-13.862,1.021-18.2C152.52,35.243,157.134,45.118,158.395,46.125" id="path21" style="fill:#969696;"></path>
<path
d="m 118.269,37.735 c -1.283,2.154 -2.983,4.106 -4.986,5.619 -1.565,1.183 -3.853,1.641 -4.952,3.395 -1.47,2.347 0.599,5.242 0.599,7.685 0,4.216 -0.604,8.428 -0.717,12.647 -0.438,16.338 -0.463,32.68 -0.272,49.021 0.194,16.553 0.592,33.098 1.683,49.619 0.389,5.881 5.109,37.916 -2.616,38.886 -3.479,0.438 -8.817,1.344 -9.113,-3.157 -0.499,-7.577 -0.5,-15.216 -0.751,-22.806 -0.55,-16.556 -1.148,-33.111 -1.437,-49.675 -0.284,-16.31 -0.281,-32.628 0.23,-48.934 0.255,-8.16 0.637,-16.315 1.172,-24.461 0.475,-7.23 -3.972,-10.534 -5.669,-17.048 8.945,-0.177 17.875,-1.168 26.829,-0.791"
id="path19"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path d="M86.137,40.11c-1.802,4.444-6.351,6.834-8.785,10.843c0.118-3.233-1.075-7.139,0.521-10.162 C78.82,38.997,86.6,37.518,86.137,40.11" id="path23" style="fill:#E3E3E3;"></path>
<path
d="m 158.395,46.125 c -0.533,31.886 -1.188,63.758 -1.188,95.65 0,15.317 0,30.634 0,45.95 0,4.617 0.757,9.24 0.664,13.833 -0.068,3.371 -8.199,3.735 -8.344,0.423 -1.413,-32.226 -1.844,-64.548 -1.556,-96.803 0.143,-15.907 0.771,-31.809 1.218,-47.709 0.135,-4.806 -1.466,-13.862 1.021,-18.2 2.31,-4.026 6.924,5.849 8.185,6.856"
id="path21"
style="fill:#969696"
inkscape:connector-curvature="0" />
<path d="M127.924,47.708c-0.864,29.137-0.867,58.291-0.963,87.438c-0.048,14.845-0.097,29.689-0.146,44.534 c-0.023,6.938,0.175,13.919-0.089,20.853c-0.133,3.509-2.079,3.183-5.074,3.256c-3.186,0.077-1.998-5.488-2.133-8.231 c-0.182-3.69-0.362-7.381-0.538-11.071c-0.351-7.383-0.684-14.767-0.974-22.152c-0.581-14.771-0.985-29.548-1.057-44.33 c-0.071-14.73,0.919-29.391,1.103-44.1c0.088-7.041-0.18-14.086-0.18-21.128c0-5.268-1.026-9.582,2.85-13.457 C123.231,42.02,125.295,45.115,127.924,47.708" id="path25" style="fill:#969696;"></path>
<path
d="M 86.137,40.11 C 84.335,44.554 79.786,46.944 77.352,50.953 77.47,47.72 76.277,43.814 77.873,40.791 78.82,38.997 86.6,37.518 86.137,40.11"
id="path23"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path d="M188.469,83.005c-0.868,27.782-1.484,55.573-1.786,83.367c-0.124,11.389,0.632,23.096-0.191,34.44 c-0.213,2.944-4.001,4.863-6.649,2.729c-2.821-2.274-2.137-11.711-2.193-14.737c-0.244-12.991,0.978-25.921,0.54-38.927 c-0.438-12.993-0.009-25.956,0.292-38.947c0.301-13.003,0.601-26.007,0.907-39.01c0.25-10.571-2.265-22.762,2.749-32.602 C192.517,51.294,189.273,68.576,188.469,83.005" id="path27" style="fill:#969696;"></path>
<path
d="m 127.924,47.708 c -0.864,29.137 -0.867,58.291 -0.963,87.438 -0.048,14.845 -0.097,29.689 -0.146,44.534 -0.023,6.938 0.175,13.919 -0.089,20.853 -0.133,3.509 -2.079,3.183 -5.074,3.256 -3.186,0.077 -1.998,-5.488 -2.133,-8.231 -0.182,-3.69 -0.362,-7.381 -0.538,-11.071 -0.351,-7.383 -0.684,-14.767 -0.974,-22.152 -0.581,-14.771 -0.985,-29.548 -1.057,-44.33 -0.071,-14.73 0.919,-29.391 1.103,-44.1 0.088,-7.041 -0.18,-14.086 -0.18,-21.128 0,-5.268 -1.026,-9.582 2.85,-13.457 2.508,2.7 4.572,5.795 7.201,8.388"
id="path25"
style="fill:#969696"
inkscape:connector-curvature="0" />
<path d="M95.001,51.744c-1.75,28.572-2.194,57.212-1.738,85.831c0.216,13.561,0.746,27.112,1.23,40.665 c0.248,6.934,0.492,13.867,0.735,20.801c0.229,6.533-2.363,4.685-7.43,5.211c-1.578-28.564-2.779-57.147-2.978-85.757 c-0.093-13.326-0.059-26.656,0.183-39.98c0.121-6.69,0.447-13.376,0.565-20.066c0.106-6.027,0.059-12.19,3.418-17.468 C90.991,44.568,92.996,48.156,95.001,51.744" id="path29" style="fill:#969696;"></path>
<path
d="m 188.469,83.005 c -0.868,27.782 -1.484,55.573 -1.786,83.367 -0.124,11.389 0.632,23.096 -0.191,34.44 -0.213,2.944 -4.001,4.863 -6.649,2.729 -2.821,-2.274 -2.137,-11.711 -2.193,-14.737 -0.244,-12.991 0.978,-25.921 0.54,-38.927 -0.438,-12.993 -0.009,-25.956 0.292,-38.947 0.301,-13.003 0.601,-26.007 0.907,-39.01 0.25,-10.571 -2.265,-22.762 2.749,-32.602 10.379,11.976 7.135,29.258 6.331,43.687"
id="path27"
style="fill:#969696"
inkscape:connector-curvature="0" />
<path d="M145.177,87.437c0.988,25.058,1.155,50.139,1.183,75.214c0.013,11.358,0.005,22.718,0.005,34.077 c0,1.782,0.651,4.979-0.428,6.579c-2.152,3.19-2.427-2.293-2.446-2.981c-0.175-6.101-0.312-12.202-0.37-18.306 c-0.233-24.164-0.411-48.273-0.979-72.433c-0.275-11.732,0.069-23.448,0.522-35.172c0.243-6.293,0.513-12.586,0.71-18.882 c0.128-4.116-0.891-8.615,2.99-11.388C146.64,58.581,146.323,73.043,145.177,87.437" id="path31" style="fill:#BFBFBF;"></path>
<path
d="m 95.001,51.744 c -1.75,28.572 -2.194,57.212 -1.738,85.831 0.216,13.561 0.746,27.112 1.23,40.665 0.248,6.934 0.492,13.867 0.735,20.801 0.229,6.533 -2.363,4.685 -7.43,5.211 -1.578,-28.564 -2.779,-57.147 -2.978,-85.757 -0.093,-13.326 -0.059,-26.656 0.183,-39.98 0.121,-6.69 0.447,-13.376 0.565,-20.066 0.106,-6.027 0.059,-12.19 3.418,-17.468 2.005,3.587 4.01,7.175 6.015,10.763"
id="path29"
style="fill:#969696"
inkscape:connector-curvature="0" />
<path d="M115.42,50.953c-1.174,28.427-1.397,56.849-0.762,85.292c0.306,13.686,0.66,27.37,1.144,41.051 c0.247,6.976,0.493,13.949,0.709,20.926c0.113,3.651,0.938,5.553-3.386,6.031c-0.947-29.533-2.22-59.063-2.748-88.608 c-0.248-13.869-0.502-27.894,0.314-41.748c0.369-6.252,1.427-12.552,0.738-18.821c-0.473-4.301-1.087-7.463,3.278-9.742 C114.97,47.199,115.34,49.065,115.42,50.953" id="path33" style="fill:#BFBFBF;"></path>
<path
d="m 145.177,87.437 c 0.988,25.058 1.155,50.139 1.183,75.214 0.013,11.358 0.005,22.718 0.005,34.077 0,1.782 0.651,4.979 -0.428,6.579 -2.152,3.19 -2.427,-2.293 -2.446,-2.981 -0.175,-6.101 -0.312,-12.202 -0.37,-18.306 -0.233,-24.164 -0.411,-48.273 -0.979,-72.433 -0.275,-11.732 0.069,-23.448 0.522,-35.172 0.243,-6.293 0.513,-12.586 0.71,-18.882 0.128,-4.116 -0.891,-8.615 2.99,-11.388 0.276,14.436 -0.041,28.898 -1.187,43.292"
id="path31"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
<path d="M177.626,47.312c-1.061,29.439-2.265,58.83-1.941,88.295c0.16,14.534-0.268,29.064-0.391,43.597 c-0.057,6.632-0.034,13.265,0.191,19.893c0.047,1.372,0.716,3.423-0.136,4.674c-0.996,1.462-2.972,0.332-3.359-0.947 c-1.224-4.041-0.131-9.819-0.212-13.987c-0.144-7.308-0.277-14.616-0.389-21.924c-0.224-14.616-0.359-29.235-0.309-43.853 c0.051-14.634,0.195-29.277,0.585-43.906c0.269-10.124-2.24-25.542,5.248-33.028C177.136,46.464,177.512,46.979,177.626,47.312" id="path35" style="fill:#BFBFBF;"></path>
<path
d="m 115.42,50.953 c -1.174,28.427 -1.397,56.849 -0.762,85.292 0.306,13.686 0.66,27.37 1.144,41.051 0.247,6.976 0.493,13.949 0.709,20.926 0.113,3.651 0.938,5.553 -3.386,6.031 -0.947,-29.533 -2.22,-59.063 -2.748,-88.608 -0.248,-13.869 -0.502,-27.894 0.314,-41.748 0.369,-6.252 1.427,-12.552 0.738,-18.821 -0.473,-4.301 -1.087,-7.463 3.278,-9.742 0.263,1.865 0.633,3.731 0.713,5.619"
id="path33"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
<path d="M82.18,85.063c0.151,25.021-0.078,50.047,0.583,75.063c0.338,12.787,1.207,25.561,1.396,38.35 c0.032,2.203,1.505,6.316-2.127,5.501c-1.73-0.388-1.261-14.663-1.35-16.759c-1.034-24.321-2.365-48.646-2.663-72.991 c-0.149-12.221-0.477-24.412,0.259-36.618c0.576-9.556-1.54-21.67,4.694-29.426C82.115,60.46,82.981,72.783,82.18,85.063" id="path37" style="fill:#BFBFBF;"></path>
<path
d="m 177.626,47.312 c -1.061,29.439 -2.265,58.83 -1.941,88.295 0.16,14.534 -0.268,29.064 -0.391,43.597 -0.057,6.632 -0.034,13.265 0.191,19.893 0.047,1.372 0.716,3.423 -0.136,4.674 -0.996,1.462 -2.972,0.332 -3.359,-0.947 -1.224,-4.041 -0.131,-9.819 -0.212,-13.987 -0.144,-7.308 -0.277,-14.616 -0.389,-21.924 -0.224,-14.616 -0.359,-29.235 -0.309,-43.853 0.051,-14.634 0.195,-29.277 0.585,-43.906 0.269,-10.124 -2.24,-25.542 5.248,-33.028 0.223,0.338 0.599,0.853 0.713,1.186"
id="path35"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
<path d="M76.56,148.457c0.157,10.251,0.532,20.496,0.961,30.738c0.296,7.057,2.459,16.297,1.102,23.311 c-0.727,3.755-9.991,3.729-10.081-0.096c-0.255-10.852-0.904-21.675-1.379-32.518c-0.936-21.354-1.054-42.732-1.057-64.104 c-0.001-9.405-0.544-18.909-0.314-28.295c0.123-5.044,2.847-7.453,5.167-11.591c2.299-4.102,3.548-8.677,5.603-12.893 C75.467,84.813,75.458,116.654,76.56,148.457" id="path39" style="fill:#E3E3E3;"></path>
<path
d="m 82.18,85.063 c 0.151,25.021 -0.078,50.047 0.583,75.063 0.338,12.787 1.207,25.561 1.396,38.35 0.032,2.203 1.505,6.316 -2.127,5.501 -1.73,-0.388 -1.261,-14.663 -1.35,-16.759 -1.034,-24.321 -2.365,-48.646 -2.663,-72.991 -0.149,-12.221 -0.477,-24.412 0.259,-36.618 0.576,-9.556 -1.54,-21.67 4.694,-29.426 -0.857,12.277 0.009,24.6 -0.792,36.88"
id="path37"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
<path d="M207.781,73.825c0.317,21.825-0.792,43.493-0.792,65.278c0,10.738,0,21.478,0,32.216 c0,5.481,0,10.963,0,16.445c0,2.65,1.686,12.848-0.612,14.655c-4.082,3.21-2.532-8.896-2.516-10.782 c0.052-5.517,0.092-11.034,0.129-16.552c0.074-11.035,0.133-22.071,0.23-33.106c0.202-22.987,0.569-45.978,1.582-68.945 C206.461,73.297,207.122,73.561,207.781,73.825" id="path41" style="fill:#BFBFBF;"></path>
<path
d="m 76.56,148.457 c 0.157,10.251 0.532,20.496 0.961,30.738 0.296,7.057 2.459,16.297 1.102,23.311 -0.727,3.755 -9.991,3.729 -10.081,-0.096 -0.255,-10.852 -0.904,-21.675 -1.379,-32.518 -0.936,-21.354 -1.054,-42.732 -1.057,-64.104 -10e-4,-9.405 -0.544,-18.909 -0.314,-28.295 0.123,-5.044 2.847,-7.453 5.167,-11.591 2.299,-4.102 3.548,-8.677 5.603,-12.893 -1.095,31.804 -1.104,63.645 -0.002,95.448"
id="path39"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path d="M63.66,154.472c0.783,16.721,1.787,33.437,2.058,50.177c-2.401-0.132-4.802-0.265-7.203-0.396 c4.111-2.813,0.355-17.984,0.207-22.342c-0.486-14.264-0.922-28.527-1.294-42.794c-0.371-14.189-1.13-28.355-1.666-42.537 c-0.121-3.195-2.525-15.268-0.633-17.566c1.9-2.309,5.626-3.449,8.214-4.792c0.066,13.375,0.132,26.75,0.198,40.125 C63.607,127.713,64.891,141.124,63.66,154.472" id="path43" style="fill:#BFBFBF;"></path>
<path
d="m 207.781,73.825 c 0.317,21.825 -0.792,43.493 -0.792,65.278 0,10.738 0,21.478 0,32.216 0,5.481 0,10.963 0,16.445 0,2.65 1.686,12.848 -0.612,14.655 -4.082,3.21 -2.532,-8.896 -2.516,-10.782 0.052,-5.517 0.092,-11.034 0.129,-16.552 0.074,-11.035 0.133,-22.071 0.23,-33.106 0.202,-22.987 0.569,-45.978 1.582,-68.945 0.659,0.263 1.32,0.527 1.979,0.791"
id="path41"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
<path d="M216.96,80.235c0.446,21.664-0.711,43.313-1.313,64.962c-0.296,10.651-0.357,21.305-0.45,31.959 c-0.03,3.503,1.627,25.193-1.97,25.515c-5.911,0.527-3.371-20.418-3.351-24.031c0.063-10.85,0.132-21.698,0.181-32.548 c0.104-23.14,0.117-46.282,0.571-69.418C213.076,77.254,214.519,79.697,216.96,80.235" id="path45" style="fill:#E3E3E3;"></path>
<path
d="m 63.66,154.472 c 0.783,16.721 1.787,33.437 2.058,50.177 -2.401,-0.132 -4.802,-0.265 -7.203,-0.396 4.111,-2.813 0.355,-17.984 0.207,-22.342 C 58.236,167.647 57.8,153.384 57.428,139.117 57.057,124.928 56.298,110.762 55.762,96.58 55.641,93.385 53.237,81.312 55.129,79.014 c 1.9,-2.309 5.626,-3.449 8.214,-4.792 0.066,13.375 0.132,26.75 0.198,40.125 0.066,13.366 1.35,26.777 0.119,40.125"
id="path43"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
<path d="M52.421,79.84c0.88,22.406,1.916,44.805,2.742,67.213c0.432,11.725,0.802,23.45,1.042,35.18 c0.088,4.317-2.453,18.714,1.124,22.02c-4.652,0-3.771-2.246-3.999-6.369c-0.426-7.703-0.767-15.425-0.831-23.14 c-0.122-14.887-0.063-29.809-0.743-44.682C51.631,127.329,46.842,79.502,52.421,79.84" id="path47" style="fill:#E3E3E3;"></path>
<path
d="m 216.96,80.235 c 0.446,21.664 -0.711,43.313 -1.313,64.962 -0.296,10.651 -0.357,21.305 -0.45,31.959 -0.03,3.503 1.627,25.193 -1.97,25.515 -5.911,0.527 -3.371,-20.418 -3.351,-24.031 0.063,-10.85 0.132,-21.698 0.181,-32.548 0.104,-23.14 0.117,-46.282 0.571,-69.418 2.448,0.58 3.891,3.023 6.332,3.561"
id="path45"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path d="M233.027,205.044c2.539,9.07-2.377,10.524-9.861,11.079c-9.534,0.707-19.151,0.729-28.707,0.77 c-20.313,0.088-40.627,0.037-60.94,0.133c-19.374,0.091-38.575,1.29-57.922,1.899c-9.106,0.287-18.38,0.342-27.438-0.75 c-3.971-0.479-5.018,0.146-5.204-3.817c-0.107-2.286-0.019-4.574-0.109-6.859c31.892,0,63.831-1.94,95.708-1.301 c16.213,0.325,32.394,0.372,48.607,0.431C202.487,206.683,217.678,205.044,233.027,205.044" id="path49" style="fill:#BFBFBF;"></path>
<path
d="m 52.421,79.84 c 0.88,22.406 1.916,44.805 2.742,67.213 0.432,11.725 0.802,23.45 1.042,35.18 0.088,4.317 -2.453,18.714 1.124,22.02 -4.652,0 -3.771,-2.246 -3.999,-6.369 -0.426,-7.703 -0.767,-15.425 -0.831,-23.14 -0.122,-14.887 -0.063,-29.809 -0.743,-44.682 -0.125,-2.733 -4.914,-50.56 0.665,-50.222"
id="path47"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path d="M249.092,224.275c-37.66,2.193-75.668-0.496-113.257,2.421c-36.526,2.834-73.583,2.146-110.243,1.22 c14.839-9.382,31.379-6.451,47.913-6.075c20.089,0.457,40.228-2.287,60.35-2.391c20.478-0.105,40.953,0.454,61.432,0.33 c10.018-0.061,19.98-0.497,29.972-1.229C234.292,217.891,240.738,221.712,249.092,224.275" id="path51" style="fill:#E3E3E3;"></path>
<path
d="m 233.027,205.044 c 2.539,9.07 -2.377,10.524 -9.861,11.079 -9.534,0.707 -19.151,0.729 -28.707,0.77 -20.313,0.088 -40.627,0.037 -60.94,0.133 -19.374,0.091 -38.575,1.29 -57.922,1.899 -9.106,0.287 -18.38,0.342 -27.438,-0.75 -3.971,-0.479 -5.018,0.146 -5.204,-3.817 -0.107,-2.286 -0.019,-4.574 -0.109,-6.859 31.892,0 63.831,-1.94 95.708,-1.301 16.213,0.325 32.394,0.372 48.607,0.431 15.326,0.054 30.517,-1.585 45.866,-1.585"
id="path49"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
<path d="M255.108,245.961c-1.281,0.09-1.54,1.658-2.793,1.662c-2.189,0.008-4.379,0.015-6.568,0.022 c-5.926,0.021-11.852,0.04-17.777,0.061c-11.854,0.041-23.707,0.08-35.561,0.121c-23.952,0.081-47.894,0.144-71.839,0.773 c-23.992,0.63-47.979,1.343-71.98,1.604c-6.661,0.072-13.326,0.174-19.988,0.186c-3.327,0.005-4.571,1.054-4.644-2.605 c-0.115-5.806-0.229-11.61-0.344-17.415c23.308,2.299,47.056,0.97,70.449,1.107c23.82,0.141,47.644-2.438,71.469-3.03 c23.765-0.591,47.532-0.933,71.303-0.928c3.688,0.001,17.249-3.522,18.395,1.103C256.617,234.223,255.108,240.288,255.108,245.961" id="path53" style="fill:#BFBFBF;"></path>
<path
d="m 249.092,224.275 c -37.66,2.193 -75.668,-0.496 -113.257,2.421 -36.526,2.834 -73.583,2.146 -110.243,1.22 14.839,-9.382 31.379,-6.451 47.913,-6.075 20.089,0.457 40.228,-2.287 60.35,-2.391 20.478,-0.105 40.953,0.454 61.432,0.33 10.018,-0.061 19.98,-0.497 29.972,-1.229 9.033,-0.66 15.479,3.161 23.833,5.724"
id="path51"
style="fill:#e3e3e3"
inkscape:connector-curvature="0" />
<path
d="m 255.108,245.961 c -1.281,0.09 -1.54,1.658 -2.793,1.662 -2.189,0.008 -4.379,0.015 -6.568,0.022 -5.926,0.021 -11.852,0.04 -17.777,0.061 -11.854,0.041 -23.707,0.08 -35.561,0.121 -23.952,0.081 -47.894,0.144 -71.839,0.773 -23.992,0.63 -47.979,1.343 -71.98,1.604 -6.661,0.072 -13.326,0.174 -19.988,0.186 -3.327,0.005 -4.571,1.054 -4.644,-2.605 -0.115,-5.806 -0.229,-11.61 -0.344,-17.415 23.308,2.299 47.056,0.97 70.449,1.107 23.82,0.141 47.644,-2.438 71.469,-3.03 23.765,-0.591 47.532,-0.933 71.303,-0.928 3.688,0.001 17.249,-3.522 18.395,1.103 1.387,5.601 -0.122,11.666 -0.122,17.339"
id="path53"
style="fill:#bfbfbf"
inkscape:connector-curvature="0" />
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

View File

@ -0,0 +1,42 @@
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import Tag
class AdvancedUserRecipe1282101454(BasicNewsRecipe):
title = 'BuckMasters In The Kitchen'
language = 'en'
__author__ = 'TonytheBookworm & Starson17'
description = 'Learn how to cook all those outdoor varments'
publisher = 'BuckMasters.com'
category = 'food,cooking,recipes'
oldest_article = 365
max_articles_per_feed = 100
conversion_options = {'linearize_tables' : True}
masthead_url = 'http://www.buckmasters.com/Portals/_default/Skins/BM_10/images/header_bg.jpg'
keep_only_tags = [
dict(name='table', attrs={'class':['containermaster_black']})
]
remove_tags_after = [dict(name='div', attrs={'align':['left']})]
feeds = [
('Recipes', 'http://www.buckmasters.com/DesktopModules/DnnForge%20-%20NewsArticles/RSS.aspx?TabID=292&ModuleID=658&MaxCount=25'),
]
def preprocess_html(self, soup):
item = soup.find('a', attrs={'class':['MenuTopSelected']})
if item:
item.parent.extract()
for img_tag in soup.findAll('img'):
parent_tag = img_tag.parent
if parent_tag.name == 'a':
new_tag = Tag(soup,'p')
new_tag.insert(0,img_tag)
parent_tag.replaceWith(new_tag)
elif parent_tag.name == 'p':
if not self.tag_to_string(parent_tag) == '':
new_div = Tag(soup,'div')
new_tag = Tag(soup,'p')
new_tag.insert(0,img_tag)
parent_tag.replaceWith(new_div)
new_div.insert(0,new_tag)
new_div.insert(1,parent_tag)
return soup

View File

@ -0,0 +1,64 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__author__ = 'somedayson & TonytheBookworm, revised by Cynthia Clavey'
__copyright__ = '2010, Cynthia Clavey cynvision@yahoo.com'
__version__ = '1.02'
__date__ = '05, september 2010'
__docformat__ = 'restructuredtext en'
from calibre.web.feeds.recipes import BasicNewsRecipe
class AdvancedUserRecipe1283666183(BasicNewsRecipe):
title = u'Journal Gazette Ft. Wayne IN'
__author__ = 'cynvision'
oldest_article = 1
max_articles_per_feed = 8
no_stylesheets = True
remove_javascript = True
use_embedded_content = False
keep_only_tags = [dict(name='div', attrs={'id':'mainContent'})]
extra_css = '#copyinfo { font-size: 6 ;} \n #photocredit { font-size: 6 ;} \n .pubinfo { font-size: 6 ;}'
masthead_url = 'http://www.journalgazette.net/img/icons/jgmini.gif'
# cover_url = 'http://www.journalgazette.net/img/icons/jgmini.gif'
encoding = 'cp1252'
feeds = [(u'Opinion', u'http://journalgazette.net/apps/pbcs.dll/section?Category=EDIT&template=blogrss&mime=xml'),
(u'Local News',u'http://journalgazette.net/apps/pbcs.dll/section?Category=LOCAL&template=blogrss&mime=xml') ,
(u'Sports',u'http://journalgazette.net/apps/pbcs.dll/section?Category=SPORTS&template=blogrss&mime=xml' ),
(u'Features',u'http://journalgazette.net/apps/pbcs.dll/section?Category=FEAT&template=blogrss&mime=xml'),
(u'Business',u'http://journalgazette.net/apps/pbcs.dll/section?Category=BIZ&template=blogrss&mime=xml'),
(u'Ice Chips',u'http://journalgazette.net/apps/pbcs.dll/section?Category=BLOGS11&template=blogrss&mime=xml '),
(u'Entertainment',u'http://journalgazette.net/apps/pbcs.dll/section?Category=ENT&template=blogrss&mime=xml'),
(u'Food',u'http://journalgazette.net/apps/pbcs.dll/section?Category=FOOD&template=blogrss&mime=xml')
]
def print_version(self, url):
split1 = url.split("/")
#print 'THE SPLIT IS: ', split1
#url1 = split1[0]
#url2 = split1[1]
url3 = split1[2]
#url4 = split1[3]
url5 = split1[4]
url6 = split1[5]
url7 = split1[6]
#url8 = split1[7]
#need to convert to print_version
#originalversion is : http://www.journalgazette.net/article/20100905/EDIT10/309059959/1021/EDIT
#printversion should be: http://www.journalgazette.net/apps/pbcs.dll/article?AID=/20100905/EDIT10/309059959/-1/EDIT01&template=printart
#results of the split
#THE SPLIT IS: [u'http:', u'', u'www.journalgazette.net', u'article', u'20100905', u'EDIT10', u'309059959', u'1021', u'EDIT']
print_url = 'http://' + url3 + '/apps/pbcs.dll/article?AID=/' + url5 + '/' + url6 + '/' + url7 + '/-1/EDIT01&template=printart'
#print 'THIS URL WILL PRINT: ', print_url # this is a test string to see what the url is it will return
return print_url
def preprocess_html(self, soup):
for item in soup.findAll(style=True):
del item['style']
return soup

View File

@ -0,0 +1,46 @@
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1282101454(BasicNewsRecipe):
title = 'The Walrus Mag'
language = 'en'
__author__ = 'TonytheBookworm'
description = 'national general interest magazine about Canada and its place in the world'
publisher = 'Tony Stegall'
category = 'Canada, news'
oldest_article = 365
max_articles_per_feed = 100
masthead_url = 'http://www.walrusmagazine.com/images/wordmark.png'
keep_only_tags = [
dict(name='h1'),
dict(name='div', attrs={'id':['prbody']})
# ,dict(attrs={'id':['cxArticleText','cxArticleBodyText']})
]
feeds = [
('Walrus Magazine', 'http://feeds.feedburner.com/WalrusFeatureArticles?format=xml'),
]
def print_version(self, url):
split1 = url.split("/articles/")
#print 'THE SPLIT IS: ', split1
url1 = split1[0]
#print 'url1 is: ',url1
url2 = split1[1]
#print 'url2 is: ',url2
#need to convert to print_version
#originalversion is : http://www.walrusmagazine.com/articles/2010.09-frontier-no-one-can-hear-you-scream/
#printversion should be: http://www.walrusmagazine.com/print/2010.09-frontier-no-one-can-hear-you-scream/
print_url = url1 + '/print/' + url2
#print 'THIS URL WILL PRINT: ', print_url # this is a test string to see what the url is it will return
return print_url

View File

@ -0,0 +1,153 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
from calibre.web.feeds.news import BasicNewsRecipe
import copy
class WallStreetJournal(BasicNewsRecipe):
title = 'Wall Street Journal (free)'
__author__ = 'Kovid Goyal, Sujata Raman, Joshua Oster-Morris, Starson17'
description = 'News and current affairs'
language = 'en'
cover_url = 'http://dealbreaker.com/images/thumbs/Wall%20Street%20Journal%20A1.JPG'
max_articles_per_feed = 1000
timefmt = ' [%a, %b %d, %Y]'
no_stylesheets = True
extra_css = '''h1{color:#093D72 ; font-size:large ; font-family:Georgia,"Century Schoolbook","Times New Roman",Times,serif; }
h2{color:#474537; font-family:Georgia,"Century Schoolbook","Times New Roman",Times,serif; font-size:small; font-style:italic;}
.subhead{color:gray; font-family:Georgia,"Century Schoolbook","Times New Roman",Times,serif; font-size:small; font-style:italic;}
.insettipUnit {color:#666666; font-family:Arial,Sans-serif;font-size:xx-small }
.targetCaption{ font-size:x-small; color:#333333; font-family:Arial,Helvetica,sans-serif}
.article{font-family :Arial,Helvetica,sans-serif; font-size:x-small}
.tagline {color:#333333; font-size:xx-small}
.dateStamp {color:#666666; font-family:Arial,Helvetica,sans-serif}
h3{color:blue ;font-family:Arial,Helvetica,sans-serif; font-size:xx-small}
.byline{color:blue;font-family:Arial,Helvetica,sans-serif; font-size:xx-small}
h6{color:#333333; font-family:Georgia,"Century Schoolbook","Times New Roman",Times,serif; font-size:small;font-style:italic; }
.paperLocation{color:#666666; font-size:xx-small}'''
remove_tags_before = dict(name='h1')
remove_tags = [
dict(id=["articleTabs_tab_article", "articleTabs_tab_comments", "articleTabs_tab_interactive","articleTabs_tab_video","articleTabs_tab_map","articleTabs_tab_slideshow"]),
{'class':['footer_columns','network','insetCol3wide','interactive','video','slideshow','map','insettip','insetClose','more_in', "insetContent", 'articleTools_bottom', 'aTools', "tooltip", "adSummary", "nav-inline"]},
dict(name='div', attrs={'data-flash-settings':True}),
{'class':['insetContent embedType-interactive insetCol3wide','insetCol6wide','insettipUnit']},
dict(rel='shortcut icon'),
]
remove_tags_after = [dict(id="article_story_body"), {'class':"article story"},]
def postprocess_html(self, soup, first):
for tag in soup.findAll(name=['table', 'tr', 'td']):
tag.name = 'div'
for tag in soup.findAll('div', dict(id=["articleThumbnail_1", "articleThumbnail_2", "articleThumbnail_3", "articleThumbnail_4", "articleThumbnail_5", "articleThumbnail_6", "articleThumbnail_7"])):
tag.extract()
return soup
def wsj_get_index(self):
return self.index_to_soup('http://online.wsj.com/itp')
def wsj_add_feed(self,feeds,title,url):
self.log('Found section:', title)
if url.endswith('whatsnews'):
articles = self.wsj_find_wn_articles(url)
else:
articles = self.wsj_find_articles(url)
if articles:
feeds.append((title, articles))
return feeds
def parse_index(self):
soup = self.wsj_get_index()
date = soup.find('span', attrs={'class':'date-date'})
if date is not None:
self.timefmt = ' [%s]'%self.tag_to_string(date)
feeds = []
div = soup.find('div', attrs={'class':'itpHeader'})
div = div.find('ul', attrs={'class':'tab'})
for a in div.findAll('a', href=lambda x: x and '/itp/' in x):
pageone = a['href'].endswith('pageone')
if pageone:
title = 'Front Section'
url = 'http://online.wsj.com' + a['href']
feeds = self.wsj_add_feed(feeds,title,url)
title = 'What''s News'
url = url.replace('pageone','whatsnews')
feeds = self.wsj_add_feed(feeds,title,url)
else:
title = self.tag_to_string(a)
url = 'http://online.wsj.com' + a['href']
feeds = self.wsj_add_feed(feeds,title,url)
return feeds
def wsj_find_wn_articles(self, url):
soup = self.index_to_soup(url)
articles = []
whats_news = soup.find('div', attrs={'class':lambda x: x and 'whatsNews-simple' in x})
if whats_news is not None:
for a in whats_news.findAll('a', href=lambda x: x and '/article/' in x):
container = a.findParent(['p'])
meta = a.find(attrs={'class':'meta_sectionName'})
if meta is not None:
meta.extract()
title = self.tag_to_string(a).strip()
url = a['href']
desc = ''
if container is not None:
desc = self.tag_to_string(container)
articles.append({'title':title, 'url':url,
'description':desc, 'date':''})
self.log('\tFound WN article:', title)
return articles
def wsj_find_articles(self, url):
soup = self.index_to_soup(url)
whats_news = soup.find('div', attrs={'class':lambda x: x and 'whatsNews-simple' in x})
if whats_news is not None:
whats_news.extract()
articles = []
flavorarea = soup.find('div', attrs={'class':lambda x: x and 'ahed' in x})
if flavorarea is not None:
flavorstory = flavorarea.find('a', href=lambda x: x and x.startswith('/article'))
if flavorstory is not None:
flavorstory['class'] = 'mjLinkItem'
metapage = soup.find('span', attrs={'class':lambda x: x and 'meta_sectionName' in x})
if metapage is not None:
flavorstory.append( copy.copy(metapage) ) #metapage should always be A1 because that should be first on the page
for a in soup.findAll('a', attrs={'class':'mjLinkItem'}, href=True):
container = a.findParent(['li', 'div'])
meta = a.find(attrs={'class':'meta_sectionName'})
if meta is not None:
meta.extract()
title = self.tag_to_string(a).strip() + ' [%s]'%self.tag_to_string(meta)
url = 'http://online.wsj.com'+a['href']
desc = ''
p = container.find('p')
if p is not None:
desc = self.tag_to_string(p)
articles.append({'title':title, 'url':url,
'description':desc, 'date':''})
self.log('\tFound article:', title)
return articles
def cleanup(self):
self.browser.open('http://online.wsj.com/logout?url=http://online.wsj.com')

View File

@ -393,9 +393,16 @@ class PreferencesPlugin(Plugin): # {{{
#: The category name displayed to the user for this plugin
gui_category = None
#: The name displayed to the user for this plugin
gui_name = None
#: The icon for this plugin, should be an absolute path
icon = None
#: The description used for tooltips and the like
description = None
def create_widget(self, parent=None):
'''
Create and return the actual Qt widget used for setting this group of

View File

@ -678,133 +678,181 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
class LookAndFeel(PreferencesPlugin):
name = 'Look & Feel'
icon = I('lookfeel.png')
gui_name = _('Look and Feel')
category = 'Interface'
gui_category = _('Interface')
category_order = 1
name_order = 1
config_widget = 'calibre.gui2.preferences.look_feel'
description = _('Adjust the look and feel of the calibre interface'
' to suit your tastes')
class Behavior(PreferencesPlugin):
name = 'Behavior'
icon = I('config.png')
gui_name = _('Behavior')
category = 'Interface'
gui_category = _('Interface')
category_order = 1
name_order = 2
config_widget = 'calibre.gui2.preferences.behavior'
description = _('Change the way calibre behaves')
class Columns(PreferencesPlugin):
name = 'Custom Columns'
icon = I('column.png')
gui_name = _('Add your own columns')
category = 'Interface'
gui_category = _('Interface')
category_order = 1
name_order = 3
config_widget = 'calibre.gui2.preferences.columns'
description = _('Add/remove your own columns to the calibre book list')
class Toolbar(PreferencesPlugin):
name = 'Toolbar'
icon = I('wizard.png')
gui_name = _('Customize the toolbar')
category = 'Interface'
gui_category = _('Interface')
category_order = 1
name_order = 4
config_widget = 'calibre.gui2.preferences.toolbar'
description = _('Customize the toolbars and context menus, changing which'
' actions are available in each')
class InputOptions(PreferencesPlugin):
name = 'Input Options'
icon = I('arrow-down.png')
gui_name = _('Input Options')
category = 'Conversion'
gui_category = _('Conversion')
category_order = 2
name_order = 1
config_widget = 'calibre.gui2.preferences.conversion:InputOptions'
description = _('Set conversion options specific to each input format')
class CommonOptions(PreferencesPlugin):
name = 'Common Options'
icon = I('convert.png')
gui_name = _('Common Options')
category = 'Conversion'
gui_category = _('Conversion')
category_order = 2
name_order = 2
config_widget = 'calibre.gui2.preferences.conversion:CommonOptions'
description = _('Set conversion options common to all formats')
class OutputOptions(PreferencesPlugin):
name = 'Output Options'
icon = I('arrow-up.png')
gui_name = _('Output Options')
category = 'Conversion'
gui_category = _('Conversion')
category_order = 2
name_order = 3
config_widget = 'calibre.gui2.preferences.conversion:OutputOptions'
description = _('Set conversion options specific to each output format')
class Adding(PreferencesPlugin):
name = 'Adding'
icon = I('add_book.png')
gui_name = _('Adding books')
category = 'Import/Export'
gui_category = _('Import/Export')
category_order = 3
name_order = 1
config_widget = 'calibre.gui2.preferences.adding'
description = _('Control how calibre reads metadata from files when '
'adding books')
class Saving(PreferencesPlugin):
name = 'Saving'
icon = I('save.png')
gui_name = _('Saving books to disk')
category = 'Import/Export'
gui_category = _('Import/Export')
category_order = 3
name_order = 2
config_widget = 'calibre.gui2.preferences.saving'
description = _('Control how calibre exports files from its database '
'to disk when using Save to disk')
class Sending(PreferencesPlugin):
name = 'Sending'
icon = I('sync.png')
gui_name = _('Sending books to devices')
category = 'Import/Export'
gui_category = _('Import/Export')
category_order = 3
name_order = 3
config_widget = 'calibre.gui2.preferences.sending'
description = _('Control how calibre transfers files to your '
'ebook reader')
class Email(PreferencesPlugin):
name = 'Email'
gui_name = _('Sending books by email')
icon = I('mail.png')
gui_name = _('Sharing books by email')
category = 'Sharing'
gui_category = _('Sharing')
category_order = 4
name_order = 1
config_widget = 'calibre.gui2.preferences.emailp'
description = _('Setup sharing of books via email. Can be used '
'for automatic sending of downloaded news to your devices')
class Server(PreferencesPlugin):
name = 'Server'
icon = I('network-server.png')
gui_name = _('Sharing over the net')
category = 'Sharing'
gui_category = _('Sharing')
category_order = 4
name_order = 2
config_widget = 'calibre.gui2.preferences.server'
description = _('Setup the calibre Content Server which will '
'give you access to your calibre library from anywhere, '
'on any device, over the internet')
class Plugins(PreferencesPlugin):
name = 'Plugins'
icon = I('plugins.png')
gui_name = _('Plugins')
category = 'Advanced'
gui_category = _('Advanced')
category_order = 5
name_order = 1
config_widget = 'calibre.gui2.preferences.plugins'
description = _('Add/remove/customize various bits of calibre '
'functionality')
class Tweaks(PreferencesPlugin):
name = 'Tweaks'
icon = I('drawer.png')
gui_name = _('Tweaks')
category = 'Advanced'
gui_category = _('Advanced')
category_order = 5
name_order = 2
config_widget = 'calibre.gui2.preferences.tweaks'
description = _('Fine tune how calibre behaves in various contexts')
class Misc(PreferencesPlugin):
name = 'Misc'
icon = I('exec.png')
gui_name = _('Miscellaneous')
category = 'Advanced'
gui_category = _('Advanced')
category_order = 5
name_order = 3
config_widget = 'calibre.gui2.preferences.misc'
description = _('Miscellaneous advanced configuration')
plugins += [LookAndFeel, Behavior, Columns, Toolbar, InputOptions,
CommonOptions, OutputOptions, Adding, Saving, Sending, Email, Server,
Plugins, Tweaks]
Plugins, Tweaks, Misc]
#}}}

View File

@ -87,7 +87,7 @@ class MIBUK(USBMS):
name = 'MiBuk Wolder Device Interface'
description = _('Communicate with the MiBuk Wolder reader.')
author = 'Kovid Goyal'
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['windows']
FORMATS = ['epub', 'mobi', 'prc', 'fb2', 'txt', 'rtf', 'pdf']

View File

@ -159,7 +159,7 @@ class DeleteAction(InterfaceAction):
if self.gui.stack.currentIndex() == 0:
if not confirm('<p>'+_('The selected books will be '
'<b>permanently deleted</b> and the files '
'removed from your computer. Are you sure?')
'removed from your calibre library. Are you sure?')
+'</p>', 'library_delete_books', self.gui):
return
ci = view.currentIndex()

View File

@ -122,7 +122,7 @@ class ConnectShareAction(InterfaceAction):
self.share_conn_menu.toggle_server.connect(self.toggle_content_server)
self.share_conn_menu.config_email.connect(partial(
self.gui.iactions['Preferences'].do_config,
initial_category='email'))
initial_plugin=('Sharing', 'Email')))
self.qaction.setMenu(self.share_conn_menu)
self.share_conn_menu.connect_to_folder.connect(self.gui.connect_to_folder)
self.share_conn_menu.connect_to_itunes.connect(self.gui.connect_to_itunes)

View File

@ -51,7 +51,8 @@ class EditMetadataAction(InterfaceAction):
self.merge_books)
mb.addSeparator()
mb.addAction(_('Merge into first selected book - keep others'),
partial(self.merge_books, safe_merge=True))
partial(self.merge_books, safe_merge=True),
Qt.AltModifier+Qt.Key_M)
self.merge_menu = mb
self.action_merge.setMenu(mb)
md.addSeparator()

View File

@ -8,8 +8,8 @@ __docformat__ = 'restructuredtext en'
from PyQt4.Qt import QIcon, QMenu
from calibre.gui2.actions import InterfaceAction
from calibre.gui2.dialogs.config import ConfigDialog
from calibre.gui2 import error_dialog, config
from calibre.gui2.preferences.main import Preferences
from calibre.gui2 import error_dialog
class PreferencesAction(InterfaceAction):
@ -28,7 +28,7 @@ class PreferencesAction(InterfaceAction):
x.triggered.connect(self.do_config)
def do_config(self, checked=False, initial_category='general'):
def do_config(self, checked=False, initial_plugin=None):
if self.gui.job_manager.has_jobs():
d = error_dialog(self.gui, _('Cannot configure'),
_('Cannot configure while there are running jobs.'))
@ -39,20 +39,12 @@ class PreferencesAction(InterfaceAction):
_('Cannot configure before calibre is restarted.'))
d.exec_()
return
d = ConfigDialog(self.gui, self.gui.library_view,
server=self.gui.content_server, initial_category=initial_category)
d = Preferences(self.gui, initial_plugin=initial_plugin)
d.show()
d.exec_()
self.gui.content_server = d.server
if self.gui.content_server is not None:
self.gui.content_server.state_callback = \
self.Dispatcher(self.gui.iactions['Connect Share'].content_server_state_changed)
self.gui.content_server.state_callback(self.gui.content_server.is_running)
if d.result() == d.Accepted:
self.gui.search.search_as_you_type(config['search_as_you_type'])
if d.committed:
self.gui.must_restart_before_config = d.must_restart
self.gui.tags_view.set_new_model() # in case columns changed
self.gui.iactions['Save To Disk'].reread_prefs()
self.gui.tags_view.recount()
self.gui.create_device_menu()
self.gui.set_device_menu_items_state(bool(self.gui.device_connected))

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import textwrap
from PyQt4.Qt import QTabWidget
from calibre.gui2.dialogs.config.add_save_ui import Ui_TabWidget
from calibre.library.save_to_disk import config
from calibre.utils.config import prefs
from calibre.gui2.widgets import FilenamePattern
class AddSave(QTabWidget, Ui_TabWidget):
def __init__(self, parent=None):
QTabWidget.__init__(self, parent)
self.setupUi(self)
while self.count() > 3:
self.removeTab(3)
c = config()
opts = c.parse()
for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf',
'replace_whitespace', 'to_lowercase'):
g = getattr(self, 'opt_'+x)
g.setChecked(getattr(opts, x))
help = '\n'.join(textwrap.wrap(c.get_option(x).help, 75))
g.setToolTip(help)
g.setWhatsThis(help)
for x in ('formats', 'timefmt'):
g = getattr(self, 'opt_'+x)
g.setText(getattr(opts, x))
help = '\n'.join(textwrap.wrap(c.get_option(x).help, 75))
g.setToolTip(help)
g.setWhatsThis(help)
self.opt_read_metadata_from_filename.setChecked(not prefs['read_file_metadata'])
self.filename_pattern = FilenamePattern(self)
self.metadata_box.layout().insertWidget(0, self.filename_pattern)
self.opt_swap_author_names.setChecked(prefs['swap_author_names'])
self.opt_add_formats_to_existing.setChecked(prefs['add_formats_to_existing'])
if prefs['manage_device_metadata'] == 'manual':
self.manage_device_metadata.setCurrentIndex(0)
elif prefs['manage_device_metadata'] == 'on_send':
self.manage_device_metadata.setCurrentIndex(1)
else:
self.manage_device_metadata.setCurrentIndex(2)
help = '\n'.join(textwrap.wrap(c.get_option('template').help, 75))
self.save_template.initialize('save_to_disk', opts.template, help)
self.send_template.initialize('send_to_device', opts.send_template, help)
def validate(self):
return self.save_template.validate() and self.send_template.validate()
def save_settings(self):
if not self.validate():
return False
c = config()
for x in ('asciiize', 'update_metadata', 'save_cover', 'write_opf',
'replace_whitespace', 'to_lowercase'):
c.set(x, getattr(self, 'opt_'+x).isChecked())
for x in ('formats', 'timefmt'):
val = unicode(getattr(self, 'opt_'+x).text()).strip()
if x == 'formats' and not val:
val = 'all'
c.set(x, val)
self.save_template.save_settings(c, 'template')
self.send_template.save_settings(c, 'send_template')
prefs['read_file_metadata'] = not bool(self.opt_read_metadata_from_filename.isChecked())
pattern = self.filename_pattern.commit()
prefs['filename_pattern'] = pattern
prefs['swap_author_names'] = bool(self.opt_swap_author_names.isChecked())
prefs['add_formats_to_existing'] = bool(self.opt_add_formats_to_existing.isChecked())
if self.manage_device_metadata.currentIndex() == 0:
prefs['manage_device_metadata'] = 'manual'
elif self.manage_device_metadata.currentIndex() == 1:
prefs['manage_device_metadata'] = 'on_send'
else:
prefs['manage_device_metadata'] = 'on_connect'
return True
if __name__ == '__main__':
from PyQt4.Qt import QApplication
app=QApplication([])
a = AddSave()
a.show()
app.exec_()
a.save_settings()

View File

@ -1,280 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TabWidget</class>
<widget class="QTabWidget" name="TabWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>671</width>
<height>516</height>
</rect>
</property>
<property name="windowTitle">
<string>TabWidget</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>&amp;Adding books</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Here you can control how calibre will read metadata from the files you add to it. calibre can either read metadata from the contents of the file, or from the filename.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="opt_read_metadata_from_filename">
<property name="text">
<string>Read metadata only from &amp;file name</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="opt_swap_author_names">
<property name="toolTip">
<string>Swap the firstname and lastname of the author. This affects only metadata read from file names.</string>
</property>
<property name="text">
<string>&amp;Swap author firstname and lastname</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="opt_add_formats_to_existing">
<property name="toolTip">
<string>If an existing book with a similar title and author is found that does not have the format being added, the format is added
to the existing book, instead of creating a new entry. If the existing book already has the format, then it is silently ignored.
Title match ignores leading indefinite articles (&quot;the&quot;, &quot;a&quot;, &quot;an&quot;), punctuation, case, etc. Author match is exact.</string>
</property>
<property name="text">
<string>If books with similar titles and authors found, &amp;merge the new files automatically</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="metadata_box">
<property name="title">
<string>&amp;Configure metadata from file name</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>363</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>&amp;Saving books</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Here you can control how calibre will save your books when you click the Save to Disk button:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="opt_save_cover">
<property name="text">
<string>Save &amp;cover separately</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="opt_update_metadata">
<property name="text">
<string>Update &amp;metadata in saved copies</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="opt_write_opf">
<property name="text">
<string>Save metadata in &amp;OPF file</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="opt_asciiize">
<property name="text">
<string>Convert non-English characters to &amp;English equivalents</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Format &amp;dates as:</string>
</property>
<property name="buddy">
<cstring>opt_timefmt</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="opt_timefmt"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>File &amp;formats to save:</string>
</property>
<property name="buddy">
<cstring>opt_formats</cstring>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="opt_formats"/>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="opt_replace_whitespace">
<property name="text">
<string>Replace space with &amp;underscores</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="opt_to_lowercase">
<property name="text">
<string>Change paths to &amp;lowercase</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="SaveTemplate" name="save_template" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Sending to &amp;device</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Metadata &amp;management:</string>
</property>
<property name="buddy">
<cstring>manage_device_metadata</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="manage_device_metadata">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string extracomment="foobar">Manual management</string>
</property>
</item>
<item>
<property name="text">
<string>Only on send</string>
</property>
</item>
<item>
<property name="text">
<string>Automatic management</string>
</property>
</item>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>313</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="3">
<widget class="QLabel" name="label_41">
<property name="text">
<string>&lt;li&gt;&lt;b&gt;Manual Management&lt;/b&gt;: Calibre updates the metadata and adds collections only when a book is sent. With this option, calibre will never remove a collection.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Only on send&lt;/b&gt;: Calibre updates metadata and adds/removes collections for a book only when it is sent to the device. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;Automatic management&lt;/b&gt;: Calibre automatically keeps metadata on the device in sync with the calibre library, on every connect&lt;/li&gt;&lt;/ul&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_42">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="label_43">
<property name="text">
<string>Here you can control how calibre will save your books when you click the Send to Device button. This setting can be overriden for individual devices by customizing the device interface plugins in Preferences-&gt;Plugins</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="SaveTemplate" name="send_template" native="true"/>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>SaveTemplate</class>
<extends>QWidget</extends>
<header>calibre/gui2/dialogs/config/save_template.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

File diff suppressed because it is too large Load Diff

View File

@ -1,173 +0,0 @@
__license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid at kovidgoyal.net>'
'''Dialog to create a new custom column'''
import re
from functools import partial
from PyQt4.QtCore import SIGNAL
from PyQt4.Qt import QDialog, Qt, QListWidgetItem, QVariant
from calibre.gui2.dialogs.config.create_custom_column_ui import Ui_QCreateCustomColumn
from calibre.gui2 import error_dialog
class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn):
column_types = {
0:{'datatype':'text',
'text':_('Text, column shown in the tag browser'),
'is_multiple':False},
1:{'datatype':'*text',
'text':_('Comma separated text, like tags, shown in the tag browser'),
'is_multiple':True},
2:{'datatype':'comments',
'text':_('Long text, like comments, not shown in the tag browser'),
'is_multiple':False},
3:{'datatype':'series',
'text':_('Text column for keeping series-like information'),
'is_multiple':False},
4:{'datatype':'datetime',
'text':_('Date'), 'is_multiple':False},
5:{'datatype':'float',
'text':_('Floating point numbers'), 'is_multiple':False},
6:{'datatype':'int',
'text':_('Integers'), 'is_multiple':False},
7:{'datatype':'rating',
'text':_('Ratings, shown with stars'),
'is_multiple':False},
8:{'datatype':'bool',
'text':_('Yes/No'), 'is_multiple':False},
}
def __init__(self, parent, editing, standard_colheads, standard_colnames):
QDialog.__init__(self, parent)
Ui_QCreateCustomColumn.__init__(self)
self.setupUi(self)
# Remove help icon on title bar
icon = self.windowIcon()
self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
self.setWindowIcon(icon)
self.simple_error = partial(error_dialog, self, show=True,
show_copy_button=False)
self.connect(self.button_box, SIGNAL("accepted()"), self.accept)
self.connect(self.button_box, SIGNAL("rejected()"), self.reject)
self.parent = parent
self.editing_col = editing
self.standard_colheads = standard_colheads
self.standard_colnames = standard_colnames
for t in self.column_types:
self.column_type_box.addItem(self.column_types[t]['text'])
self.column_type_box.currentIndexChanged.connect(self.datatype_changed)
if not self.editing_col:
self.datatype_changed()
self.exec_()
return
idx = parent.columns.currentRow()
if idx < 0:
self.simple_error(_('No column selected'),
_('No column has been selected'))
return
col = unicode(parent.columns.item(idx).data(Qt.UserRole).toString())
if col not in parent.custcols:
self.simple_error('', _('Selected column is not a user-defined column'))
return
c = parent.custcols[col]
self.column_name_box.setText(c['label'])
self.column_heading_box.setText(c['name'])
ct = c['datatype'] if not c['is_multiple'] else '*text'
self.orig_column_number = c['colnum']
self.orig_column_name = col
column_numbers = dict(map(lambda x:(self.column_types[x]['datatype'], x), self.column_types))
self.column_type_box.setCurrentIndex(column_numbers[ct])
self.column_type_box.setEnabled(False)
if ct == 'datetime':
if c['display'].get('date_format', None):
self.date_format_box.setText(c['display'].get('date_format', ''))
self.datatype_changed()
self.exec_()
def datatype_changed(self, *args):
try:
col_type = self.column_types[self.column_type_box.currentIndex()]['datatype']
except:
col_type = None
df_visible = col_type == 'datetime'
for x in ('box', 'default_label', 'label'):
getattr(self, 'date_format_'+x).setVisible(df_visible)
def accept(self):
col = unicode(self.column_name_box.text())
if not col:
return self.simple_error('', _('No lookup name was provided'))
if re.match('^\w*$', col) is None or not col[0].isalpha() or col.lower() != col:
return self.simple_error('', _('The lookup name must contain only lower case letters, digits and underscores, and start with a letter'))
if col.endswith('_index'):
return self.simple_error('', _('Lookup names cannot end with _index, because these names are reserved for the index of a series column.'))
col_heading = unicode(self.column_heading_box.text())
col_type = self.column_types[self.column_type_box.currentIndex()]['datatype']
if col_type == '*text':
col_type='text'
is_multiple = True
else:
is_multiple = False
if not col_heading:
return self.simple_error('', _('No column heading was provided'))
bad_col = False
if col in self.parent.custcols:
if not self.editing_col or self.parent.custcols[col]['colnum'] != self.orig_column_number:
bad_col = True
if bad_col:
return self.simple_error('', _('The lookup name %s is already used')%col)
bad_head = False
for t in self.parent.custcols:
if self.parent.custcols[t]['name'] == col_heading:
if not self.editing_col or self.parent.custcols[t]['colnum'] != self.orig_column_number:
bad_head = True
for t in self.standard_colheads:
if self.standard_colheads[t] == col_heading:
bad_head = True
if bad_head:
return self.simple_error('', _('The heading %s is already used')%col_heading)
date_format = {}
if col_type == 'datetime':
if self.date_format_box.text():
date_format = {'date_format':unicode(self.date_format_box.text())}
else:
date_format = {'date_format': None}
key = self.parent.db.field_metadata.custom_field_prefix+col
if not self.editing_col:
self.parent.db.field_metadata
self.parent.custcols[key] = {
'label':col,
'name':col_heading,
'datatype':col_type,
'editable':True,
'display':date_format,
'normalized':None,
'colnum':None,
'is_multiple':is_multiple,
}
item = QListWidgetItem(col_heading, self.parent.columns)
item.setData(Qt.UserRole, QVariant(key))
item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable|Qt.ItemIsSelectable)
item.setCheckState(Qt.Checked)
else:
idx = self.parent.columns.currentRow()
item = self.parent.columns.item(idx)
item.setData(Qt.UserRole, QVariant(key))
item.setText(col_heading)
self.parent.custcols[self.orig_column_name]['label'] = col
self.parent.custcols[self.orig_column_name]['name'] = col_heading
self.parent.custcols[self.orig_column_name]['display'].update(date_format)
self.parent.custcols[self.orig_column_name]['*edited'] = True
self.parent.custcols[self.orig_column_name]['*must_restart'] = True
QDialog.accept(self)
def reject(self):
QDialog.reject(self)

View File

@ -1,191 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QCreateCustomColumn</class>
<widget class="QDialog" name="QCreateCustomColumn">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>528</width>
<height>199</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Create or edit custom columns</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="margin">
<number>5</number>
</property>
<item row="2" column="0">
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Lookup name</string>
</property>
<property name="buddy">
<cstring>column_name_box</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Column &amp;heading</string>
</property>
<property name="buddy">
<cstring>column_heading_box</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="column_name_box">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Used for searching the column. Must contain only digits and lower case letters.</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="column_heading_box">
<property name="toolTip">
<string>Column heading in the library view and category name in the tag browser</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Column &amp;type</string>
</property>
<property name="buddy">
<cstring>column_type_box</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="column_type_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>What kind of information will be kept in the column.</string>
</property>
</widget>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="date_format_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;p&gt;Date format. Use 1-4 'd's for day, 1-4 'M's for month, and 2 or 4 'y's for year.&lt;/p&gt;
&lt;p&gt;For example:
&lt;ul&gt;
&lt;li&gt; ddd, d MMM yyyy gives Mon, 5 Jan 2010&lt;li&gt;
&lt;li&gt;dd MMMM yy gives 05 January 10&lt;/li&gt;
&lt;/ul&gt; </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="date_format_default_label">
<property name="toolTip">
<string>Use MMM yyyy for month + year, yyyy for year only</string>
</property>
<property name="text">
<string>Default: dd MMM yyyy.</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="date_format_label">
<property name="text">
<string>Format for &amp;dates</string>
</property>
<property name="buddy">
<cstring>date_format_box</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QDialogButtonBox" name="button_box">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Create or edit custom columns</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>column_name_box</tabstop>
<tabstop>column_heading_box</tabstop>
<tabstop>column_type_box</tabstop>
<tabstop>date_format_box</tabstop>
<tabstop>button_box</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -1,40 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QComboBox, QStringList, Qt
from calibre.gui2 import config as gui_conf
class HistoryBox(QComboBox):
def __init__(self, parent=None):
QComboBox.__init__(self, parent)
self.setEditable(True)
def initialize(self, opt_name, default, help=None):
history = gui_conf[opt_name]
if default not in history:
history.append(default)
self.addItems(QStringList(history))
self.setCurrentIndex(self.findText(default, Qt.MatchFixedString))
if help is not None:
self.setToolTip(help)
self.setWhatsThis(help)
def save_history(self, opt_name):
history = [unicode(self.itemText(i)) for i in range(self.count())]
ct = self.text()
if ct not in history:
history = [ct] + history
gui_conf[opt_name] = history[:10]
def text(self):
return unicode(self.currentText()).strip()

View File

@ -1,58 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QWidget
from calibre.gui2 import error_dialog
from calibre.gui2.dialogs.config.save_template_ui import Ui_Form
from calibre.library.save_to_disk import FORMAT_ARG_DESCS, \
preprocess_template
class SaveTemplate(QWidget, Ui_Form):
def __init__(self, *args):
QWidget.__init__(self, *args)
Ui_Form.__init__(self)
self.setupUi(self)
def initialize(self, name, default, help):
variables = sorted(FORMAT_ARG_DESCS.keys())
rows = []
for var in variables:
rows.append(u'<tr><td>%s</td><td>%s</td></tr>'%
(var, FORMAT_ARG_DESCS[var]))
table = u'<table>%s</table>'%(u'\n'.join(rows))
self.template_variables.setText(table)
self.opt_template.initialize(name+'_template_history',
default, help)
self.option_name = name
def validate(self):
tmpl = preprocess_template(self.opt_template.text())
fa = {}
for x in FORMAT_ARG_DESCS.keys():
fa[x]='random long string'
try:
tmpl.format(**fa)
except Exception, err:
error_dialog(self, _('Invalid template'),
'<p>'+_('The template %s is invalid:')%tmpl + \
'<br>'+str(err), show=True)
return False
return True
def save_settings(self, config, name):
val = unicode(self.opt_template.text())
config.set(name, val)
self.opt_template.save_history(self.option_name+'_template_history')

View File

@ -1,60 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Save &amp;template</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>By adjusting the template below, you can control what folders the files are saved in and what filenames they are given. You can use the / character to indicate sub-folders. Available metadata variables are described below. If a particular book does not have some metadata, the variable will be replaced by the empty string.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Available variables:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QTextBrowser" name="template_variables"/>
</item>
<item row="1" column="0">
<widget class="HistoryBox" name="opt_template"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>HistoryBox</class>
<extends>QComboBox</extends>
<header>calibre/gui2/dialogs/config/history.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -1,295 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from functools import partial
from PyQt4.Qt import QWidget, QAbstractListModel, Qt, QIcon, \
QVariant, QItemSelectionModel
from calibre.gui2.dialogs.config.toolbar_ui import Ui_Form
from calibre.gui2 import gprefs, NONE, warning_dialog
class FakeAction(object):
def __init__(self, name, icon, tooltip=None,
dont_add_to=frozenset([]), dont_remove_from=frozenset([])):
self.name = name
self.action_spec = (name, icon, tooltip, None)
self.dont_remove_from = dont_remove_from
self.dont_add_to = dont_add_to
class BaseModel(QAbstractListModel):
def name_to_action(self, name, gui):
if name == 'Donate':
return FakeAction(name, 'donate.png',
dont_add_to=frozenset(['context-menu',
'context-menu-device']))
if name == 'Location Manager':
return FakeAction(name, None,
_('Switch between library and device views'),
dont_remove_from=set(['toolbar-device']))
if name is None:
return FakeAction('--- '+_('Separator')+' ---', None)
return gui.iactions[name]
def rowCount(self, parent):
return len(self._data)
def data(self, index, role):
row = index.row()
action = self._data[row].action_spec
if role == Qt.DisplayRole:
text = action[0]
text = text.replace('&', '')
if text == _('%d books'):
text = _('Choose library')
return QVariant(text)
if role == Qt.DecorationRole:
ic = action[1]
if ic is None:
ic = 'blank.png'
return QVariant(QIcon(I(ic)))
if role == Qt.ToolTipRole and action[2] is not None:
return QVariant(action[2])
return NONE
def names(self, indexes):
rows = [i.row() for i in indexes]
ans = []
for i in rows:
n = self._data[i].name
if n.startswith('---'):
n = None
ans.append(n)
return ans
class AllModel(BaseModel):
def __init__(self, key, gui):
BaseModel.__init__(self)
self.gprefs_name = 'action-layout-'+key
current = gprefs[self.gprefs_name]
self.gui = gui
self.key = key
self._data = self.get_all_actions(current)
def get_all_actions(self, current):
all = list(self.gui.iactions.keys()) + ['Donate']
all = [x for x in all if x not in current] + [None]
all = [self.name_to_action(x, self.gui) for x in all]
all = [x for x in all if self.key not in x.dont_add_to]
all.sort()
return all
def add(self, names):
actions = []
for name in names:
if name is None or name.startswith('---'): continue
actions.append(self.name_to_action(name, self.gui))
self._data.extend(actions)
self._data.sort()
self.reset()
def remove(self, indices, allowed):
rows = [i.row() for i in indices]
remove = set([])
for row in rows:
ac = self._data[row]
if ac.name.startswith('---'): continue
if ac.name in allowed:
remove.add(row)
ndata = []
for i, ac in enumerate(self._data):
if i not in remove:
ndata.append(ac)
self._data = ndata
self.reset()
def restore_defaults(self):
current = gprefs.defaults[self.gprefs_name]
self._data = self.get_all_actions(current)
self.reset()
class CurrentModel(BaseModel):
def __init__(self, key, gui):
BaseModel.__init__(self)
self.gprefs_name = 'action-layout-'+key
current = gprefs[self.gprefs_name]
self._data = [self.name_to_action(x, gui) for x in current]
self.key = key
self.gui = gui
def move(self, idx, delta):
row = idx.row()
if row < 0 or row >= len(self._data):
return
nrow = row + delta
if nrow < 0 or nrow >= len(self._data):
return
t = self._data[row]
self._data[row] = self._data[nrow]
self._data[nrow] = t
ni = self.index(nrow)
self.dataChanged.emit(idx, idx)
self.dataChanged.emit(ni, ni)
return ni
def add(self, names):
actions = []
reject = set([])
for name in names:
ac = self.name_to_action(name, self.gui)
if self.key in ac.dont_add_to:
reject.add(ac)
else:
actions.append(ac)
self._data.extend(actions)
self.reset()
return reject
def remove(self, indices):
rows = [i.row() for i in indices]
remove, rejected = set([]), set([])
for row in rows:
ac = self._data[row]
if self.key in ac.dont_remove_from:
rejected.add(ac)
continue
remove.add(row)
ndata = []
for i, ac in enumerate(self._data):
if i not in remove:
ndata.append(ac)
self._data = ndata
self.reset()
return rejected
def commit(self):
old = gprefs[self.gprefs_name]
new = []
for x in self._data:
n = x.name
if n.startswith('---'):
n = None
new.append(n)
new = tuple(new)
if new != old:
defaults = gprefs.defaults[self.gprefs_name]
if defaults == new:
del gprefs[self.gprefs_name]
else:
gprefs[self.gprefs_name] = new
def restore_defaults(self):
current = gprefs.defaults[self.gprefs_name]
self._data = [self.name_to_action(x, self.gui) for x in current]
self.reset()
class ToolbarLayout(QWidget, Ui_Form):
LOCATIONS = [
('toolbar', _('The main toolbar')),
('toolbar-device', _('The main toolbar when a device is connected')),
('context-menu', _('The context menu for the books in the '
'calibre library')),
('context-menu-device', _('The context menu for the books on '
'the device'))
]
def __init__(self, gui, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.models = {}
for key, text in self.LOCATIONS:
self.what.addItem(text, key)
all_model = AllModel(key, gui)
current_model = CurrentModel(key, gui)
self.models[key] = (all_model, current_model)
self.what.setCurrentIndex(0)
self.what.currentIndexChanged[int].connect(self.what_changed)
self.what_changed(0)
self.add_action_button.clicked.connect(self.add_action)
self.remove_action_button.clicked.connect(self.remove_action)
self.restore_defaults_button.clicked.connect(self.restore_defaults)
self.action_up_button.clicked.connect(partial(self.move, -1))
self.action_down_button.clicked.connect(partial(self.move, 1))
def what_changed(self, idx):
key = unicode(self.what.itemData(idx).toString())
self.all_actions.setModel(self.models[key][0])
self.current_actions.setModel(self.models[key][1])
def add_action(self, *args):
x = self.all_actions.selectionModel().selectedIndexes()
names = self.all_actions.model().names(x)
if names:
not_added = self.current_actions.model().add(names)
ns = set([x.name for x in not_added])
added = set(names) - ns
self.all_actions.model().remove(x, added)
if not_added:
warning_dialog(self, _('Cannot add'),
_('Cannot add the actions %s to this location') %
','.join([a.action_spec[0] for a in not_added]),
show=True)
if added:
ca = self.current_actions
idx = ca.model().index(ca.model().rowCount(None)-1)
ca.scrollTo(idx)
def remove_action(self, *args):
x = self.current_actions.selectionModel().selectedIndexes()
names = self.current_actions.model().names(x)
if names:
not_removed = self.current_actions.model().remove(x)
ns = set([x.name for x in not_removed])
removed = set(names) - ns
self.all_actions.model().add(removed)
if not_removed:
warning_dialog(self, _('Cannot remove'),
_('Cannot remove the actions %s from this location') %
','.join([a.action_spec[0] for a in not_removed]),
show=True)
def move(self, delta, *args):
ci = self.current_actions.currentIndex()
m = self.current_actions.model()
if ci.isValid():
ni = m.move(ci, delta)
if ni is not None:
self.current_actions.setCurrentIndex(ni)
self.current_actions.selectionModel().select(ni,
QItemSelectionModel.ClearAndSelect)
def commit(self):
for am, cm in self.models.values():
cm.commit()
def restore_defaults(self, *args):
for am, cm in self.models.values():
cm.restore_defaults()
am.restore_defaults()
if __name__ == '__main__':
from PyQt4.Qt import QApplication
from calibre.gui2.ui import Main
app=QApplication([])
m = Main(None)
a = ToolbarLayout(m)
a.show()
app.exec_()
a.commit()

View File

@ -1,223 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>831</width>
<height>553</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Customize the actions in:</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="what">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
<property name="minimumContentsLength">
<number>20</number>
</property>
</widget>
</item>
<item row="1" column="0" rowspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>A&amp;vailable actions</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListView" name="all_actions">
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="spacing">
<number>10</number>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="2" rowspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>&amp;Current actions</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListView" name="current_actions">
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="spacing">
<number>10</number>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QToolButton" name="action_up_button">
<property name="toolTip">
<string>Move selected action up</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../../resources/images.qrc">
<normaloff>:/images/arrow-up.png</normaloff>:/images/arrow-up.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="action_down_button">
<property name="toolTip">
<string>Move selected action down</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../../resources/images.qrc">
<normaloff>:/images/arrow-down.png</normaloff>:/images/arrow-down.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QToolButton" name="add_action_button">
<property name="toolTip">
<string>Add selected actions to toolbar</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../../resources/images.qrc">
<normaloff>:/images/forward.png</normaloff>:/images/forward.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="remove_action_button">
<property name="toolTip">
<string>Remove selected actions from toolbar</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../../resources/images.qrc">
<normaloff>:/images/back.png</normaloff>:/images/back.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="restore_defaults_button">
<property name="text">
<string>Restore to &amp;default</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../../../../resources/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -30,7 +30,7 @@ from calibre.ebooks.metadata import MetaInformation
from calibre.utils.config import prefs, tweaks
from calibre.utils.date import qt_to_dt, local_tz, utcfromtimestamp
from calibre.customize.ui import run_plugins_on_import, get_isbndb_key
from calibre.gui2.dialogs.config.social import SocialMetadata
from calibre.gui2.preferences.social import SocialMetadata
from calibre.gui2.custom_column_widgets import populate_metadata_page
from calibre import strftime

View File

@ -646,7 +646,7 @@
<item>
<widget class="QPushButton" name="fetch_cover_button">
<property name="text">
<string>Download &amp;cover</string>
<string>Download co&amp;ver</string>
</property>
</widget>
</item>

View File

@ -258,7 +258,9 @@ class LayoutMixin(object): # {{{
getattr(self, x+'_view').save_state()
for x in ('cb', 'tb', 'bd'):
getattr(self, x+'_splitter').save_state()
s = getattr(self, x+'_splitter')
s.update_desired_state()
s.save_state()
def read_layout_settings(self):
# View states are restored automatically when set_database is called

View File

@ -20,6 +20,8 @@ class ConfigWidgetInterface(object):
changed_signal = None
supports_restoring_to_defaults = True
restore_defaults_desc = _('Restore settings to default values. '
'You have to click Apply to actually save the default settings.')
def genesis(self, gui):
raise NotImplementedError()
@ -39,6 +41,9 @@ class ConfigWidgetInterface(object):
'''
return False
def refresh_gui(self, gui):
pass
class Setting(object):
def __init__(self, name, config_obj, widget, gui_name=None,

View File

@ -34,6 +34,10 @@ class Model(QStringListModel):
class Base(ConfigWidgetBase, Ui_Form):
restore_defaults_desc = _('Restore settings to default values. '
'Only settings for the currently selected section '
'are restored.')
def genesis(self, gui):
log = Log()
log.outputs = []

View File

@ -23,7 +23,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('gui_layout', config, restart_required=True, choices=
[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')])
r('cover_flow_queue_length', config)
r('cover_flow_queue_length', config, restart_required=True)
lang = get_lang()
if lang is None or lang not in available_translations():
@ -55,6 +55,10 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
(_('Never'), 'never')]
r('toolbar_text', gprefs, choices=choices)
def refresh_gui(self, gui):
gui.search.search_as_you_type(config['search_as_you_type'])
if __name__ == '__main__':
from PyQt4.Qt import QApplication
app = QApplication([])

View File

@ -0,0 +1,305 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import textwrap
from functools import partial
from PyQt4.Qt import QMainWindow, Qt, QIcon, QStatusBar, QFont, QWidget, \
QScrollArea, QStackedWidget, QVBoxLayout, QLabel, QFrame, QKeySequence, \
QToolBar, QSize, pyqtSignal, QSizePolicy, QToolButton, QAction, \
QPushButton, QHBoxLayout
from calibre.constants import __appname__, __version__, islinux, isosx
from calibre.gui2 import gprefs, min_available_height, available_width, \
warning_dialog
from calibre.gui2.preferences import init_gui, AbortCommit, get_plugin
from calibre.customize.ui import preferences_plugins
from calibre.utils.ordered_dict import OrderedDict
class StatusBar(QStatusBar): # {{{
def __init__(self, parent=None):
QStatusBar.__init__(self, parent)
self.default_message = __appname__ + ' ' + _('version') + ' ' + \
__version__ + ' ' + _('created by Kovid Goyal')
self.device_string = ''
self._font = QFont()
self._font.setBold(True)
self.setFont(self._font)
self.messageChanged.connect(self.message_changed,
type=Qt.QueuedConnection)
self.message_changed('')
def message_changed(self, msg):
if not msg or msg.isEmpty() or msg.isNull() or \
not unicode(msg).strip():
self.showMessage(self.default_message)
# }}}
class Category(QWidget): # {{{
plugin_activated = pyqtSignal(object)
def __init__(self, name, plugins, parent=None):
QWidget.__init__(self, parent)
self._layout = QVBoxLayout()
self.setLayout(self._layout)
self.label = QLabel(name)
self.sep = QFrame(self)
self.bf = QFont()
self.bf.setBold(True)
self.label.setFont(self.bf)
self.sep.setFrameShape(QFrame.HLine)
self._layout.addWidget(self.label)
self._layout.addWidget(self.sep)
self.plugins = plugins
self.bar = QToolBar(self)
self.bar.setIconSize(QSize(48, 48))
self.bar.setMovable(False)
self.bar.setFloatable(False)
self.bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self._layout.addWidget(self.bar)
self.actions = []
for p in plugins:
target = partial(self.triggered, p)
ac = self.bar.addAction(QIcon(p.icon), p.gui_name, target)
ac.setToolTip(textwrap.fill(p.description))
ac.setWhatsThis(textwrap.fill(p.description))
ac.setStatusTip(p.description)
self.actions.append(ac)
w = self.bar.widgetForAction(ac)
w.setStyleSheet('QToolButton { margin-right: 20px; min-width: 100px }')
w.setCursor(Qt.PointingHandCursor)
w.setAutoRaise(True)
def triggered(self, plugin, *args):
self.plugin_activated.emit(plugin)
# }}}
class Browser(QScrollArea): # {{{
show_plugin = pyqtSignal(object)
close_signal = pyqtSignal()
def __init__(self, parent=None):
QScrollArea.__init__(self, parent)
self.setWidgetResizable(True)
category_map = {}
for plugin in preferences_plugins():
if plugin.category not in category_map:
category_map[plugin.category] = plugin.category_order
if category_map[plugin.category] < plugin.category_order:
category_map[plugin.category] = plugin.category_order
categories = list(category_map.keys())
categories.sort(cmp=lambda x, y: cmp(category_map[x], category_map[y]))
self.category_map = OrderedDict()
for c in categories:
self.category_map[c] = []
for plugin in preferences_plugins():
self.category_map[plugin.category].append(plugin)
for plugins in self.category_map.values():
plugins.sort(cmp=lambda x, y: cmp(x.name_order, y.name_order))
self.widgets = []
self._layout = QVBoxLayout()
self.container = QWidget(self)
self.container.setLayout(self._layout)
self.setWidget(self.container)
if isosx:
self._osxl = QHBoxLayout()
self.close_button = QPushButton(_('Close'))
self.close_button.clicked.connect(self.close_requested)
self._osxl.addStretch(10)
self._osxl.addWidget(self.close_button)
#self._osxl.addStretch(10)
self._layout.addLayout(self._osxl)
for name, plugins in self.category_map.items():
w = Category(name, plugins, self)
self.widgets.append(w)
self._layout.addWidget(w)
w.plugin_activated.connect(self.show_plugin.emit)
def close_requested(self, *args):
self.close_signal.emit()
# }}}
class Preferences(QMainWindow):
def __init__(self, gui, initial_plugin=None):
QMainWindow.__init__(self, gui)
self.gui = gui
self.must_restart = False
self.committed = False
self.resize(900, 760 if isosx else 710)
nh, nw = min_available_height()-25, available_width()-10
if nh < 0:
nh = 800
if nw < 0:
nw = 600
nh = min(self.height(), nh)
nw = min(self.width(), nw)
self.resize(nw, nh)
self.esc_action = QAction(self)
self.addAction(self.esc_action)
self.esc_action.setShortcut(QKeySequence(Qt.Key_Escape))
self.esc_action.triggered.connect(self.esc)
geom = gprefs.get('preferences_window_geometry', None)
if geom is not None:
self.restoreGeometry(geom)
# Center
if islinux:
self.move(gui.rect().center() - self.rect().center())
self.setWindowModality(Qt.WindowModal)
self.setWindowTitle(__appname__ + ' - ' + _('Preferences'))
self.setWindowIcon(QIcon(I('config.png')))
self.status_bar = StatusBar(self)
self.setStatusBar(self.status_bar)
self.stack = QStackedWidget(self)
self.setCentralWidget(self.stack)
self.browser = Browser(self)
self.browser.close_signal.connect(self.close, type=Qt.QueuedConnection)
self.browser.show_plugin.connect(self.show_plugin)
self.stack.addWidget(self.browser)
self.scroll_area = QScrollArea(self)
self.stack.addWidget(self.scroll_area)
self.scroll_area.setWidgetResizable(True)
self.bar = QToolBar(self)
self.addToolBar(self.bar)
self.bar.setVisible(False)
self.bar.setIconSize(QSize(32, 32))
self.bar.setMovable(False)
self.bar.setFloatable(False)
self.bar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
self.apply_action = self.bar.addAction(QIcon(I('ok.png')), _('&Apply'),
self.commit)
self.cancel_action = self.bar.addAction(QIcon(I('window-close.png')),
_('&Cancel'), self.cancel)
self.bar_filler = QLabel('')
self.bar_filler.setSizePolicy(QSizePolicy.Expanding,
QSizePolicy.Preferred)
self.bar_filler.setStyleSheet(
'QLabel { font-weight: bold }')
self.bar_filler.setAlignment(Qt.AlignHCenter | Qt.AlignCenter)
self.bar.addWidget(self.bar_filler)
self.restore_action = self.bar.addAction(QIcon(I('clear_left.png')),
_('Restore &defaults'), self.restore_defaults)
for ac, tt in [('apply', _('Save changes')),
('cancel', _('Cancel and return to overview'))]:
ac = getattr(self, ac+'_action')
ac.setToolTip(tt)
ac.setWhatsThis(tt)
ac.setStatusTip(tt)
for ch in self.bar.children():
if isinstance(ch, QToolButton):
ch.setCursor(Qt.PointingHandCursor)
ch.setAutoRaise(True)
self.stack.setCurrentIndex(0)
if initial_plugin is not None:
category, name = initial_plugin
plugin = get_plugin(category, name)
if plugin is not None:
self.show_plugin(plugin)
def show_plugin(self, plugin):
self.showing_widget = plugin.create_widget(self.scroll_area)
self.showing_widget.genesis(self.gui)
self.showing_widget.initialize()
self.scroll_area.setWidget(self.showing_widget)
self.stack.setCurrentIndex(1)
self.showing_widget.show()
self.setWindowTitle(__appname__ + ' - ' + _('Preferences') + ' - ' +
plugin.gui_name)
self.apply_action.setEnabled(False)
self.showing_widget.changed_signal.connect(lambda :
self.apply_action.setEnabled(True))
self.restore_action.setEnabled(self.showing_widget.supports_restoring_to_defaults)
tt = self.showing_widget.restore_defaults_desc
if not self.restore_action.isEnabled():
tt = _('Restoring to defaults not supported for') + ' ' + \
plugin.gui_name
self.restore_action.setToolTip(textwrap.fill(tt))
self.restore_action.setWhatsThis(textwrap.fill(tt))
self.restore_action.setStatusTip(tt)
self.bar_filler.setText(plugin.gui_name)
self.setWindowIcon(QIcon(plugin.icon))
self.bar.setVisible(True)
def hide_plugin(self):
self.showing_widget = QWidget(self.scroll_area)
self.scroll_area.setWidget(self.showing_widget)
self.setWindowTitle(__appname__ + ' - ' + _('Preferences'))
self.bar.setVisible(False)
self.stack.setCurrentIndex(0)
self.setWindowIcon(QIcon(I('config.png')))
def esc(self, *args):
if self.stack.currentIndex() == 1:
self.hide_plugin()
elif self.stack.currentIndex() == 0:
self.close()
def commit(self, *args):
try:
must_restart = self.showing_widget.commit()
except AbortCommit:
return
self.committed = True
if must_restart:
self.must_restart = True
warning_dialog(self, _('Restart needed'),
_('Some of the changes you made require a restart.'
' Please restart calibre as soon as possible.'),
show=True, show_copy_button=False)
self.showing_widget.refresh_gui(self.gui)
self.hide_plugin()
def cancel(self, *args):
self.hide_plugin()
def restore_defaults(self, *args):
self.showing_widget.restore_defaults()
def closeEvent(self, *args):
gprefs.set('preferences_window_geometry',
bytearray(self.saveGeometry()))
return QMainWindow.closeEvent(self, *args)
if __name__ == '__main__':
from PyQt4.Qt import QApplication
app = QApplication([])
app
gui = init_gui()
p = Preferences(gui)
p.show()
app.exec_()
gui.shutdown()

View File

@ -0,0 +1,127 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QProgressDialog, QThread, Qt, pyqtSignal
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
from calibre.gui2.preferences.misc_ui import Ui_Form
from calibre.gui2 import error_dialog, config, warning_dialog, \
open_local_file, info_dialog
from calibre.constants import isosx
# Check Integrity {{{
class VacThread(QThread):
check_done = pyqtSignal(object, object)
callback = pyqtSignal(object, object)
def __init__(self, parent, db):
QThread.__init__(self, parent)
self.db = db
self._parent = parent
def run(self):
err = bad = None
try:
bad = self.db.check_integrity(self.callbackf)
except:
import traceback
err = traceback.format_exc()
self.check_done.emit(bad, err)
def callbackf(self, progress, msg):
self.callback.emit(progress, msg)
class CheckIntegrity(QProgressDialog):
def __init__(self, db, parent=None):
QProgressDialog.__init__(self, parent)
self.db = db
self.setCancelButton(None)
self.setMinimum(0)
self.setMaximum(100)
self.setWindowTitle(_('Checking database integrity'))
self.setAutoReset(False)
self.setValue(0)
self.vthread = VacThread(self, db)
self.vthread.check_done.connect(self.check_done,
type=Qt.QueuedConnection)
self.vthread.callback.connect(self.callback, type=Qt.QueuedConnection)
self.vthread.start()
def callback(self, progress, msg):
self.setLabelText(msg)
self.setValue(int(100*progress))
def check_done(self, bad, err):
if err:
error_dialog(self, _('Error'),
_('Failed to check database integrity'),
det_msg=err, show=True)
elif bad:
titles = [self.db.title(x, index_is_id=True) for x in bad]
det_msg = '\n'.join(titles)
warning_dialog(self, _('Some inconsistencies found'),
_('The following books had formats listed in the '
'database that are not actually available. '
'The entries for the formats have been removed. '
'You should check them manually. This can '
'happen if you manipulate the files in the '
'library folder directly.'), det_msg=det_msg, show=True)
self.reset()
# }}}
class ConfigWidget(ConfigWidgetBase, Ui_Form):
def genesis(self, gui):
self.gui = gui
r = self.register
r('worker_limit', config, restart_required=True)
r('enforce_cpu_limit', config, restart_required=True)
self.device_detection_button.clicked.connect(self.debug_device_detection)
self.compact_button.clicked.connect(self.compact)
self.button_open_config_dir.clicked.connect(self.open_config_dir)
self.button_osx_symlinks.clicked.connect(self.create_symlinks)
self.button_osx_symlinks.setVisible(isosx)
def debug_device_detection(self, *args):
from calibre.gui2.preferences.device_debug import DebugDevice
d = DebugDevice(self)
d.exec_()
def compact(self, *args):
d = CheckIntegrity(self.gui.library_view.model().db, self)
d.exec_()
def open_config_dir(self, *args):
from calibre.utils.config import config_dir
open_local_file(config_dir)
def create_symlinks(self):
from calibre.utils.osx_symlinks import create_symlinks
loc, paths = create_symlinks()
if loc is None:
error_dialog(self, _('Error'),
_('Failed to install command line tools.'),
det_msg=paths, show=True)
else:
info_dialog(self, _('Command line tools installed'),
'<p>'+_('Command line tools installed in')+' '+loc+
'<br>'+ _('If you move calibre.app, you have to re-install '
'the command line tools.'),
det_msg='\n'.join(paths), show=True)
if __name__ == '__main__':
from PyQt4.Qt import QApplication
app = QApplication([])
test_widget('Advanced', 'Misc')

View File

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>502</width>
<height>314</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>&amp;Maximum number of waiting worker processes (needs restart):</string>
</property>
<property name="buddy">
<cstring>opt_worker_limit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="opt_worker_limit">
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="singleStep">
<number>2</number>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="opt_enforce_cpu_limit">
<property name="text">
<string>Limit the max. simultaneous jobs to the available CPU &amp;cores</string>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="device_detection_button">
<property name="text">
<string>Debug &amp;device detection</string>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>19</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0" colspan="2">
<widget class="QPushButton" name="compact_button">
<property name="text">
<string>&amp;Check database integrity</string>
</property>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0" colspan="2">
<widget class="QPushButton" name="button_open_config_dir">
<property name="text">
<string>Open calibre &amp;configuration directory</string>
</property>
</widget>
</item>
<item row="8" column="0">
<spacer name="verticalSpacer_8">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>19</height>
</size>
</property>
</spacer>
</item>
<item row="9" column="0" colspan="2">
<widget class="QPushButton" name="button_osx_symlinks">
<property name="text">
<string>&amp;Install command line tools</string>
</property>
</widget>
</item>
<item row="10" column="0">
<spacer name="verticalSpacer_9">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -45,6 +45,10 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.save_template.save_settings(self.proxy, 'template')
return ConfigWidgetBase.commit(self)
def refresh_gui(self, gui):
gui.iactions['Save To Disk'].reread_prefs()
if __name__ == '__main__':
from PyQt4.Qt import QApplication
app = QApplication([])

View File

@ -15,7 +15,8 @@ from calibre.gui2.preferences.server_ui import Ui_Form
from calibre.utils.search_query_parser import saved_searches
from calibre.library.server import server_config
from calibre.utils.config import ConfigProxy
from calibre.gui2 import error_dialog, config, open_url, warning_dialog
from calibre.gui2 import error_dialog, config, open_url, warning_dialog, \
Dispatcher
class ConfigWidget(ConfigWidgetBase, Ui_Form):
@ -121,6 +122,13 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
' take effect'), show=True)
return False
def refresh_gui(self, gui):
gui.content_server = self.server
if gui.content_server is not None:
gui.content_server.state_callback = \
Dispatcher(gui.iactions['Connect Share'].content_server_state_changed)
gui.content_server.state_callback(gui.content_server.is_running)
if __name__ == '__main__':
from PyQt4.Qt import QApplication

View File

@ -522,6 +522,12 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
def shutdown(self, write_settings=True):
try:
cf = self.library_view.model().db.clean
except:
pass
else:
cf()
for action in self.iactions.values():
if not action.shutting_down():
return

View File

@ -1032,6 +1032,9 @@ class Splitter(QSplitter):
# Public API {{{
def update_desired_state(self):
self.desired_show = not self.is_side_index_hidden
def save_state(self):
if self.count() > 1:
gprefs[self.save_name+'_state'] = self.get_state()

View File

@ -104,6 +104,8 @@ class CSV_XML(CatalogPlugin):
# Output the entry fields
for entry in data:
print "%s [%s]" % (entry['title'],entry['id'])
print "ondevice: %s" % db.ondevice(entry['id'], index_is_id=True)
outstr = []
for field in fields:
item = entry[field]

View File

@ -324,6 +324,7 @@ def do_remove(db, ids):
db.delete_book(y)
send_message()
db.clean()
def remove_option_parser():
return get_parser(_(
@ -449,6 +450,7 @@ def command_show_metadata(args, dbpath):
def do_set_metadata(db, id, stream):
mi = OPF(stream)
db.set_metadata(id, mi)
db.clean()
do_show_metadata(db, id, False)
send_message()

View File

@ -144,6 +144,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.initialize_dynamic()
def initialize_dynamic(self):
self.field_metadata = FieldMetadata() #Ensure we start with a clean copy
self.prefs = DBPrefs(self)
defs = self.prefs.defaults
defs['gui_restriction'] = defs['cs_restriction'] = ''
@ -331,7 +332,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
for prop in ('author_sort', 'authors', 'comment', 'comments', 'isbn',
'publisher', 'rating', 'series', 'series_index', 'tags',
'title', 'timestamp', 'uuid', 'pubdate'):
'title', 'timestamp', 'uuid', 'pubdate', 'ondevice'):
setattr(self, prop, functools.partial(get_property,
loc=self.FIELD_MAP['comments' if prop == 'comment' else prop]))
setattr(self, 'title_sort', functools.partial(get_property,
@ -1125,7 +1126,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
if not authors:
authors = [_('Unknown')]
self.conn.execute('DELETE FROM books_authors_link WHERE book=?',(id,))
self.conn.execute('DELETE FROM authors WHERE (SELECT COUNT(id) FROM books_authors_link WHERE author=authors.id) < 1')
for a in authors:
if not a:
continue
@ -2151,8 +2151,6 @@ books_series_link feeds
os.remove(self.dbpath)
shutil.copyfile(dest, self.dbpath)
self.connect()
self.field_metadata.remove_dynamic_categories()
self.field_metadata.remove_custom_fields()
self.initialize_dynamic()
self.refresh()
if os.path.exists(dest):

View File

@ -306,7 +306,7 @@ class FieldMetadata(dict):
self._tb_cats[k]['label'] = k
self._tb_cats[k]['display'] = {}
self._tb_cats[k]['is_editable'] = True
self._add_search_terms_to_map(k, self._tb_cats[k]['search_terms'])
self._add_search_terms_to_map(k, v['search_terms'])
self.custom_field_prefix = '#'
self.get = self._tb_cats.get
@ -408,16 +408,6 @@ class FieldMetadata(dict):
self._add_search_terms_to_map(key, [key])
self.custom_label_to_key_map[label+'_index'] = key
def remove_custom_fields(self):
for key in self.get_custom_fields():
del self._tb_cats[key]
def remove_dynamic_categories(self):
for key in list(self._tb_cats.keys()):
val = self._tb_cats[key]
if val['is_category'] and val['kind'] in ('user', 'search'):
del self._tb_cats[key]
def cc_series_index_column_for(self, key):
return self._tb_cats[key]['rec_index'] + 1

View File

@ -345,6 +345,8 @@ Calibre has several keyboard shortcuts to save you time and mouse movement. Thes
- Show book details
* - :kbd:`M`
- Merge selected records
* - :kbd:`Alt+M`
- Merge selected records, keeping originals
* - :kbd:`O`
- Open containing folder
* - :kbd:`S`

File diff suppressed because it is too large Load Diff

View File

@ -50,8 +50,9 @@ def get_mx(host, verbose=0):
if verbose:
print 'Find mail exchanger for', host
answers = list(dns.resolver.query(host, 'MX'))
answers.sort(cmp=lambda x, y: cmp(int(x.preference), int(y.preference)))
return [str(x.exchange) for x in answers]
answers.sort(cmp=lambda x, y: cmp(int(getattr(x, 'preference', sys.maxint)),
int(getattr(y, 'preference', sys.maxint))))
return [str(x.exchange) for x in answers if hasattr(x, 'exchange')]
def sendmail_direct(from_, to, msg, timeout, localhost, verbose):
import smtplib