KG updates
@ -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 |
5187
imgsrc/drawer.svg
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 297 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 28 KiB |
BIN
resources/images/news/journalgazette.png
Normal file
After Width: | Height: | Size: 414 B |
BIN
resources/images/news/walrusmag.png
Normal file
After Width: | Height: | Size: 569 B |
42
resources/recipes/buckmasters.recipe
Normal 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
|
||||
|
64
resources/recipes/journalgazette.recipe
Normal 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
|
46
resources/recipes/walrusmag.recipe
Normal 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
|
||||
|
153
resources/recipes/wsj_free.recipe
Normal 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')
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
||||
#}}}
|
||||
|
||||
|
@ -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']
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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))
|
||||
|
@ -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()
|
||||
|
@ -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>&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 &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>&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 ("the", "a", "an"), punctuation, case, etc. Author match is exact.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>If books with similar titles and authors found, &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>&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>&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 &cover separately</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="opt_update_metadata">
|
||||
<property name="text">
|
||||
<string>Update &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 &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 &English equivalents</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Format &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 &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 &underscores</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="opt_to_lowercase">
|
||||
<property name="text">
|
||||
<string>Change paths to &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 &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 &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><li><b>Manual Management</b>: Calibre updates the metadata and adds collections only when a book is sent. With this option, calibre will never remove a collection.</li>
|
||||
<li><b>Only on send</b>: Calibre updates metadata and adds/removes collections for a book only when it is sent to the device. </li>
|
||||
<li><b>Automatic management</b>: Calibre automatically keeps metadata on the device in sync with the calibre library, on every connect</li></ul></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->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>
|
@ -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)
|
@ -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>&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 &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 &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><p>Date format. Use 1-4 'd's for day, 1-4 'M's for month, and 2 or 4 'y's for year.</p>
|
||||
<p>For example:
|
||||
<ul>
|
||||
<li> ddd, d MMM yyyy gives Mon, 5 Jan 2010<li>
|
||||
<li>dd MMMM yy gives 05 January 10</li>
|
||||
</ul> </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 &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>
|
@ -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()
|
||||
|
||||
|
||||
|
@ -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')
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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 &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>
|
@ -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()
|
||||
|
@ -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&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>&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 &default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../../../resources/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -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
|
||||
|
||||
|
@ -646,7 +646,7 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="fetch_cover_button">
|
||||
<property name="text">
|
||||
<string>Download &cover</string>
|
||||
<string>Download co&ver</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 = []
|
||||
|
@ -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([])
|
||||
|
305
src/calibre/gui2/preferences/main.py
Normal 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()
|
127
src/calibre/gui2/preferences/misc.py
Normal 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')
|
||||
|
144
src/calibre/gui2/preferences/misc.ui
Normal 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>&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 &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 &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>&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 &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>&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>
|
@ -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([])
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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]
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`
|
||||
|
@ -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
|
||||
|