* Added tag editor to the toolbar.

* Moved file saving code to the worker thread.
This commit is contained in:
Lukáš Lalinský
2006-09-16 15:32:11 +02:00
parent 32d80545d2
commit 5eb60614db
15 changed files with 983 additions and 192 deletions

BIN
data/images/tag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

597
data/images/tag.svg Normal file
View File

@@ -0,0 +1,597 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="22"
height="22"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.44"
version="1.0"
sodipodi:docbase="E:\projects\picard-qt\data\images"
sodipodi:docname="tag.svg"
inkscape:export-filename="E:\projects\picard-qt\data\images\tag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<linearGradient
id="linearGradient3726">
<stop
id="stop3728"
offset="0"
style="stop-color:black;stop-opacity:1;" />
<stop
id="stop3730"
offset="1"
style="stop-color:#b2b4b1;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3714">
<stop
style="stop-color:#3a3c39;stop-opacity:1;"
offset="0"
id="stop3716" />
<stop
style="stop-color:#555753;stop-opacity:0;"
offset="1"
id="stop3718" />
</linearGradient>
<linearGradient
id="linearGradient3696">
<stop
style="stop-color:white;stop-opacity:1;"
offset="0"
id="stop3698" />
<stop
style="stop-color:white;stop-opacity:0;"
offset="1"
id="stop3700" />
</linearGradient>
<linearGradient
id="linearGradient3680">
<stop
style="stop-color:#d3d7cf;stop-opacity:1;"
offset="0"
id="stop3682" />
<stop
style="stop-color:#b2b9ab;stop-opacity:0.8761062;"
offset="1"
id="stop3684" />
</linearGradient>
<linearGradient
id="linearGradient3656">
<stop
style="stop-color:#d3d7cf;stop-opacity:1;"
offset="0"
id="stop3658" />
<stop
style="stop-color:#6f7964;stop-opacity:0;"
offset="1"
id="stop3660" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3680"
id="linearGradient3686"
x1="10.054452"
y1="5.5608668"
x2="13.825938"
y2="17.709879"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.513109,-0.88873,0.826477,0.477167,-3.102252,14.6625)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3696"
id="linearGradient3702"
x1="11.540086"
y1="19.989897"
x2="9.6603203"
y2="1.0677689"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.5,-0.866025,0.866025,0.5,-4.065295,13.37917)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3726"
id="radialGradient3720"
cx="11.083145"
cy="6.7037535"
fx="11.083145"
fy="6.7037535"
r="0.91117597"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3714"
id="radialGradient3724"
gradientUnits="userSpaceOnUse"
cx="11.136956"
cy="6.7652531"
fx="11.136956"
fy="6.7652531"
r="0.91117594"
gradientTransform="matrix(2.108848,-1.411636,1.00581,1.502588,-19.15375,12.32119)" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="13.802949"
x2="298.86948"
y1="13.599585"
x1="298.47852"
id="linearGradient2265"
xlink:href="#linearGradient2259"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="13.802949"
x2="298.86948"
y1="13.599585"
x1="298.47852"
id="linearGradient2257"
xlink:href="#linearGradient2251"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="13.3396"
x2="297.18515"
y1="12.187603"
x1="294.59497"
id="linearGradient16769"
xlink:href="#XMLID_52_"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="22.860907"
x2="24.190449"
y1="23.843431"
x1="22.225399"
id="linearGradient16739"
xlink:href="#XMLID_45_"
inkscape:collect="always" />
<linearGradient
y2="-79.574341"
x2="1420.6542"
y1="-50.919434"
x1="1420.5474"
gradientTransform="matrix(2.050967,0.000000,0.167197,-0.988984,-2231.169,167.6639)"
gradientUnits="userSpaceOnUse"
id="linearGradient142892"
xlink:href="#path3311_1_"
inkscape:collect="always" />
<linearGradient
y2="175.78883"
x2="1679.5989"
y1="185.30176"
x1="1668.7646"
gradientTransform="matrix(1.213781,0.000000,0.282495,-1.671173,-1385.251,394.5320)"
gradientUnits="userSpaceOnUse"
id="linearGradient142884"
xlink:href="#path3230_2_"
inkscape:collect="always" />
<linearGradient
y2="175.78883"
x2="1679.5989"
y1="185.30176"
x1="1668.7646"
gradientTransform="matrix(1.213781,0,0.282495,-1.671173,-1712.251,391.532)"
gradientUnits="userSpaceOnUse"
id="linearGradient142876"
xlink:href="#path3230_2_"
inkscape:collect="always" />
<linearGradient
y2="27.836672"
x2="74.587158"
y1="21.424805"
x1="68.175293"
gradientUnits="userSpaceOnUse"
id="XMLID_45_">
<stop
id="stop695"
style="stop-color:#BABDB6"
offset="0" />
<stop
id="stop697"
style="stop-color:#EEEEEC"
offset="1" />
</linearGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.000000,0.000000,0.000000,1.010300,1.007969e-18,-0.159801)"
r="7.2848282"
cy="23.333008"
cx="165.06104"
id="XMLID_52_">
<stop
id="stop812"
style="stop-color:#EF3535"
offset="0" />
<stop
offset="0"
style="stop-color:#c91a1a;stop-opacity:1;"
id="stop2239" />
<stop
id="stop814"
style="stop-color:#ff4c4c;stop-opacity:1;"
offset="1" />
</radialGradient>
<linearGradient
gradientTransform="matrix(2.051000,0.000000,0.167200,-0.989000,-799.2049,221.0724)"
y2="-79.574341"
x2="1420.6542"
y1="-50.919434"
x1="1420.5474"
gradientUnits="userSpaceOnUse"
id="path3311_1_">
<stop
id="stop4970"
style="stop-color:#C4A000"
offset="0" />
<stop
id="stop4972"
style="stop-color:#957A00"
offset="1" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1.213800,0.000000,0.282500,-1.671200,46.72625,447.9442)"
y2="175.78883"
x2="1679.5989"
y1="185.30176"
x1="1668.7646"
gradientUnits="userSpaceOnUse"
id="path3230_2_">
<stop
id="stop4977"
style="stop-color:#FFFFFF"
offset="0" />
<stop
id="stop4979"
style="stop-color:#CFCFCF"
offset="1" />
</linearGradient>
<linearGradient
y2="10.711433"
x2="296.93979"
y1="4.7592773"
x1="292.97168"
gradientUnits="userSpaceOnUse"
id="XMLID_897_">
<stop
id="stop45093"
style="stop-color:#EEEEEC"
offset="0" />
<stop
id="stop45095"
style="stop-color:#ffffff;stop-opacity:1;"
offset="1" />
</linearGradient>
<radialGradient
id="radialGradient16850"
cx="165.06104"
cy="23.333008"
r="7.2848282"
gradientTransform="matrix(1.000000,0.000000,0.000000,1.010300,1.007969e-18,-0.159801)"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#EF3535"
id="stop16852" />
<stop
offset="1"
style="stop-color:#a40000;stop-opacity:0"
id="stop16854" />
</radialGradient>
<linearGradient
id="linearGradient2229">
<stop
id="stop2231"
offset="0"
style="stop-color:#e2e2e2;stop-opacity:1;" />
<stop
id="stop2233"
offset="1"
style="stop-color:#d8d8d8;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2251"
inkscape:collect="always">
<stop
id="stop2253"
offset="0"
style="stop-color:#df2a2a;stop-opacity:1;" />
<stop
id="stop2255"
offset="1"
style="stop-color:#df2a2a;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2259"
inkscape:collect="always">
<stop
id="stop2261"
offset="0"
style="stop-color:#9a0c00;stop-opacity:1;" />
<stop
id="stop2263"
offset="1"
style="stop-color:#9a0c00;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2269"
inkscape:collect="always">
<stop
id="stop2271"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop2273"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#radialGradient16850"
id="linearGradient3866"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.161878,0,0,0.992497,-61.86211,-20.93599)"
x1="39.619942"
y1="44.540932"
x2="-3.532515"
y2="-11.889042" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient3869"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.624438,0,0,3.624438,-1109.929,-37.8472)"
x1="296.76199"
y1="12.012225"
x2="297.79822"
y2="10.946587" />
<radialGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="radialGradient3873"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.060381,-56.75,-23.29951)"
cx="34.376091"
cy="37.50008"
fx="34.376091"
fy="37.50008"
r="8.3887873" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient3876"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.161878,0,0,0.992497,-59.41697,-20.93599)"
x1="13.82536"
y1="40.068752"
x2="7.6700611"
y2="2.3262277" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient3879"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.161878,0,0,0.992497,-59.18078,-20.73424)"
x1="7.184845"
y1="31.056622"
x2="25.152235"
y2="50.774887" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2229"
id="linearGradient3884"
gradientUnits="userSpaceOnUse"
x1="20.288025"
y1="6.4603648"
x2="24.32597"
y2="23.942537"
gradientTransform="translate(-56.75,-21)" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_897_"
id="linearGradient3887"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(4.053427,0,0,4.136601,-1232.285,-32.90495)"
x1="292.97168"
y1="4.7592773"
x2="296.93979"
y2="10.711433" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_52_"
id="linearGradient3890"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.637893,0,0,3.470375,-1112.866,-37.00724)"
x1="296.48611"
y1="15.506916"
x2="296.52905"
y2="9.8769522" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2229"
id="linearGradient3894"
gradientUnits="userSpaceOnUse"
x1="20.288025"
y1="6.4603648"
x2="24.32597"
y2="23.942537"
gradientTransform="translate(-56.75,-21)" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_897_"
id="linearGradient3897"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-4.127761,0,0,4.136601,1187.715,-32.90495)"
x1="292.97168"
y1="4.7592773"
x2="296.93979"
y2="10.711433" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2269"
id="radialGradient3899"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.32526,0,28.08607)"
cx="25.1875"
cy="41.625"
fx="25.1875"
fy="41.625"
r="18.0625" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="35.33718"
inkscape:cx="12.71219"
inkscape:cy="5.8065194"
inkscape:document-units="px"
inkscape:current-layer="layer1"
width="22px"
height="22px"
showgrid="true"
inkscape:window-width="942"
inkscape:window-height="819"
inkscape:window-x="4"
inkscape:window-y="8" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;fill-opacity:1;stroke:#2e3436;stroke-width:0.99999958;stroke-miterlimit:4;stroke-opacity:1"
d="M 7.6572017,7.9742723 C 6.4688947,9.5696506 4.8068936,10.410434 2.5810451,9.2891686 C 0.42884616,8.205004 1.1876173,5.1948118 2.0034241,4.0241161"
id="path4815"
sodipodi:nodetypes="csc" />
<path
sodipodi:type="arc"
style="opacity:0.26704544;color:black;fill:url(#radialGradient3899);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path2267"
sodipodi:cx="25.1875"
sodipodi:cy="41.625"
sodipodi:rx="18.0625"
sodipodi:ry="5.875"
d="M 43.25 41.625 A 18.0625 5.875 0 1 1 7.125,41.625 A 18.0625 5.875 0 1 1 43.25 41.625 z"
transform="matrix(0.387543,0,0,0.229988,3.238756,9.07557)" />
<path
style="fill:url(#linearGradient3686);fill-opacity:1;stroke:#555753;stroke-width:0.99999923;stroke-miterlimit:4;stroke-opacity:1"
d="M 3.8999996,8.5828624 L 6.6857154,3.7578614 L 10.217546,3.7275103 L 20.5722,9.705772 L 16.072201,17.5 L 5.8116799,11.576085 L 3.8999996,8.5828624 z "
id="rect1872"
sodipodi:nodetypes="ccccccc" />
<path
sodipodi:type="arc"
style="fill:url(#radialGradient3724);fill-opacity:1;stroke:none;stroke-width:0.60745066;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3722"
sodipodi:cx="11.313767"
sodipodi:cy="7.0035634"
sodipodi:rx="0.6074506"
sodipodi:ry="0.6074506"
d="M 11.921218 7.0035634 A 0.6074506 0.6074506 0 1 1 10.706317,7.0035634 A 0.6074506 0.6074506 0 1 1 11.921218 7.0035634 z"
transform="matrix(1.234669,-2.13851,2.138506,1.234667,-21.01603,23.15043)" />
<path
style="fill:none;fill-opacity:1;stroke:url(#linearGradient3702);stroke-width:0.99999946;stroke-miterlimit:4;stroke-opacity:1"
d="M 5.0842114,8.5317584 L 7.2508799,4.7789784 L 10.232147,4.8906385 L 19.206184,10.071801 L 15.706184,16.133979 L 6.8137292,10.999917 L 5.0842114,8.5317584 z "
id="path3692"
sodipodi:nodetypes="ccccccc" />
<path
sodipodi:type="arc"
style="fill:url(#radialGradient3720);fill-opacity:1;stroke:none;stroke-width:0.60745066;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3704"
sodipodi:cx="11.313767"
sodipodi:cy="7.0035634"
sodipodi:rx="0.6074506"
sodipodi:ry="0.6074506"
d="M 11.921218 7.0035634 A 0.6074506 0.6074506 0 1 1 10.706317,7.0035634 A 0.6074506 0.6074506 0 1 1 11.921218 7.0035634 z"
transform="matrix(0.823113,-1.425674,1.42567,0.823111,-11.36739,17.96793)" />
<path
style="fill:url(#linearGradient3897);stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M -22.575689,-19.375 C -22.363739,-19.306465 -22.15843,-19.230338 -21.951706,-19.157498 C -21.300291,-16.960496 -18.280223,-14.738778 -19.428646,-12.550867 C -23.254491,-6.17048 -27.052979,0.294565 -30.850241,6.72527 C -31.595987,6.872172 -32.348268,6.952183 -33.102005,6.96996 C -34.688397,7.01017 -36.316937,6.775465 -37.822569,6.23589 C -32.771697,-2.315384 -27.718699,-10.885517 -22.575689,-19.375 z "
id="path16717" />
<path
style="fill:url(#linearGradient3894);fill-opacity:1;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M -22.461177,-16.75 C -22.692298,-16.442547 -22.910792,-15.879058 -23.147207,-15.59375 C -27.194062,-8.841021 -31.309216,-2.099671 -35.371024,4.625 C -35.431575,4.878117 -36.184953,5.637291 -35.383065,5.567963 C -34.271508,5.765843 -33.111318,5.918567 -32.003238,5.625 C -28.244248,-0.592206 -24.557361,-6.857418 -20.806952,-13.076822 C -20.464481,-13.464096 -20.397837,-14.00208 -20.757597,-14.388803 C -21.287613,-15.205411 -21.824536,-16.063518 -22.367627,-16.84375 L -22.438187,-16.773039 L -22.461177,-16.75 z "
id="path16719" />
<polygon
style="fill:url(#linearGradient16769);fill-opacity:1;stroke:#9a0c00;stroke-width:0.28144068;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="polygon45129"
points="297.04443,12.300293 296.39941,13.384766 295.13281,14.71875 294.73242,13.672852 295.74658,11.960449 297.04443,12.300293 "
transform="matrix(3.637893,0,0,3.470375,-1112.866,-37.00724)" />
<path
style="fill:url(#linearGradient3890);fill-opacity:1;stroke:none;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M -36.34375,5.96875 C -37.566095,6.455468 -37.557768,8.003929 -38.268728,8.932762 C -38.611051,9.648557 -39.212517,10.278989 -39.46875,11.03125 C -39.478429,11.546641 -39.020797,12.391474 -38.4375,11.9375 C -37.052524,10.791172 -35.873134,9.398821 -34.993275,7.810629 C -34.760912,7.320596 -34.197524,6.916466 -34.125,6.40625 C -34.663569,5.835441 -35.637818,5.873225 -36.34375,5.96875 z "
id="polygon16896" />
<path
style="fill:url(#linearGradient3887);stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M -43.789901,-19.375 C -43.998034,-19.306465 -44.199645,-19.230338 -44.402647,-19.157498 C -45.042331,-16.960496 -48.008012,-14.738778 -46.88027,-12.550867 C -43.123323,-6.17048 -39.39324,0.294565 -35.664361,6.72527 C -34.932044,6.872172 -34.19331,6.952183 -33.453147,6.96996 C -31.895323,7.01017 -30.296111,6.775465 -28.817593,6.23589 C -33.777507,-2.315384 -38.739508,-10.885517 -43.789901,-19.375 z "
id="polygon45097" />
<path
style="fill:url(#linearGradient3884);fill-opacity:1;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M -44.030333,-16.75 C -44.413368,-15.623321 -45.479994,-14.794036 -45.745145,-13.59375 C -42.036624,-7.199638 -38.274202,-0.824622 -34.568243,5.5625 C -33.369877,5.820799 -32.139802,5.655657 -30.954888,5.40625 C -31.143661,4.665807 -31.693089,4.075319 -31.984871,3.3767 C -35.879474,-3.193826 -39.808571,-9.757128 -43.662873,-16.34375 C -43.677534,-16.49536 -43.879575,-16.827885 -44.030333,-16.75 z "
id="path16635" />
<path
sodipodi:type="arc"
style="color:black;fill:url(#linearGradient16739);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path16731"
sodipodi:cx="23.207924"
sodipodi:cy="23.843431"
sodipodi:rx="0.98252523"
sodipodi:ry="0.98252523"
d="M 24.190449 23.843431 A 0.98252523 0.98252523 0 1 1 22.225399,23.843431 A 0.98252523 0.98252523 0 1 1 24.190449 23.843431 z"
transform="matrix(0.979893,0,0,1,-56.43862,-20.82596)" />
<path
id="path45138"
style="fill:url(#linearGradient3879);fill-opacity:1;stroke:#a40000;stroke-opacity:1"
d="M -39.049607,9.286934 C -35.814596,11.013583 -35.553771,15.899851 -38.471662,20.201286 C -41.389521,24.50525 -46.376151,26.596472 -49.612619,24.877418 C -52.849117,23.150767 -53.108454,18.267032 -50.190564,13.965597 C -47.274192,9.664166 -42.286075,7.572944 -39.049607,9.286934 z M -40.904732,12.029079 C -42.341255,11.26545 -45.41219,12.569599 -47.371073,15.463107 C -49.333984,18.356612 -49.193971,21.376624 -47.758798,22.137951 C -46.323652,22.906181 -43.250015,21.597432 -41.291132,18.703925 C -39.32687,15.81042 -39.468235,12.792709 -40.904732,12.029079 z " />
<path
style="fill:url(#linearGradient3876);fill-opacity:1;stroke:none;stroke-opacity:1"
d="M -42.4245,9.583289 C -44.349631,9.97051 -46.058959,11.037306 -47.471407,12.064531 C -48.223171,12.759433 -48.714971,13.514452 -49.387055,14.31874 C -51.095382,16.670805 -51.811293,19.762168 -50.459893,22.388409 C -49.84044,23.841515 -47.817258,24.435852 -46.091677,24.067542 C -44.639764,23.819078 -43.410361,22.906473 -42.279265,22.268641 C -41.358363,21.47786 -40.725251,20.642131 -39.946374,19.677364 C -38.137014,17.202962 -37.154463,13.928687 -38.648396,11.165081 C -39.372102,10.022952 -40.883037,9.41829 -42.4245,9.583289 z M -41.952487,10.54477 C -39.935983,10.795124 -38.595513,12.577585 -38.82994,14.266634 C -38.809167,16.553573 -39.975962,18.710728 -41.553091,20.500756 C -42.970295,21.902737 -44.901706,23.229027 -47.217247,23.137076 C -48.5761,23.134209 -49.649821,22.224779 -50.033068,21.176618 C -50.649706,18.644695 -49.83835,15.911389 -48.066871,13.83862 C -46.708633,12.315308 -44.872024,10.95152 -42.599358,10.596926 C -42.383669,10.581652 -42.168478,10.554432 -41.952487,10.54477 z "
id="path16771" />
<path
d="M -26.418236,9.286934 C -29.653247,11.013583 -29.914071,15.899851 -26.99618,20.201286 C -24.078321,24.50525 -19.091691,26.596472 -15.855223,24.877418 C -12.618724,23.150767 -12.359389,18.267032 -15.277278,13.965597 C -18.19365,9.664166 -23.181767,7.572944 -26.418236,9.286934 z M -24.56311,12.029079 C -23.126588,11.26545 -20.055652,12.569599 -18.096769,15.463107 C -16.133859,18.356612 -16.273872,21.376624 -17.709044,22.137951 C -19.14419,22.906181 -22.217827,21.597432 -24.17671,18.703925 C -26.140972,15.81042 -25.999607,12.792709 -24.56311,12.029079 z "
style="fill:url(#radialGradient3873);fill-opacity:1;stroke:#a40000;stroke-opacity:1"
id="path11967" />
<polygon
style="fill:url(#linearGradient2257);fill-opacity:1;stroke:url(#linearGradient2265);stroke-width:0.27590489;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="polygon45101"
points="296.95605,12.300293 297.6001,13.384766 298.86719,14.71875 299.26807,13.672852 298.25391,11.960449 296.95605,12.300293 "
transform="matrix(3.624438,0,0,3.624438,-1109.929,-37.8472)" />
<path
style="fill:url(#linearGradient3869);fill-opacity:1;stroke:none;stroke-width:0.27590489;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M -30.59375,6.9375 C -31.020498,7.136321 -31.610564,7.138981 -31.9375,7.4375 C -30.98748,8.838889 -30.047588,10.352161 -29.086621,11.650077 C -28.418067,12.404621 -27.730806,13.150303 -26.96875,13.8125 C -26.233473,12.421076 -26.83359,10.751292 -27.78125,9.625 C -28.383785,8.725307 -28.611072,7.512038 -29.625,7.03125 C -29.929049,6.912839 -30.275615,6.853373 -30.59375,6.9375 z "
id="polygon16860" />
<path
style="fill:url(#linearGradient3866);fill-opacity:1;stroke:none;stroke-opacity:1"
d="M -24.469913,9.449093 C -25.990297,9.678844 -27.364859,10.534748 -27.710361,11.837057 C -28.841505,14.232508 -27.925237,16.950571 -26.430582,19.063908 C -25.328655,20.40911 -24.490512,21.993821 -22.790999,22.837878 C -21.320346,23.761502 -19.449857,24.728452 -17.573359,24.138766 C -16.060044,23.705317 -15.202687,22.4582 -14.893187,21.166912 C -14.288757,18.856882 -15.188883,16.490951 -16.600154,14.530428 C -17.258827,13.616722 -17.933139,12.647222 -18.713472,11.835783 C -19.908031,10.932329 -21.351386,10.184254 -22.802312,9.603431 C -23.33641,9.493019 -23.917536,9.37069 -24.469913,9.449093 z M -24.034208,10.658699 C -22.276905,10.591923 -20.799695,11.398157 -19.657838,12.427664 C -18.625541,13.396792 -17.636183,14.23287 -16.995327,15.426541 C -15.918144,17.24711 -15.607466,19.4065 -16.155223,21.390073 C -16.683603,22.714585 -18.381377,23.362109 -19.946343,23.006518 C -21.928224,22.77769 -23.163683,21.335503 -24.472909,20.198158 C -25.978656,18.766768 -26.91353,16.719532 -26.98349,14.715783 C -26.969378,13.698114 -27.009958,12.53736 -26.285347,11.682212 C -25.873074,11.139062 -24.90534,10.627886 -24.034208,10.658699 z "
id="path16795" />
<path
style="fill:none;fill-opacity:1;stroke:#2e3436;stroke-width:0.99999958;stroke-miterlimit:4;stroke-opacity:1"
d="M 1.861328,4.2806115 C 2.5075428,2.9359088 4.6909289,2.6674794 6.2344291,3.165814 C 8.1878979,3.7965111 8.8740081,6.5213913 7.6857012,8.1167697"
id="path4820"
sodipodi:nodetypes="csc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

BIN
data/images/track-saved.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

View File

@@ -27,5 +27,7 @@
<file>images/match-90.png</file>
<file>images/match-100.png</file>
<file>images/magic-wand.png</file>
<file>images/track-saved.png</file>
<file>images/tag.png</file>
</qresource>
</RCC>

View File

@@ -121,10 +121,10 @@ class Album(DataObject):
def addLinkedFile(self, track, file):
index = self.tracks.index(track)
self.files.append(file)
self.emit(QtCore.SIGNAL("trackUpdated"), track)
self.emit(QtCore.SIGNAL("track_updated"), track)
def removeLinkedFile(self, track, file):
self.emit(QtCore.SIGNAL("trackUpdated"), track)
self.emit(QtCore.SIGNAL("track_updated"), track)
def getNumUnmatchedFiles(self):
return len(self.unmatched_files)
@@ -174,3 +174,7 @@ class Album(DataObject):
"""Return if this object can be removed."""
return True
def can_edit_tags(self):
"""Return if this object supports tag editing."""
return False

View File

@@ -58,3 +58,7 @@ class Cluster(QtCore.QObject):
"""Return if this object can be removed."""
return True
def can_edit_tags(self):
"""Return if this object supports tag editing."""
return False

View File

@@ -24,93 +24,77 @@ from PyQt4 import QtCore
from picard.metadata import Metadata
from picard.parsefilename import parseFileName
from picard.similarity import similarity
from picard.util import LockableObject
class File(QtCore.QObject):
class File(LockableObject):
_id_counter = 1
NEW = 0
CHANGED = 1
TO_BE_SAVED = 2
SAVED = 3
def __init__(self, filename):
QtCore.QObject.__init__(self)
self._id = File._id_counter
File._id_counter += 1
self.mutex = QtCore.QMutex(QtCore.QMutex.Recursive)
LockableObject.__init__(self)
self.id = self.new_id()
self.filename = filename
self.base_filename = os.path.basename(filename)
self.cluster = None
self.track = None
self.state = File.NEW
self.orig_metadata = Metadata()
self.metadata = Metadata()
def __str__(self):
return ('<File #%d "%s">' % (self.id, self.base_filename)).encode("UTF-8")
def lock(self):
self.mutex.lock()
def unlock(self):
self.mutex.unlock()
__id_counter = 1
def getId(self):
return self._id
id = property(getId)
@classmethod
def new_id(cls):
cls.__id_counter += 1
return cls.__id_counter
def save(self):
"""Save the file."""
locker = QtCore.QMutexLocker(self.mutex)
try:
self._save()
if self.config.setting["rename_files"]:
format = self.config.setting["file_naming_format"]
filename = self.tagger.evaluate_script(format, self.metadata)
filename = os.path.basename(filename) + os.path.splitext(self.filename)[1]
filename = os.path.join(os.path.dirname(self.filename), filename)
os.rename(self.filename, filename)
self.filename = filename
except Exception, e:
raise
else:
self.orig_metadata.copy(self.metadata)
self.metadata.changed = False
def _save(self):
"""Save metadata to the file."""
raise NotImplementedError
def remove_from_cluster(self):
locker = QtCore.QMutexLocker(self.mutex)
if self.cluster is not None:
self.log.debug("%s being removed from %s", self, self.cluster)
self.cluster.remove_file(self)
self.cluster = None
def remove_from_track(self):
locker = QtCore.QMutexLocker(self.mutex)
if self.track is not None:
self.log.debug("%s being removed from %s", self, self.track)
self.track.remove_file(self)
self.track = None
def move_to_cluster(self, cluster):
locker = QtCore.QMutexLocker(self.mutex)
if cluster != self.cluster:
self.remove_from_cluster()
self.remove_from_track()
self.log.debug("%s being moved to %s", self, cluster)
self.state = self.CHANGED
self.cluster = cluster
self.cluster.add_file(self)
def move_to_track(self, track):
locker = QtCore.QMutexLocker(self.mutex)
if track != self.track:
self.remove_from_cluster()
self.remove_from_track()
self.log.debug("%s being moved to %s", self, track)
self.state = self.CHANGED
if self.orig_metadata["musicbrainz_trackid"] and \
self.orig_metadata["musicbrainz_trackid"] == track.id:
self.state = self.SAVED
print self.metadata["musicbrainz_trackid"]
print track.id
print "state", self.state
self.track = track
self.track.add_file(self)
def get_similarity(self, metadata=None):
locker = QtCore.QMutexLocker(self.mutex)
if not metadata:
metadata = self.metadata
return self.orig_metadata.compare(metadata)
@@ -123,3 +107,7 @@ class File(QtCore.QObject):
"""Return if this object can be removed."""
return True
def can_edit_tags(self):
"""Return if this object supports tag editing."""
return True

View File

@@ -39,7 +39,7 @@ class MutagenMP3File(File):
self.metadata.copy(self.orig_metadata)
def _save(self):
def save(self):
"""Save ID3 tags to the file."""
tags = CompatID3(encode_filename(self.filename), translate=False)
@@ -52,9 +52,9 @@ class MutagenMP3File(File):
else:
v1 = 0
if self.config.setting["id3v2_encoding"] == "utf-8":
if self.config.setting["id3v2_encoding"].lower() == "utf-8":
encoding = 3
elif self.config.setting["id3v2_encoding"] == "utf-16":
elif self.config.setting["id3v2_encoding"].lower() == "utf-16":
encoding = 1
else:
encoding = 0

View File

@@ -1,6 +1,6 @@
# Resource object code
#
# Created: ?t 14. IX 13:09:50 2006
# Created: so 16. IX 15:26:50 2006
# by: The Resource Compiler for PyQt (Qt v4.1.3)
#
# WARNING! All changes made in this file will be lost!
@@ -1900,6 +1900,18 @@ qt_resource_data = "\
\x6a\xa1\x46\x96\xc1\x7c\xee\x56\x87\xab\x23\xd3\xcb\xdd\x81\xcf\
\x99\xc8\x57\x93\xb7\xb6\xbf\x05\x18\x00\xb3\x4c\x68\x8a\xf9\xd4\
\xd4\xe6\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\x9c\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00\x28\x2d\x0f\x53\
\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xaf\xc8\x37\x05\x8a\xe9\
\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\
\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\x65\x52\x65\x61\x64\
\x79\x71\xc9\x65\x3c\x00\x00\x00\x06\x50\x4c\x54\x45\xff\xff\xff\
\x00\x00\x00\x55\xc2\xd3\x7e\x00\x00\x00\x01\x74\x52\x4e\x53\x00\
\x40\xe6\xd8\x66\x00\x00\x00\x0f\x49\x44\x41\x54\x78\xda\x62\x60\
\x18\x05\xc8\x00\x20\xc0\x00\x01\x10\x00\x01\x3b\x42\x42\x4b\x00\
\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x01\x08\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -2433,23 +2445,131 @@ qt_resource_data = "\
\xd1\xa4\xf0\xe7\x6f\x64\xe7\x61\x16\x79\xf3\xdf\xc4\x6f\x97\x71\
\x39\x10\x00\x75\x1a\x77\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
\x00\x00\x00\xe6\
\x00\x00\x04\x2a\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x16\x00\x00\x00\x16\x08\x06\x00\x00\x00\xc4\xb4\x6c\x3b\
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\
\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\
\x67\x9b\xee\x3c\x1a\x00\x00\x03\xbc\x49\x44\x41\x54\x38\x8d\xb5\
\xd5\x5f\x6c\x53\x55\x1c\x07\xf0\xef\xb9\xff\xda\x6e\xeb\x9f\xb9\
\x75\x1d\x43\xb3\x08\x73\x41\xb2\xbf\xea\x36\x8d\xf2\x82\x89\xcc\
\x08\x0f\x83\xae\x69\x70\xf2\xe0\x50\x94\x04\x12\x40\xcd\x66\x42\
\x02\x6a\xdc\x83\x0f\x26\xc4\x07\xcd\x02\x1a\x30\xa6\xe9\x9a\x18\
\x36\xf7\x00\x4a\x7c\x80\x28\x5d\x35\x5a\xc2\xd6\x06\xcd\x9a\xe9\
\xd6\x6d\x4c\x60\x32\xb6\xde\xde\x9e\x73\x7f\x3e\xf4\x0e\x06\x91\
\x39\x35\xfb\xe5\x9e\x7b\x4e\x72\xef\xfd\xfc\x6e\x7e\xe7\x9c\x7b\
\x19\x11\x61\x35\x42\x5a\x15\x15\x80\xb2\x38\xa8\xab\xdb\x54\xcc\
\x34\x63\x07\x40\x05\x24\x49\x73\x12\x89\xe1\x9f\x63\xb1\xa1\xff\
\x0a\x33\x22\x42\x43\x73\x73\x23\x11\xfb\x1a\xc0\xb7\x60\x2c\x0d\
\x90\x5b\x96\xa4\x76\x97\xb3\x68\xa1\xf2\x41\xdf\x34\x11\x18\x91\
\x99\xca\x66\x8d\x03\xe1\x50\xe4\x97\x15\xc3\x75\x4d\x2d\xfd\x8c\
\xe8\x72\xfc\x87\xa1\xb7\x01\x20\x10\xf4\x6f\x7f\xa0\xa4\xe4\xe4\
\xe8\x58\xba\x70\xdb\xd6\x56\x6a\xac\xaf\x31\xc7\x27\x26\xc4\xe0\
\xc0\x20\x17\x42\xf4\x72\xce\x0f\x87\x43\x91\xb9\x65\xe1\xba\x27\
\x9a\xed\x00\xa6\x00\xac\x8f\xc7\xa2\xd7\x02\x41\xbf\x4d\x55\xd5\
\xb1\xdd\xaf\x74\xfa\x86\x13\x57\x68\x64\x24\x89\xbd\xaf\xbf\xcc\
\x55\x45\x23\x06\x86\x6f\xce\x9d\xcb\x5d\x38\x7f\xc1\xe0\x9c\xbf\
\x01\xe0\xd3\x70\x28\xf2\xb7\xb3\x2f\x01\x78\x06\x40\x22\x1e\x8b\
\x5e\x03\x00\x59\x96\xdf\xac\xae\xae\x76\x96\x95\x95\x61\x6c\x34\
\xc5\x7e\x9f\x98\x40\x46\xcf\xd0\xcd\xb9\x59\x31\xb7\x70\x93\xb7\
\xb6\x6e\x91\xbb\xbb\xbb\x0a\x1e\xdd\xb8\xe1\x43\x55\x55\x2e\x07\
\x82\xfe\xa7\xee\x07\x4f\x03\x28\xb6\x4a\x50\xce\x18\xeb\xde\xba\
\xed\x85\x82\x91\x44\x02\x43\x3f\xfe\x04\x15\x8c\xcd\x4c\x5f\x05\
\x81\x60\x18\x59\x73\x72\x7a\xdc\x10\xc4\x8d\x3d\xaf\xee\xd1\xf6\
\xed\xdb\xbf\xce\xeb\xf5\x9e\xdd\xd9\x11\xec\x0b\x04\xfd\x6b\xef\
\x85\x13\x00\x72\xf5\x4d\x2d\xef\x00\x38\x58\x5b\x57\x2b\x7b\x3c\
\x6e\xf8\xca\xbc\x50\x65\x42\x71\xb1\x93\x5c\x1e\x97\x49\xd6\x82\
\x27\x02\xfd\x39\x37\xcb\xaf\x8c\x26\xe7\x5d\x9e\x22\xe3\xe8\x91\
\xa3\xea\xae\x5d\x2f\x3d\xef\x70\x38\x92\xc1\x9d\x81\xc3\x81\xa0\
\xdf\x76\x7b\xf2\xea\x9b\x5a\x7c\x00\x22\x9a\xaa\x6c\xac\x5a\xf7\
\x90\xa7\xab\xeb\x2d\x49\xb3\x69\xc8\x66\x33\x42\x08\x21\x4c\x22\
\xd3\x34\xf3\x43\x61\x0a\x61\x9a\xc2\x14\x22\xdf\x2b\xb2\x8a\x87\
\x2b\xab\x0a\x9d\x45\x6e\xed\xf4\xe9\x2f\xf5\x33\x67\xce\xde\x32\
\x4d\xb3\x56\x02\x80\x78\x2c\x3a\x1d\x8f\x45\x37\x19\x39\x5e\x9b\
\xc9\xe8\x9f\xf5\xf5\x45\x16\x1c\x76\x07\x29\xb2\x4a\x60\x0c\x20\
\x22\x22\x02\x81\xac\xe3\xce\xdb\xeb\x86\x2e\x86\x93\xf1\x1b\x99\
\xcc\xbc\x51\x55\x55\xa5\x48\x92\x34\x1c\x0e\x45\xae\xdf\xb5\xf3\
\xe2\xb1\x68\x5a\x53\x95\xd7\x52\xa3\xa9\xf4\x40\xff\x57\xba\x66\
\x73\x30\x57\x91\x9b\x31\x49\xba\x83\x02\xf9\x93\x95\x0a\x44\xe4\
\x74\xba\x54\x67\x91\xdb\x76\xfc\xf8\x09\x70\xce\xf7\x2e\xd6\xf8\
\xae\x08\x87\x22\xb9\x5c\x2e\xf7\xf8\xc5\x8b\xdf\xf7\xbe\xff\xee\
\x7b\x7a\x32\x99\x24\x5f\x69\xb9\xe2\x76\x16\xcb\x00\xb3\xf0\x3c\
\x0b\x0b\xdf\xb0\xbe\xc6\x3d\x30\xd8\x9f\xcd\x66\xb3\x9f\x84\x43\
\x91\x5f\x6f\xd7\xf8\x7e\x11\x08\xfa\x1f\xd1\x34\xed\xe3\xd2\xd2\
\x92\xa6\x17\x3b\x3a\xec\x15\x15\x15\xe6\xd5\x3f\x26\xb3\x37\x66\
\xaf\x1b\xa6\x55\x65\x6f\xa9\x4f\x2b\xf7\xae\x75\x1e\x3a\x74\x70\
\x5e\x08\x51\xb9\xb8\x71\x96\x85\x97\x24\xd8\xa2\xaa\x6a\x6f\x43\
\x63\x83\xa7\xdd\xdf\x6e\x53\x14\x59\x8c\x8d\xa7\x6e\xcd\x67\xe6\
\xf9\x93\x8f\x3d\x5d\x72\xec\xa3\x63\xfa\xa5\xf8\xa5\x03\xe1\x50\
\xe4\xc4\xe2\x33\x2b\x82\x2d\x5c\x91\x24\x69\xbf\x2c\xcb\x47\xda\
\xda\xda\xa4\xcd\x9b\x9f\x55\x85\xe0\xe6\xd4\xd4\x14\x7a\x7a\x7a\
\x46\x39\xe7\x35\x4b\x77\xe1\x8a\xe1\x25\x09\xbc\x8a\xa2\x7c\x50\
\x58\x58\xd8\xde\xb9\xbb\x53\x3a\x75\xf2\x94\x98\x99\x99\x79\x2e\
\x1c\x8a\x7c\xb7\xf4\xbe\x7f\x0d\x2f\x49\xd0\xa0\xa8\x4a\x2f\x08\
\xbf\x7d\xf1\x79\x68\xc7\xbd\xd7\x97\x85\x19\x63\x0c\x80\xdd\x6a\
\x36\x00\x1a\xf2\xdf\x70\x06\x80\x00\xf0\x35\x15\x6b\xe4\xc9\xf4\
\xe4\x2c\x00\x1d\x80\xbe\xb8\xc6\xff\x09\x96\x2d\xd0\x0e\xc0\x01\
\xa0\xc0\xea\x25\x00\x06\x80\x8c\xd5\x74\xab\x37\x56\x04\xff\x9f\
\x58\xb5\x7f\xde\x5f\xf5\x72\xf5\x72\x11\x6f\xdf\x2b\x00\x00\x00\
\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\xf4\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x0d\x00\x00\x00\x0d\x08\x03\x00\x00\x00\x45\x35\x14\x4e\
\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xaf\xc8\x37\x05\x8a\xe9\
\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\
\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\x65\x52\x65\x61\x64\
\x79\x71\xc9\x65\x3c\x00\x00\x00\x0c\x50\x4c\x54\x45\x19\x7b\x30\
\x00\x5e\x20\x39\xb5\x4a\x74\x74\x74\xde\x81\xcf\x1f\x00\x00\x00\
\x04\x74\x52\x4e\x53\xff\xff\xff\x00\x40\x2a\xa9\xf4\x00\x00\x00\
\x50\x49\x44\x41\x54\x78\xda\x62\x60\x46\x06\x00\x01\xc4\x00\xc4\
\x8c\x10\x00\x64\x01\x04\x10\x98\xc7\x00\x02\x20\x1e\x40\x00\x81\
\x79\x4c\x20\x00\xe2\x01\x04\x10\x2a\x0f\x20\x80\x50\x79\x00\x01\
\x84\xca\x03\x08\x20\x54\x1e\x40\x00\xa1\xf2\x00\x02\x08\x95\x07\
\x10\x40\xa8\x3c\x80\x00\x42\xe5\x01\x04\x10\xaa\xcb\x00\x02\x0c\
\x00\x88\x79\x01\x7c\x1c\x2f\xc7\x96\x00\x00\x00\x00\x49\x45\x4e\
\x44\xae\x42\x60\x82\
\x79\x71\xc9\x65\x3c\x00\x00\x00\x09\x50\x4c\x54\x45\x00\x58\x26\
\x00\xa6\x51\xff\xff\xff\x25\xa5\x29\xf6\x00\x00\x00\x03\x74\x52\
\x4e\x53\xff\xff\x00\xd7\xca\x0d\x41\x00\x00\x00\x62\x49\x44\x41\
\x54\x78\xda\x62\x60\x42\x06\x00\x01\xc4\x80\x60\x31\x30\x30\x01\
\x04\x10\x9c\xc7\xc0\xc8\xc8\xc8\x00\x10\x40\x0c\xc8\x1c\x26\x80\
\x00\x62\x40\xe6\x30\x01\x04\x10\x03\x58\x2f\x94\xc3\x04\x10\x40\
\x20\x01\x46\x18\x87\x09\x20\x80\x20\xe2\x50\x0e\x13\x40\x00\x31\
\xc0\xf5\x80\x00\x40\x00\x81\x55\xc3\x38\x4c\x00\x01\xc4\x80\xe2\
\x04\x80\x00\x62\x40\x71\x19\x40\x00\xa1\xf2\x00\x02\x0c\x00\x5d\
\x64\x01\x0e\xd9\x8f\x83\x25\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
\x42\x60\x82\
\x00\x00\x02\x32\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00\x28\x2d\x0f\x53\
\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xaf\xc8\x37\x05\x8a\xe9\
\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\
\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\x65\x52\x65\x61\x64\
\x79\x71\xc9\x65\x3c\x00\x00\x00\xcc\x50\x4c\x54\x45\xc6\xcc\x9b\
\xea\xed\xcd\x9c\xde\x5c\x7b\xd3\x27\x75\xd1\x1c\xc3\xc8\x9a\xe1\
\xe6\xb8\x78\xd2\x21\xd9\xe0\xa4\xda\xe0\xa5\xbd\xc0\xa4\xc9\xcb\
\xbb\x80\xd4\x2f\xc7\xcb\xac\x85\xd6\x38\x76\xd2\x1d\x86\xd6\x38\
\x8b\xd8\x42\xdc\xe2\xab\x93\xdb\x4e\xac\xe4\x75\x7a\xd3\x25\xe8\
\xe8\xe5\xd9\xdb\xc8\xd0\xd7\x9e\xa2\xe0\x66\xf8\xf8\xf6\xbd\xc2\
\x9a\x8a\xd8\x3f\xde\xe0\xd1\x9e\xdf\x60\xd4\xdb\xa0\x75\xd1\x1b\
\x82\xd5\x32\x87\xd7\x3b\xa4\xe1\x6a\xe1\xe6\xb6\x74\xd1\x18\x8e\
\xd9\x46\xdc\xe2\xa9\xa5\xe1\x6b\x7d\xd3\x2a\xc9\xcb\xb4\x94\xdb\
\x4f\x91\xda\x4a\xc2\xc7\x9a\xd0\xd2\xc1\x7e\xd4\x2c\x84\xd5\x35\
\xe5\xe9\xc0\xe0\xe5\xb4\x96\xdc\x52\x77\xd2\x1f\xdc\xde\xcd\x74\
\xd1\x1a\xe3\xe8\xbc\xa8\xe2\x70\xb0\xe5\x7b\xce\xd2\xb5\x8c\xd8\
\x43\x99\xdd\x57\x79\xd2\x23\xf8\xf9\xf6\xbe\xc2\x9b\xe4\xe8\xbe\
\x47\x8a\x05\xbb\xc0\x97\xff\xff\xff\x49\x96\x4a\x76\x00\x00\x00\
\x44\x74\x52\x4e\x53\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
\xff\xff\xff\xff\xff\xff\xff\xff\x00\x71\xd2\x8f\x12\x00\x00\x00\
\x9c\x49\x44\x41\x54\x78\xda\x5c\xcf\xd7\x0e\x83\x30\x0c\x05\x50\
\xb3\xa1\x85\xee\xbd\xe8\xde\x7b\x6f\x62\xf3\xff\xff\xd4\x40\x8a\
\x0a\xbd\x0f\xb1\x74\x24\x5f\x39\xe0\xff\x05\xc2\xb7\x4a\x51\xee\
\x02\x88\x61\x18\xc6\x48\x80\xc7\xf0\x56\xba\x0e\x12\x30\xad\x77\
\x64\xa4\x18\xc8\xcf\x43\x11\x9b\x31\x58\x2c\xc7\x79\xf4\x22\xe0\
\xa5\x8f\x56\x3f\xf3\x5b\xe1\x90\xdb\xf6\xec\x44\x87\xbd\x99\x29\
\x62\xa5\xd1\x9e\x13\xe9\xa8\x94\x5f\x06\x92\xce\x61\xbd\x9a\x5c\
\x24\x0b\x8d\x63\x56\x45\xc9\x02\xf0\x69\xb8\xdf\x99\x1a\xaa\xdd\
\xf3\x08\x4d\xed\xc4\xa1\xe6\x16\xc0\x11\xa7\x83\x53\xe1\xa5\x29\
\xa2\x74\xd0\x1c\xcc\xf7\xf7\xb7\xb1\x7c\x04\x18\x00\x81\x3b\x35\
\xe0\x3f\xf2\x0f\x99\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\
\x82\
\x00\x00\x02\xd1\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -2553,6 +2673,10 @@ qt_resource_name = "\
\x0d\xba\x66\x47\
\x00\x50\
\x00\x69\x00\x63\x00\x61\x00\x72\x00\x64\x00\x33\x00\x32\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x09\
\x07\xbc\x8f\xc7\
\x00\x65\
\x00\x6d\x00\x70\x00\x74\x00\x79\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0c\
\x0e\xe2\x04\x27\
\x00\x6d\
@@ -2615,6 +2739,14 @@ qt_resource_name = "\
\x00\x54\
\x00\x6f\x00\x6f\x00\x6c\x00\x62\x00\x61\x00\x72\x00\x41\x00\x64\x00\x64\x00\x44\x00\x69\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
\
\x00\x07\
\x0a\x7a\x57\xa7\
\x00\x74\
\x00\x61\x00\x67\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0f\
\x03\x8a\x2a\x47\
\x00\x74\
\x00\x72\x00\x61\x00\x63\x00\x6b\x00\x2d\x00\x73\x00\x61\x00\x76\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0d\
\x03\x26\x60\x87\
\x00\x6d\
@@ -2627,33 +2759,36 @@ qt_resource_name = "\
qt_resource_struct = "\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1b\x00\x00\x00\x02\
\x00\x00\x02\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x7e\xb2\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00\x02\
\x00\x00\x02\x34\x00\x00\x00\x00\x00\x01\x00\x00\x7f\x52\
\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x04\x82\
\x00\x00\x00\xf2\x00\x00\x00\x00\x00\x01\x00\x00\x64\x1a\
\x00\x00\x03\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x93\xf5\
\x00\x00\x03\x9e\x00\x00\x00\x00\x00\x01\x00\x00\x99\xbb\
\x00\x00\x03\x7a\x00\x00\x00\x00\x00\x01\x00\x00\x98\xc3\
\x00\x00\x01\x1a\x00\x00\x00\x00\x00\x01\x00\x00\x69\x8f\
\x00\x00\x01\xf2\x00\x00\x00\x00\x00\x01\x00\x00\x7a\x2f\
\x00\x00\x02\x32\x00\x00\x00\x00\x00\x01\x00\x00\x81\x17\
\x00\x00\x02\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x7a\xcf\
\x00\x00\x02\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x81\xb7\
\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x00\xc6\x00\x00\x00\x00\x00\x01\x00\x00\x5b\x7c\
\x00\x00\x02\x78\x00\x00\x00\x00\x00\x01\x00\x00\x88\x3a\
\x00\x00\x01\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x75\xad\
\x00\x00\x03\x6e\x00\x00\x00\x00\x00\x01\x00\x00\x94\xdf\
\x00\x00\x02\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x89\x62\
\x00\x00\x02\x90\x00\x00\x00\x00\x00\x01\x00\x00\x88\xda\
\x00\x00\x01\xb8\x00\x00\x00\x00\x00\x01\x00\x00\x76\x4d\
\x00\x00\x03\xbe\x00\x00\x00\x00\x00\x01\x00\x00\x9b\xf1\
\x00\x00\x02\xb8\x00\x00\x00\x00\x00\x01\x00\x00\x8a\x02\
\x00\x00\x01\x82\x00\x00\x00\x00\x00\x01\x00\x00\x74\xa1\
\x00\x00\x00\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x5f\x23\
\x00\x00\x00\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x0e\x87\
\x00\x00\x03\x66\x00\x00\x00\x00\x00\x01\x00\x00\x94\x95\
\x00\x00\x00\x74\x00\x00\x00\x00\x00\x01\x00\x00\x0a\xb1\
\x00\x00\x02\xca\x00\x00\x00\x00\x00\x01\x00\x00\x8a\xc1\
\x00\x00\x03\x26\x00\x00\x00\x00\x00\x01\x00\x00\x90\xce\
\x00\x00\x02\xe2\x00\x00\x00\x00\x00\x01\x00\x00\x8b\x61\
\x00\x00\x03\x3e\x00\x00\x00\x00\x00\x01\x00\x00\x91\x6e\
\x00\x00\x00\x52\x00\x00\x00\x00\x00\x01\x00\x00\x07\x59\
\x00\x00\x02\xde\x00\x00\x00\x00\x00\x01\x00\x00\x8c\xb7\
\x00\x00\x01\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x78\x46\
\x00\x00\x02\xf6\x00\x00\x00\x00\x00\x01\x00\x00\x8d\x57\
\x00\x00\x01\xec\x00\x00\x00\x00\x00\x01\x00\x00\x78\xe6\
\x00\x00\x01\x64\x00\x00\x00\x00\x00\x01\x00\x00\x6e\x6e\
\x00\x00\x03\x08\x00\x00\x00\x00\x00\x01\x00\x00\x8f\xcd\
\x00\x00\x02\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x87\x36\
\x00\x00\x01\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x77\x54\
\x00\x00\x01\x82\x00\x00\x00\x00\x00\x01\x00\x00\x74\xa1\
\x00\x00\x03\x20\x00\x00\x00\x00\x00\x01\x00\x00\x90\x6d\
\x00\x00\x02\x72\x00\x00\x00\x00\x00\x01\x00\x00\x87\xd6\
\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\x77\xf4\
\x00\x00\x01\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x75\x41\
\x00\x00\x01\x46\x00\x00\x00\x00\x00\x01\x00\x00\x6d\x7c\
"

View File

@@ -74,7 +74,10 @@ class Tagger(QtGui.QApplication, ComponentManager, Component):
self.worker = WorkerThread()
self.connect(self.worker, QtCore.SIGNAL("add_files(const QStringList &)"), self.onAddFiles)
self.connect(self.worker, QtCore.SIGNAL("file_updated(int)"), QtCore.SIGNAL("file_updated(int)"))
self.connect(self.worker,
QtCore.SIGNAL("save_file_finished(PyObject*, bool)"),
self.save_file_finished)
self.browserIntegration = BrowserIntegration()
self.files = {}
@@ -208,8 +211,32 @@ class Tagger(QtGui.QApplication, ComponentManager, Component):
def save(self, objects):
"""Save the specified objects."""
for file in self.get_files_from_objects(objects):
self.worker.save_file(file)
self.save_file(file)
def save_file(self, file):
"""Save the file."""
file.lock_for_write()
try:
file.state = File.TO_BE_SAVED
finally:
file.unlock()
self.worker.save_file(file)
def save_file_finished(self, file, saved):
"""Finalize file saving and notify views."""
if saved:
file.lock_for_write()
try:
file.orig_metadata.copy(file.metadata)
file.metadata.changed = False
file.state = File.SAVED
finally:
file.unlock()
if file.track:
self.emit(QtCore.SIGNAL("track_updated"), file.track)
else:
self.emit(QtCore.SIGNAL("file_updated"), file)
def remove(self, objects):
"""Remove the specified objects."""
files = []
@@ -232,7 +259,7 @@ class Tagger(QtGui.QApplication, ComponentManager, Component):
def load_album(self, album_id):
album = Album(unicode(album_id), "[loading album information]", None)
self.albums.append(album)
self.connect(album, QtCore.SIGNAL("trackUpdated"), self, QtCore.SIGNAL("trackUpdated"))
self.connect(album, QtCore.SIGNAL("track_updated"), self, QtCore.SIGNAL("track_updated"))
self.emit(QtCore.SIGNAL("albumAdded"), album)
self.worker.load_album(album)

View File

@@ -73,3 +73,7 @@ class Track(DataObject):
return self.linked_file.can_remove()
return False
def can_edit_tags(self):
"""Return if this object supports tag editing."""
return False

View File

@@ -24,7 +24,6 @@ from picard.cluster import Cluster
from picard.file import File
from picard.track import Track
from picard.util import format_time, encode_filename, decode_filename
from picard.ui.tageditor import TagEditor
from picard.config import TextOption
__all__ = ["FileTreeView", "AlbumTreeView"]
@@ -58,6 +57,18 @@ class BaseTreeView(QtGui.QTreeWidget):
self.setDropIndicatorShown(True)
self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.lookupAct = QtGui.QAction(QtGui.QIcon(":/images/search.png"), _("&Lookup"), self)
#self.analyze_action = QtGui.QAction(QtGui.QIcon(":/images/analyze.png"), _("&Analyze"), self)
self.contextMenu = QtGui.QMenu(self)
self.contextMenu.addAction(self.main_window.edit_tags_action)
self.contextMenu.addSeparator()
self.contextMenu.addAction(self.lookupAct)
self.contextMenu.addAction(self.main_window.analyze_action)
self.contextMenu.addAction(self.main_window.save_action)
self.contextMenu.addAction(self.main_window.remove_action)
self.objectToItem = {}
self.itemToObject = {}
@@ -124,13 +135,13 @@ class BaseTreeView(QtGui.QTreeWidget):
for item in items:
obj = self.getObjectFromItem(item)
if isinstance(obj, Album):
album_ids.append(str(obj.getId()))
album_ids.append(str(obj.id))
elif isinstance(obj, Track):
print "track:", obj
if obj.is_linked():
file_ids.append(str(obj.linked_file.id))
elif isinstance(obj, File):
file_ids.append(str(obj.getId()))
file_ids.append(str(obj.id))
mimeData = QtCore.QMimeData()
mimeData.setData("application/picard.album-list", "\n".join(album_ids))
mimeData.setData("application/picard.file-list", "\n".join(file_ids))
@@ -218,25 +229,7 @@ class FileTreeView(BaseTreeView):
def __init__(self, main_window, parent):
BaseTreeView.__init__(self, main_window, parent)
# Create the context menu
self.editTagsAct = QtGui.QAction(_("Edit &Tags..."), self)
self.connect(self.editTagsAct, QtCore.SIGNAL("triggered()"), self.editTags)
self.lookupAct = QtGui.QAction(QtGui.QIcon(":/images/search.png"), _("&Lookup"), self)
self.analyzeAct = QtGui.QAction(QtGui.QIcon(":/images/analyze.png"), _("&Analyze"), self)
self.contextMenu = QtGui.QMenu(self)
self.contextMenu.addAction(self.editTagsAct)
self.contextMenu.addSeparator()
self.contextMenu.addAction(self.lookupAct)
self.contextMenu.addAction(self.analyzeAct)
self.contextMenu.addAction(self.main_window.save_action)
self.contextMenu.addAction(self.main_window.remove_action)
# Prepare some common icons
self.dirIcon = QtGui.QIcon(":/images/dir.png")
self.fileIcon = QtGui.QIcon(":/images/file.png")
@@ -280,9 +273,9 @@ class FileTreeView(BaseTreeView):
#canAnalyze = True
canRemove = True
self.editTagsAct.setEnabled(canEditTags)
self.lookupAct.setEnabled(canLookup)
self.analyzeAct.setEnabled(canAnalyze)
#self.editTagsAct.setEnabled(canEditTags)
#self.lookupAct.setEnabled(canLookup)
#self.analyze_action.setEnabled(canAnalyze)
#self.remove_action.setEnabled(canRemove)
self.contextMenu.popup(event.globalPos())
@@ -327,19 +320,10 @@ class FileTreeView(BaseTreeView):
self.unregisterObject(file)
self.updateCluster(cluster)
def openTagEditor(self, obj):
tagEditor = TagEditor(obj.metadata, self)
tagEditor.exec_()
self.emit(QtCore.SIGNAL("selectionChanged"), [obj])
def editTags(self):
objects = self.selected_objects()
self.openTagEditor(objects[0])
def handleDoubleClick(self, index):
obj = self.itemToObject[self.itemFromIndex(index)]
if isinstance(obj, File):
self.openTagEditor(obj)
if obj.can_edit_tags():
self.main_window.edit_tags(obj)
class AlbumTreeView(BaseTreeView):
@@ -356,26 +340,35 @@ class AlbumTreeView(BaseTreeView):
QtGui.QIcon(":/images/match-90.png"),
QtGui.QIcon(":/images/match-100.png"),
]
self.icon_saved = QtGui.QIcon(":/images/track-saved.png")
self.connect(self.tagger, QtCore.SIGNAL("albumAdded"), self.addAlbum)
self.connect(self.tagger, QtCore.SIGNAL("albumRemoved"), self.remove_album)
self.connect(self.tagger, QtCore.SIGNAL("trackUpdated"), self.updateTrack)
self.connect(self.tagger.worker, QtCore.SIGNAL("albumLoaded(QString)"),
self.updateAlbum)
self.connect(self.tagger, QtCore.SIGNAL("track_updated"),
self.update_track)
def updateTrack(self, track):
def update_track(self, track):
# Update track background
item = self.getItemFromObject(track)
if track.is_linked():
similarity = track.linked_file.get_similarity()
item.setIcon(0, self.matchIcons[int(similarity * 5 + 0.5)])
file = track.linked_file
if file.state == File.SAVED:
similarity = 1.0
icon = self.icon_saved
else:
similarity = track.linked_file.get_similarity()
icon = self.matchIcons[int(similarity * 5 + 0.5)]
else:
similarity = 1
item.setIcon(0, self.noteIcon)
icon = self.noteIcon
color = matchColor(similarity)
for i in range(3):
item.setBackgroundColor(i, color)
item.setIcon(0, icon)
# Update track name
albumItem = self.getItemFromObject(track.album)
albumItem.setText(0, track.album.getName())

View File

@@ -31,6 +31,7 @@ from picard.ui.coverartbox import CoverArtBox
from picard.ui.metadatabox import MetadataBox
from picard.ui.itemviews import FileTreeView, AlbumTreeView
from picard.ui.options import OptionsDialog, OptionsDialogProvider
from picard.ui.tageditor import TagEditor
class MainWindow(QtGui.QMainWindow):
@@ -92,7 +93,7 @@ class MainWindow(QtGui.QMainWindow):
self.connect(self.serverMetadataBox, QtCore.SIGNAL("file_updated(int)"), self, QtCore.SIGNAL("file_updated(int)"))
self.coverArtBox = CoverArtBox(self)
if not self.showCoverArtAct.isChecked():
if not self.show_cover_art_action.isChecked():
self.coverArtBox.hide()
bottomLayout = QtGui.QHBoxLayout()
@@ -124,7 +125,7 @@ class MainWindow(QtGui.QMainWindow):
self.config.persist["window_position"] = self.pos()
self.config.persist["window_size"] = self.size()
self.config.persist["window_maximized"] = isMaximized
self.config.persist["view_cover_art"] = self.showCoverArtAct.isChecked()
self.config.persist["view_cover_art"] = self.show_cover_art_action.isChecked()
self.fileTreeView.saveState()
self.albumTreeView.saveState()
@@ -139,40 +140,40 @@ class MainWindow(QtGui.QMainWindow):
self.statusBar().showMessage(_("Ready"))
def createActions(self):
self.optionsAct = QtGui.QAction(QtGui.QIcon(":/images/ToolbarOptions.png"), "&Options...", self)
self.options_action = QtGui.QAction(QtGui.QIcon(":/images/ToolbarOptions.png"), "&Options...", self)
#self.openSettingsAct.setShortcut("Ctrl+O")
self.connect(self.optionsAct, QtCore.SIGNAL("triggered()"), self.showOptions)
self.connect(self.options_action, QtCore.SIGNAL("triggered()"), self.showOptions)
self.helpAct = QtGui.QAction(_("&Help..."), self)
self.help_action = QtGui.QAction(_("&Help..."), self)
# TR: Keyboard shortcut for "Help"
self.helpAct.setShortcut(QtGui.QKeySequence(_("Ctrl+H")))
#self.connect(self.helpAct, QtCore.SIGNAL("triggered()"), self.showHelp)
self.help_action.setShortcut(QtGui.QKeySequence(_("Ctrl+H")))
#self.connect(self.help_action, QtCore.SIGNAL("triggered()"), self.showHelp)
self.aboutAct = QtGui.QAction(_("&About..."), self)
#self.connect(self.aboutAct, QtCore.SIGNAL("triggered()"), self.showAbout)
self.about_action = QtGui.QAction(_("&About..."), self)
#self.connect(self.about_action, QtCore.SIGNAL("triggered()"), self.showAbout)
self.add_filesAct = QtGui.QAction(QtGui.QIcon(":/images/ToolbarAddFiles.png"), _("&Add Files..."), self)
self.add_filesAct.setStatusTip(_("Add files to the tagger"))
self.add_files_action = QtGui.QAction(QtGui.QIcon(":/images/ToolbarAddFiles.png"), _("&Add Files..."), self)
self.add_files_action.setStatusTip(_("Add files to the tagger"))
# TR: Keyboard shortcut for "Add Files..."
self.add_filesAct.setShortcut(QtGui.QKeySequence(_("Ctrl+O")))
self.connect(self.add_filesAct, QtCore.SIGNAL("triggered()"), self.add_files)
self.add_files_action.setShortcut(QtGui.QKeySequence(_("Ctrl+O")))
self.connect(self.add_files_action, QtCore.SIGNAL("triggered()"), self.add_files)
self.addDirectoryAct = QtGui.QAction(QtGui.QIcon(":/images/ToolbarAddDir.png"), _("A&dd Directory..."), self)
self.addDirectoryAct.setStatusTip(_("Add a directory to the tagger"))
self.add_directory_action = QtGui.QAction(QtGui.QIcon(":/images/ToolbarAddDir.png"), _("A&dd Directory..."), self)
self.add_directory_action.setStatusTip(_("Add a directory to the tagger"))
# TR: Keyboard shortcut for "Add Directory..."
self.addDirectoryAct.setShortcut(QtGui.QKeySequence(_("Ctrl+D")))
self.connect(self.addDirectoryAct, QtCore.SIGNAL("triggered()"), self.addDirectory)
self.add_directory_action.setShortcut(QtGui.QKeySequence(_("Ctrl+D")))
self.connect(self.add_directory_action, QtCore.SIGNAL("triggered()"), self.addDirectory)
self.save_action = QtGui.QAction(QtGui.QIcon(":/images/ToolbarSave.png"), _("&Save"), self)
self.addDirectoryAct.setStatusTip(_("Save selected files"))
self.add_directory_action.setStatusTip(_("Save selected files"))
# TR: Keyboard shortcut for "Save"
self.save_action.setShortcut(QtGui.QKeySequence(_("Ctrl+S")))
self.save_action.setEnabled(False)
self.connect(self.save_action, QtCore.SIGNAL("triggered()"), self.save)
self.submitAct = QtGui.QAction(QtGui.QIcon(":/images/ToolbarSubmit.png"), _("S&ubmit PUIDs to MusicBrainz"), self)
self.submitAct.setEnabled(False)
self.connect(self.submitAct, QtCore.SIGNAL("triggered()"), self.submit)
self.submit_action = QtGui.QAction(QtGui.QIcon(":/images/ToolbarSubmit.png"), _("S&ubmit PUIDs to MusicBrainz"), self)
self.submit_action.setEnabled(False)
self.connect(self.submit_action, QtCore.SIGNAL("triggered()"), self.submit)
self.exitAct = QtGui.QAction(_("E&xit"), self)
self.exitAct.setShortcut(QtGui.QKeySequence(_("Ctrl+Q")))
@@ -183,84 +184,86 @@ class MainWindow(QtGui.QMainWindow):
self.remove_action.setEnabled(False)
self.connect(self.remove_action, QtCore.SIGNAL("triggered()"), self.remove)
self.showFileBrowserAct = QtGui.QAction(_("File &Browser"), self)
self.showFileBrowserAct.setCheckable(True)
self.show_file_browser_action = QtGui.QAction(_("File &Browser"), self)
self.show_file_browser_action.setCheckable(True)
#if self.config.persi.value("persist/viewFileBrowser").toBool():
# self.showFileBrowserAct.setChecked(True)
# self.connect(self.showFileBrowserAct, QtCore.SIGNAL("triggered()"), self.showFileBrowser)
# self.show_file_browser_action.setChecked(True)
# self.connect(self.show_file_browser_action, QtCore.SIGNAL("triggered()"), self.showFileBrowser)
self.showCoverArtAct = QtGui.QAction(_("&Cover Art"), self)
self.showCoverArtAct.setCheckable(True)
self.show_cover_art_action = QtGui.QAction(_("&Cover Art"), self)
self.show_cover_art_action.setCheckable(True)
if self.config.persist["view_cover_art"]:
self.showCoverArtAct.setChecked(True)
self.connect(self.showCoverArtAct, QtCore.SIGNAL("triggered()"), self.showCoverArt)
self.show_cover_art_action.setChecked(True)
self.connect(self.show_cover_art_action, QtCore.SIGNAL("triggered()"), self.showCoverArt)
self.searchAct = QtGui.QAction(QtGui.QIcon(":/images/search.png"), _("Search"), self)
self.connect(self.searchAct, QtCore.SIGNAL("triggered()"), self.search)
self.search_action = QtGui.QAction(QtGui.QIcon(":/images/search.png"), _("Search"), self)
self.connect(self.search_action, QtCore.SIGNAL("triggered()"), self.search)
self.listenAct = QtGui.QAction(QtGui.QIcon(":/images/ToolbarListen.png"), _("Listen"), self)
self.listenAct.setEnabled(False)
self.connect(self.listenAct, QtCore.SIGNAL("triggered()"), self.listen)
self.cdLookupAct = QtGui.QAction(QtGui.QIcon(":/images/ToolbarLookup.png"), _("&Lookup CD"), self)
self.cdLookupAct.setEnabled(False)
self.cdLookupAct.setShortcut(QtGui.QKeySequence(_("Ctrl+L")))
self.cd_lookup_action = QtGui.QAction(QtGui.QIcon(":/images/ToolbarLookup.png"), _("&Lookup CD"), self)
self.cd_lookup_action.setEnabled(False)
self.cd_lookup_action.setShortcut(QtGui.QKeySequence(_("Ctrl+L")))
self.analyzeAct = QtGui.QAction(QtGui.QIcon(":/images/analyze.png"), _("Anal&yze"), self)
self.analyzeAct.setEnabled(False)
self.analyzeAct.setShortcut(QtGui.QKeySequence(_("Ctrl+Y")))
self.analyze_action = QtGui.QAction(QtGui.QIcon(":/images/analyze.png"), _("Anal&yze"), self)
self.analyze_action.setEnabled(False)
self.analyze_action.setShortcut(QtGui.QKeySequence(_("Ctrl+Y")))
self.clusterAct = QtGui.QAction(QtGui.QIcon(":/images/ToolbarCluster.png"), _("Cluster"), self)
self.clusterAct.setEnabled(False)
self.clusterAct.setShortcut(QtGui.QKeySequence(_("Ctrl+U")))
self.cluster_action = QtGui.QAction(QtGui.QIcon(":/images/ToolbarCluster.png"), _("Cluster"), self)
self.cluster_action.setEnabled(False)
self.cluster_action.setShortcut(QtGui.QKeySequence(_("Ctrl+U")))
self.autoTagAct = QtGui.QAction(QtGui.QIcon(":/images/magic-wand.png"), _("Auto Tag"), self)
self.autoTagAct.setShortcut(QtGui.QKeySequence(_("Ctrl+T")))
self.connect(self.autoTagAct, QtCore.SIGNAL("triggered()"), self.autoTag)
self.auto_tag_action = QtGui.QAction(QtGui.QIcon(":/images/magic-wand.png"), _("Auto Tag"), self)
self.auto_tag_action.setShortcut(QtGui.QKeySequence(_("Ctrl+T")))
self.connect(self.auto_tag_action, QtCore.SIGNAL("triggered()"), self.autoTag)
self.edit_tags_action = QtGui.QAction(QtGui.QIcon(":/images/tag.png"),
_("Edit &Tags..."), self)
self.edit_tags_action.setEnabled(False)
self.connect(self.edit_tags_action, QtCore.SIGNAL("triggered()"),
self.edit_tags)
def createMenus(self):
self.fileMenu = self.menuBar().addMenu(_("&File"))
self.fileMenu.addAction(self.add_filesAct)
self.fileMenu.addAction(self.addDirectoryAct)
self.fileMenu.addAction(self.add_files_action)
self.fileMenu.addAction(self.add_directory_action)
self.fileMenu.addSeparator()
self.fileMenu.addAction(self.save_action)
self.fileMenu.addAction(self.submitAct)
self.fileMenu.addAction(self.submit_action)
self.fileMenu.addSeparator()
self.fileMenu.addAction(self.exitAct)
self.editMenu = self.menuBar().addMenu(_("&Edit"))
self.editMenu.addSeparator()
self.editMenu.addAction(self.optionsAct)
self.editMenu.addAction(self.options_action)
self.viewMenu = self.menuBar().addMenu(_("&View"))
self.viewMenu.addAction(self.showFileBrowserAct)
self.viewMenu.addAction(self.showCoverArtAct)
self.viewMenu.addAction(self.show_file_browser_action)
self.viewMenu.addAction(self.show_cover_art_action)
self.menuBar().addSeparator()
self.helpMenu = self.menuBar().addMenu(_("&Help"))
self.helpMenu.addAction(self.helpAct)
self.helpMenu.addAction(self.aboutAct)
self.helpMenu.addAction(self.help_action)
self.helpMenu.addAction(self.about_action)
def createToolBar(self):
self.mainToolBar = self.addToolBar(self.tr("File"))
self.mainToolBar.setObjectName("fileToolbar")
self.mainToolBar.addAction(self.add_filesAct)
self.mainToolBar.addAction(self.addDirectoryAct)
self.mainToolBar.addAction(self.add_files_action)
self.mainToolBar.addAction(self.add_directory_action)
self.mainToolBar.addSeparator()
self.mainToolBar.addAction(self.save_action)
self.mainToolBar.addAction(self.submitAct)
self.mainToolBar.addSeparator()
self.mainToolBar.addAction(self.cdLookupAct)
self.mainToolBar.addAction(self.analyzeAct)
self.mainToolBar.addAction(self.clusterAct)
self.mainToolBar.addAction(self.autoTagAct)
self.mainToolBar.addAction(self.submit_action)
self.mainToolBar.addSeparator()
self.mainToolBar.addAction(self.cd_lookup_action)
self.mainToolBar.addAction(self.analyze_action)
self.mainToolBar.addAction(self.cluster_action)
self.mainToolBar.addAction(self.auto_tag_action)
#self.mainToolBar.addSeparator()
self.mainToolBar.addAction(self.edit_tags_action)
self.mainToolBar.addAction(self.remove_action)
self.mainToolBar.addSeparator()
self.mainToolBar.addAction(self.optionsAct)
self.mainToolBar.addSeparator()
self.mainToolBar.addAction(self.listenAct)
self.mainToolBar.addAction(self.options_action)
#self.mainToolBar.addSeparator()
self.searchToolBar = self.addToolBar(_("Search"))
self.searchToolBar.setObjectName("searchToolbar")
@@ -283,7 +286,7 @@ class MainWindow(QtGui.QMainWindow):
#hbox.addWidget(button, 0)
self.searchToolBar.addWidget(searchPanel)
self.searchToolBar.addAction(self.searchAct)
self.searchToolBar.addAction(self.search_action)
def setStatusBarMessage(self, message):
"""Set the status bar message."""
@@ -335,12 +338,15 @@ class MainWindow(QtGui.QMainWindow):
"""Tell the tagger to remove the selected objects."""
self.tagger.remove(self.selected_objects)
def listen(self):
pass
def submit(self):
pass
def edit_tags(self, obj=None):
if not obj:
obj = self.selected_objects[0]
tagedit = TagEditor(obj.metadata, self)
tagedit.exec_()
def updateFileTreeSelection(self):
if not self.ignoreSelectionChange:
objs = self.fileTreeView.selected_objects()
@@ -362,15 +368,21 @@ class MainWindow(QtGui.QMainWindow):
def update_actions(self):
can_remove = False
can_save = False
can_edit_tags = False
for obj in self.selected_objects:
if obj.can_save():
can_save = True
if obj.can_remove():
can_remove = True
if can_save and can_remove:
if obj.can_edit_tags():
can_edit_tags = True
if can_save and can_remove and can_edit_tags:
break
if len(self.selected_objects) != 1:
can_edit_tags = False
self.remove_action.setEnabled(can_remove)
self.save_action.setEnabled(can_save)
self.edit_tags_action.setEnabled(can_edit_tags)
def updateSelection(self, objects=None):
if objects is not None:
@@ -412,7 +424,7 @@ class MainWindow(QtGui.QMainWindow):
def showCoverArt(self):
"""Show/hide the cover art box."""
if self.showCoverArtAct.isChecked():
if self.show_cover_art_action.isChecked():
self.coverArtBox.show()
else:
self.coverArtBox.hide()
@@ -421,3 +433,4 @@ class MainWindow(QtGui.QMainWindow):
files = [obj for obj in self.selected_objects if isinstance(obj, File)]
self.tagger.autoTag(files)

View File

@@ -31,7 +31,7 @@ class TagsOptionsPage(Component):
BoolOption("setting", "clear_existing_tags", False),
BoolOption("setting", "write_id3v1", True),
BoolOption("setting", "write_id3v23", False),
TextOption("setting", "id3v2_encoding", "UTF-8"),
TextOption("setting", "id3v2_encoding", "utf-8"),
]
def get_page_info(self):

View File

@@ -102,8 +102,32 @@ class WorkerThread(QtCore.QThread):
def do_save_file(self, args):
file = args[1]
self.log.debug("Saving file %s", file)
file.lock_for_read()
self.emit(QtCore.SIGNAL("statusBarMessage(const QString &)"),
QtCore.QString(_(u"Saving file %s ...") % file.filename))
file.save()
self.emit(QtCore.SIGNAL("file_updated(int)"), file.id)
saved = True
try:
file.save()
except Exception, e:
self.log.error(e)
saved = False
if saved:
if self.config.setting["rename_files"]:
format = self.config.setting["file_naming_format"]
filename = self.tagger.evaluate_script(format, self.metadata)
filename = os.path.basename(filename) + \
os.path.splitext(self.filename)[1]
filename = os.path.join(os.path.dirname(file.filename),
filename)
os.rename(self.filename, filename)
self.filename = filename
file.unlock()
self.emit(QtCore.SIGNAL("save_file_finished(PyObject*, bool)"),
file, saved)