Comparar commits
554 Commits
v0.8
...
release-2.0
| Autor | SHA1 | Data | |
|---|---|---|---|
| 0d2c984564 | |||
| 3bf1747540 | |||
| c72e2e5ca5 | |||
| ecb4d48624 | |||
| bc46b63133 | |||
| 37510a762c | |||
| 2d6c2a5722 | |||
| eb562ed4e9 | |||
| 4058056b70 | |||
| a9fe7ddd27 | |||
| ac52161047 | |||
| e2803df857 | |||
| 8aa2e7105e | |||
| f968221bff | |||
| 90b4bf31f3 | |||
| 49b355b8cf | |||
| edfd24bbd3 | |||
| c5042bdc57 | |||
| e6c650d7b8 | |||
| 52e3e7e2ef | |||
| 82558792b5 | |||
| e0e5e5b812 | |||
| 31041fa39a | |||
| 1dcbc4ce07 | |||
| 003b10afa6 | |||
| c1fbb27b0c | |||
| 657abe17fb | |||
| ba5d9e139a | |||
| d345e75952 | |||
| 0f20559e2f | |||
| 5977335253 | |||
| 6d5be5812a | |||
| 5c20b3bdcc | |||
| 17c871897e | |||
| 8947aebe48 | |||
| 802cd5a36a | |||
| 115a652a71 | |||
| 2148fd428a | |||
| 9c90b0b8bb | |||
| e10a75945a | |||
| b1837365a2 | |||
| d9dc24447c | |||
| b35f4b5615 | |||
| ad04ae14dd | |||
| 8392648ffe | |||
| fd07433c87 | |||
| a78ad58de5 | |||
| 052df42b29 | |||
| cd3847ba67 | |||
| cabc112d1c | |||
| cfde5a42b4 | |||
| 72710425e5 | |||
| 606bb0d065 | |||
| 7ec7ff72e3 | |||
| b6dd370470 | |||
| 5b23026ae8 | |||
| e71656aeb3 | |||
| 67b5575fb4 | |||
| 0a71517161 | |||
| 5735d6d6f3 | |||
| c98881b676 | |||
| 7806c91c86 | |||
| a34ebbd3db | |||
| 635afa73e5 | |||
| ee5b1a19ea | |||
| cb3b67991b | |||
| 1504c90b4d | |||
| 9a8efff960 | |||
| 9068149d07 | |||
| 4decb6c260 | |||
| 8303145003 | |||
| 039a772795 | |||
| 84f34bcf18 | |||
| c766a4dedc | |||
| 4fe43a950f | |||
| 437dc66cf7 | |||
| d4e172aafb | |||
| 28a8c346c7 | |||
| a4c8d23fbb | |||
| d35f173453 | |||
| 3a9589074f | |||
| 8cf80c99bd | |||
| 0bbde2077c | |||
| 519fb78c84 | |||
| 2d828b4587 | |||
| 0dd34ca8f3 | |||
| 2d6bcd02b6 | |||
| 5fa4fd391e | |||
| 535059df62 | |||
| 6f10706ac1 | |||
| a5a3d6b85c | |||
| cae74bf6e7 | |||
| 08b979fa0a | |||
| 7a20522c2f | |||
| 8243b2ed34 | |||
| 1ea5d3dd67 | |||
| 4c2ef51454 | |||
| c7696d412c | |||
| 82adb4653d | |||
| 41e80ee47b | |||
| 87ea90d054 | |||
| ec24905ed0 | |||
| 1758a56ef2 | |||
| 934606eb2f | |||
| 043790eda2 | |||
| eed81c45a1 | |||
| edf995395a | |||
| e12d09e52e | |||
| 0ec0cd8f75 | |||
| 473b656412 | |||
| 22c0b68add | |||
| 8edf61af6a | |||
| e8aad1c034 | |||
| 4091c9be50 | |||
| d2be6895f0 | |||
| 52b8588f3f | |||
| e7669d3117 | |||
| 1804a55426 | |||
| b514740e19 | |||
| d39e964bc5 | |||
| c7f6281e11 | |||
| 4afc22c686 | |||
| fb64f74663 | |||
| 3896c62844 | |||
| 52033cb0a9 | |||
| 48c21be900 | |||
| 72a903992d | |||
| f8351aadb4 | |||
| 29da8eda3e | |||
| b202684e0a | |||
| 873571f1ab | |||
| 48342cdd18 | |||
| 90e02345fb | |||
| b48731ed6a | |||
| 870b4cdd7b | |||
| ecfdc66706 | |||
| aa8d23e65b | |||
| 5013de9127 | |||
| 0c0d4d6c57 | |||
| 9da85017b9 | |||
| 4174f71436 | |||
| 3088768fe6 | |||
| acb6caaba0 | |||
| 8619d73007 | |||
| 18666de36f | |||
| e9af41d634 | |||
| 9763743a95 | |||
| b6ffa2de70 | |||
| 74adbe6c3f | |||
| fd42d4e601 | |||
| 0b97a39edc | |||
| 23e2ed5297 | |||
| 273841ec65 | |||
| d128149d8d | |||
| 9cdf49e975 | |||
| 74319826d2 | |||
| afea82eee5 | |||
| dda323ac04 | |||
| a09a25690c | |||
| f27ee2464c | |||
| 18aaf08f4b | |||
| c03166007f | |||
| 0c66334569 | |||
| 1e88bab104 | |||
| b2eabeb8eb | |||
| d93ea16d1a | |||
| ac321f7815 | |||
| c53e6c33f8 | |||
| 368dda444b | |||
| d2640cf11a | |||
| b56ec0e5d9 | |||
| 5d0d513f93 | |||
| 914098f4f4 | |||
| 16beb62e9c | |||
| c1eb1d279e | |||
| f9ab0104cd | |||
| 1a7e154f64 | |||
| 4cfe692b9e | |||
| d165f5fc0c | |||
| 06a7478c70 | |||
| 7d629e5bcb | |||
| 5ddf0b306c | |||
| ade9939053 | |||
| e6f8c887c9 | |||
| db09860d08 | |||
| 1718296e46 | |||
| f5a6b56c3a | |||
| 53ff1990d2 | |||
| 4e5929237f | |||
| f1f4f451b8 | |||
| 581c1b6c0c | |||
| 2cafad60b6 | |||
| 1cd75c4664 | |||
| 161997c0d0 | |||
| cc32904e80 | |||
| c0edd4895e | |||
| f9dfa0c39d | |||
| 7eaeebf168 | |||
| 290f06981e | |||
| 87de8b9a8b | |||
| 7a233c2dbb | |||
| 931135ba70 | |||
| adba91d077 | |||
| 466112068a | |||
| 767e2791cf | |||
| f60bf048b2 | |||
| 006d621327 | |||
| 03b01b58f2 | |||
| e915b353cc | |||
| cf8e2b383e | |||
| 272127f5a3 | |||
| d4f0e9212a | |||
| 78546f3643 | |||
| e1cd035095 | |||
| 07aca0cdf6 | |||
| 7b96b47a6c | |||
| d3654e1457 | |||
| 98045cae32 | |||
| 50ae5a2a99 | |||
| 0ca674fb7b | |||
| 0ed6f0e3ec | |||
| ed1d8899be | |||
| 0c8d408688 | |||
| d67a802b3d | |||
| 51c05b6202 | |||
| 2a098b1047 | |||
| 5effd50acd | |||
| 729d7f1ff0 | |||
| 47faf9a509 | |||
| 6afe9bbed5 | |||
| 6bb5f885bb | |||
| f763b00f3a | |||
| 7d903e84cf | |||
| 7cbf51d168 | |||
| 4a1443cf66 | |||
| 7a45d9531e | |||
| b1544a8983 | |||
| 1ff243df66 | |||
| 9076627ca9 | |||
| 49d9540f8c | |||
| 5d1e68c268 | |||
| 4692c6b8ee | |||
| f34fd79952 | |||
| 295ee80351 | |||
| a508e52f0d | |||
| 2bda0f1cb0 | |||
| 74f37075e5 | |||
| 88821ef68a | |||
| 677855e5c7 | |||
| d593463a25 | |||
| 66070a6b0e | |||
| 66b4895458 | |||
| 2f6af4fa7a | |||
| 80eefa8737 | |||
| 5fa51b6ed3 | |||
| 4bdd1b4809 | |||
| 0c65a494d6 | |||
| f0acad9dca | |||
| 10b4c152c4 | |||
| 1eab887896 | |||
| 616ccb2d53 | |||
| 8b5e234cd2 | |||
| dfc0002a2c | |||
| 111147ca2a | |||
| 297378349c | |||
| 0678179585 | |||
| a03119ef29 | |||
| 66ddba7d78 | |||
| 4a23b78816 | |||
| 07273d8351 | |||
| 1dc678f31f | |||
| 64f7f3a978 | |||
| 846e995d82 | |||
| 840ef0fd68 | |||
| c562d3c4b3 | |||
| b2aec88ccf | |||
| 7302165293 | |||
| 9502bcf528 | |||
| afbc8bd3b9 | |||
| 958e6ad6de | |||
| 7027112b58 | |||
| 2c8554d79f | |||
| 16f6055488 | |||
| d09ac59971 | |||
| 9e83e420bc | |||
| 7e2eb1b8f9 | |||
| d7b7de854a | |||
| 025cd52e3c | |||
| ab7643d7fa | |||
| 211f4019bb | |||
| 5ccd07e4b2 | |||
| 7b2c529228 | |||
| 2a28592360 | |||
| 00e0c80594 | |||
| a79591f9c0 | |||
| f32713855f | |||
| 27fdc07f28 | |||
| 8ba870184d | |||
| bd9f7c52c0 | |||
| 3fd7fa281e | |||
| cafda03761 | |||
| 752357ad68 | |||
| 1394cedbd2 | |||
| 5bc4d5ef31 | |||
| 97ec1dab0a | |||
| d0e3f218e0 | |||
| e37655d7e0 | |||
| d8967fb4e1 | |||
| b7a5a8e023 | |||
| 57808278d3 | |||
| 9412ddfb29 | |||
| d99cab53d1 | |||
| 9312c37305 | |||
| f8eb618d84 | |||
| 3f610a74a1 | |||
| 12826cdde6 | |||
| c6eb082aca | |||
| 58815e03a9 | |||
| 1380515c63 | |||
| 3c18ca9052 | |||
| f9422d8a19 | |||
| d64f1bcaf7 | |||
| 27c386e172 | |||
| 5e2cec619e | |||
| 8ab66a192f | |||
| 4e480c40fe | |||
| 9b58df3784 | |||
| 34583e0086 | |||
| 368e582fe2 | |||
| 186977f6ef | |||
| ce119120b7 | |||
| 6759472a2e | |||
| 58ef685380 | |||
| 594feaca93 | |||
| edcf74f005 | |||
| a6993e3d2e | |||
| 5ccc4c1c7d | |||
| 35335da6b8 | |||
| ba9ae93d87 | |||
| 6b999b0099 | |||
| 388e8faec6 | |||
| da92ed7d9a | |||
| a17a32e33b | |||
| 17db0b98df | |||
| d500fdb0bf | |||
| 69fccf10f4 | |||
| fa2050486e | |||
| 3f85bc1da6 | |||
| 9d59cb0748 | |||
| e1aa1ba082 | |||
| 8ac60117ac | |||
| 7179b2e601 | |||
| e93a7dd36b | |||
| 85df2fa79d | |||
| 3e55c8daa9 | |||
| 59f1a840ec | |||
| 74d6a62238 | |||
| ef657da311 | |||
| 250eea8053 | |||
| f243e2aba2 | |||
| e47c3dedac | |||
| 2a2a51c1ed | |||
| c27ae05e3c | |||
| 00ccb84fc3 | |||
| 83e73f95d5 | |||
| 154e5df152 | |||
| 5781a67a70 | |||
| 0322dfd248 | |||
| ecd1a07026 | |||
| 3273c920ec | |||
| 7b33009e67 | |||
| 73e218e99f | |||
| 30a6ebeb45 | |||
| 2e27bbd794 | |||
| a029c43144 | |||
| 474fba83c0 | |||
| 491d35b581 | |||
| e7b68f91b7 | |||
| c348988325 | |||
| 6c76820891 | |||
| fadb361a0c | |||
| 52d6828480 | |||
| 9d0666144b | |||
| c9d27129b1 | |||
| 5fc8e853ad | |||
| 0c072028c0 | |||
| bc3d194920 | |||
| da37365b38 | |||
| ebfc12ef15 | |||
| 017312e7c5 | |||
| 5302cca0a1 | |||
| b9f82a794f | |||
| b9ac6a5c8a | |||
| 1e1e6481a9 | |||
| 6840a52d67 | |||
| 42fb3f650b | |||
| 9130f32038 | |||
| 6a7b7f7146 | |||
| f4f1086883 | |||
| 14b84f1a9c | |||
| 44cf1a94c6 | |||
| e348ec9b45 | |||
| 0ea4d413c3 | |||
| 69800ebb6d | |||
| e9c869e5ad | |||
| 34367b8e85 | |||
| 77436aca08 | |||
| d72cac5424 | |||
| 10d26bb4d3 | |||
| f9cff865bf | |||
| 0e43b68a73 | |||
| 0541665488 | |||
| 76a9610422 | |||
| 6c09a042f9 | |||
| 844a514ccc | |||
| b991fd6993 | |||
| ab47c5f97d | |||
| 6a5eace53d | |||
| 639429fed1 | |||
| 28ee9474f8 | |||
| b98ea85bdb | |||
| bb02cbc035 | |||
| 3ef9bb6afc | |||
| b3ed080e09 | |||
| eb5014483a | |||
| 8bd4799bf4 | |||
| a3c3631ecb | |||
| e4ecbb3c11 | |||
| 94f7e1045e | |||
| a5a9096732 | |||
| 1f3f5b7df1 | |||
| da09955aeb | |||
| 1fce749c3e | |||
| 1bb5e94b1e | |||
| f19a5d3e75 | |||
| e479bb2983 | |||
| 2d61b6ebab | |||
| 339b25633a | |||
| a651ac93d4 | |||
| 44a281ff99 | |||
| 64b900f21a | |||
| dd84f9183c | |||
| acb86fea37 | |||
| dcc89ed8a2 | |||
| 100a552d56 | |||
| f96bc30716 | |||
| 727165a9d5 | |||
| b6bb7eaeb6 | |||
| 6002454340 | |||
| 023ebcf1d3 | |||
| 4a3add381b | |||
| 206f574cdf | |||
| 9789b697f0 | |||
| 0116413aa2 | |||
| 2b03440adc | |||
| d22355d29d | |||
| 1ccde3b5d4 | |||
| a10dc87ef0 | |||
| 828787dc8d | |||
| bc7052f671 | |||
| afc4a2939c | |||
| 5bad5fa5e2 | |||
| 452de7f834 | |||
| 205fa02435 | |||
| 791787559b | |||
| 70575fb308 | |||
| 7360482c9d | |||
| d05231de82 | |||
| 8b38ae236e | |||
| 0ed9d54e22 | |||
| e7d7efaf61 | |||
| 4cac3ed47d | |||
| 777e78fbc4 | |||
| e5e66a1f24 | |||
| 6aaee47cb6 | |||
| db028fa7c8 | |||
| 2f50a382ea | |||
| 60c6cba7cf | |||
| 424f18799d | |||
| b12423ca63 | |||
| f6c23576a0 | |||
| 5c1736cb04 | |||
| ebe6678e43 | |||
| 6ab0bcecd3 | |||
| b0b6a09100 | |||
| 97e1f79ad5 | |||
| 302048e93b | |||
| 157cc0359b | |||
| 85b76af44a | |||
| 6f29b47576 | |||
| 45aa5281e2 | |||
| 6f4ff35547 | |||
| b578d8f386 | |||
| 8d40dad422 | |||
| c7d6dc3481 | |||
| 953a159018 | |||
| 68aacc4f72 | |||
| 1dad8ae6d3 | |||
| 6860b4d4a3 | |||
| 28e6ad9a04 | |||
| c2260d6806 | |||
| 6ffdc361b3 | |||
| 4e8a081cad | |||
| 193bd37572 | |||
| e666803e2d | |||
| d6128831c4 | |||
| 3277635a97 | |||
| cd1a6d1f91 | |||
| ce452dbba5 | |||
| cf0b264062 | |||
| e95e4a0af7 | |||
| c851f3d913 | |||
| 83168a14bd | |||
| b792a42371 | |||
| dc0b9a113b | |||
| 77a3867152 | |||
| 6fb90792af | |||
| dabb80dc65 | |||
| 8855b85653 | |||
| ccff276ab0 | |||
| 8f42a9ea71 | |||
| c094a8f445 | |||
| ae44b76a41 | |||
| 263df5c62c | |||
| c7f8fe0ded | |||
| 3bd947bf16 | |||
| 65de81ebc0 | |||
| a4c8cc4258 | |||
| bc59cd85a2 | |||
| 08dc4ee2e1 | |||
| c098d0a5ac | |||
| 419b95d49c | |||
| 8f3c66b726 | |||
| 35b2bda943 | |||
| 7c584aa1e3 | |||
| d1583f78f5 | |||
| fd4f1a86fd | |||
| 8d58c448e8 | |||
| 83f0194f2f | |||
| 6347abcd2f | |||
| 09c73972a5 | |||
| e9f16ab6b3 | |||
| 0a012d97bc | |||
| d674618904 | |||
| 9349e965c3 | |||
| 0a6dc5620b | |||
| f78c77c98d | |||
| 2550d46f15 | |||
| c868c1a44e | |||
| aa44101ed5 | |||
| c6099bb89d | |||
| c0a5d2566f | |||
| 9f4b104322 | |||
| 522cdb25f8 |
@@ -7,6 +7,7 @@ dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
.idea
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
|
||||
@@ -0,0 +1,621 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. {http://fsf.org/}
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
|
||||
@@ -13,24 +13,40 @@ clean:
|
||||
install:
|
||||
install -d $(DESTDIR)$(SUBDIR)
|
||||
install -m 644 *.py $(DESTDIR)$(SUBDIR)
|
||||
install -m 644 LICENSE.txt $(DESTDIR)$(SUBDIR)
|
||||
install -d $(DESTDIR)$(DATADIR)img
|
||||
install -m 644 img/*.png $(DESTDIR)$(DATADIR)img/
|
||||
install -m 644 img/*.svg $(DESTDIR)$(DATADIR)img/
|
||||
install -m 644 img/*.xml $(DESTDIR)$(DATADIR)img/
|
||||
install -d $(DESTDIR)$(DATADIR)img/darker
|
||||
install -m 644 img/darker/*.png $(DESTDIR)$(DATADIR)img/darker
|
||||
install -d $(DESTDIR)$(DATADIR)img/dark
|
||||
install -m 644 img/dark/*.png $(DESTDIR)$(DATADIR)img/dark
|
||||
install -d $(DESTDIR)$(DATADIR)img/light
|
||||
install -m 644 img/light/*.png $(DESTDIR)$(DATADIR)img/light
|
||||
install -d $(DESTDIR)$(DATADIR)img/lighter
|
||||
install -m 644 img/lighter/*.png $(DESTDIR)$(DATADIR)img/lighter
|
||||
install -d $(DESTDIR)$(DATADIR)img/standard
|
||||
install -m 644 img/standard/*.png $(DESTDIR)$(DATADIR)img/standard
|
||||
install -d $(DESTDIR)$(DATADIR)img/links
|
||||
install -m 644 img/links/*.png $(DESTDIR)$(DATADIR)img/links
|
||||
install -d $(DESTDIR)$(DATADIR)template
|
||||
install -m 644 template/*.xml $(DESTDIR)$(DATADIR)template
|
||||
install -d $(DESTDIR)$(DATADIR)ui
|
||||
install -m 644 ui/*.ui $(DESTDIR)$(DATADIR)ui/
|
||||
install -m 644 ui/*.xml $(DESTDIR)$(DATADIR)ui/
|
||||
install -m 644 coverart_browser.plugin $(DESTDIR)$(SUBDIR)
|
||||
install -m 644 ui/*.css $(DESTDIR)$(DATADIR)ui/
|
||||
install -d $(DESTDIR)$(DATADIR)coverflow
|
||||
install -d $(DESTDIR)$(DATADIR)coverflow/img
|
||||
install -m 644 coverflow/*.css $(DESTDIR)$(DATADIR)coverflow/
|
||||
install -m 644 coverflow/*.js $(DESTDIR)$(DATADIR)coverflow/
|
||||
install -m 644 coverflow/*.html $(DESTDIR)$(DATADIR)coverflow/
|
||||
install -m 644 coverflow/LICENSE $(DESTDIR)$(DATADIR)coverflow/
|
||||
install -m 644 coverflow/img/* $(DESTDIR)$(DATADIR)coverflow/img/
|
||||
install -m 644 coverart_browser.plugin* $(DESTDIR)$(SUBDIR)
|
||||
install -d $(DESTDIR)$(DATADIR)tmpl
|
||||
install -m 644 tmpl/* $(DESTDIR)$(DATADIR)tmpl/
|
||||
install -d $(DESTDIR)$(GLIB_DIR)
|
||||
install -m 644 schema/$(GLIB_SCHEME) $(DESTDIR)$(GLIB_DIR)
|
||||
cd po;./lang.sh $(DESTDIR)$(LOCALEDIR)
|
||||
cd po;./install_all.sh $(DESTDIR)$(LOCALEDIR)
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#coverart-browser v0.8
|
||||
================
|
||||
#coverart-browser v2.0
|
||||
|
||||
Browse your coverart albums in Rhythmbox v2.96 - Rhythmbox v2.98
|
||||
Browse your coverart albums in Rhythmbox v3 and later.
|
||||
|
||||

|
||||

|
||||
|
||||
-----------
|
||||
|
||||
@@ -15,68 +14,86 @@ Browse your coverart albums in Rhythmbox v2.96 - Rhythmbox v2.98
|
||||
|
||||
- fossfreedom <foss.freedom@gmail.com>, website - https://github.com/fossfreedom
|
||||
|
||||
[](https://flattr.com/thing/1238849/fossfreedom-at-Flattr "fossfreedom") [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBV682WJ3BDGL)
|
||||
[](http://flattr.com/thing/1811704/ "fossfreedom") [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBV682WJ3BDGL)
|
||||
-----------
|
||||
|
||||
##Summary: whats new in this release
|
||||
|
||||
- Export whole albums and embed coverart in the album tracks so that (where required) phones/tablets can display coverart correctly
|
||||
- Drag & Drop CoverArt icons onto playlists and sources (such as a phone) so that all tracks for an album are added
|
||||
|
||||
*note* - remember to use the *Portable Players - Ipod* and/or *Portable Players - MTP* plugin if your phone requires these to sync music
|
||||
|
||||
- separated coverart search into separate plugin (this is now a prerequisite) - https://github.com/fossfreedom/coverart-search-providers
|
||||
- New light & dark theme buttons to complement light & dark desktop themes
|
||||
- optional flat-button toolbar style
|
||||
- revised popup menu style genre & playlist windows when number of entries would exceed the desktop height
|
||||
- Use album and album-artist sort order tags for sorting if these values are utilised
|
||||
- Play from Cover-view and Track view instead of queuing & playing
|
||||
- Allow user-defined genre names to be created mapped against default system genre icons
|
||||
- Allow user-defined genre icons to be displayed. These can override system genre icons if required
|
||||
- Support for other plugins via right-click menu options in a similar manner as the Library Browser -
|
||||
|
||||
OpenContainingFolder, SendFirst, Send Track, LastFMExtension - Fingerprinter, FileOrganizer, lLyrics, WikipediaSearch
|
||||
|
||||
N.B. if NOT using my PPA then ensure you have the very latest version of the plugins installed.
|
||||
|
||||
- Compact & Full track view toggle option:
|
||||
1. Compact: fixed track view showing the key album track fields & ratings together with an enlarged album cover
|
||||
1. Full: Standard track view configurable via the preferences window
|
||||
- Smart continuous playlist: Play Similar Artists as recommended by EchoNest
|
||||
- Smart continuous playlist: Play Similar Genres as recommended by EchoNest
|
||||
- Smart continuous playlist: Play Similar Tracks as recommended by LastFM
|
||||
- New optional theme: darker toolbar icons by the graphics artist [jrbastien](https://github.com/jrbastien)
|
||||
- New subtle hover, play & queue icons by the graphics artist [jrbastien](https://github.com/jrbastien)
|
||||
- Introduce more modern look & feel through subtle animations
|
||||
- Views button ("…") now can navigate to Play Queue. Allows navigation of key views without the side-bar (F9) being visible
|
||||
- Artist & Album information pane with LastFM & EchoNest data
|
||||
- Artist & Album information is fully localised (in your native language) if LastFM returns information in your locale
|
||||
- Information pane can be made visible or hidden by dragging the pane-handle
|
||||
- Track Artist Filter and Artist & Album Information panes individually displayed per view
|
||||
- Support Jump To Playing CTRL+J to scroll to the playing album
|
||||
- Follow playing song option automatically selects playing album
|
||||
- Custom Genres are now saved in an alternative folder location to survive re-installation of the plugin
|
||||
- Search Filter by Composer
|
||||
- Introduce type-ahead Search filtering to improve searching usability
|
||||
- Single click to append album to list of playing albums
|
||||
- Right-click to append album to list of playing albums
|
||||
- View and modify the list of album tracks being played
|
||||
- Optional support for [SmallWindow](https://github.com/fossfreedom/smallwindow) plugin - allows Rhythmbox to be toggled between its standard application window and its smaller counterpart
|
||||
- Translated into 24 languages and locales
|
||||
- for developers - doxygen documentation: http://fossfreedom.github.io/coverart-browser/classes.html
|
||||
|
||||
*How it works:*
|
||||
|
||||
- Click the new CoverArt source button (left hand side of screen)
|
||||
- Click the new CoverArt Browser source button (left hand side of screen)
|
||||
- Albums are displayed as clickable buttons containing their album cover
|
||||
- Right click menu option to play, queue & search for coverart for an album.
|
||||
- Download Album & artist artwork via the properties toolbar button
|
||||
|
||||
- https://github.com/fossfreedom/coverart-browser/wiki/How-the-plugin-works
|
||||
- https://github.com/fossfreedom/coverart-browser/wiki/how-to-for-version-2.0
|
||||
- https://github.com/fossfreedom/coverart-browser/wiki/Screenshots
|
||||
|
||||
*How to install:*
|
||||
*How to install - Rhythmbox 3.0 and later:*
|
||||
|
||||
for debian & debian-based distros such as Ubuntu & Mint
|
||||
N.B. for earlier Rhythmbox versions use version 1.x
|
||||
|
||||
sudo apt-get install git gettext python-mako python-lxml
|
||||
Prerequisite is to use a distribution supporting GTK 3.10 or later - for example, Ubuntu 14.04, Arch or Fedora 20
|
||||
IMPORTANT: For GTK 3.14 users (Fedora 21/Arch etc) please look at https://github.com/fossfreedom/coverart-browser/issues/338 first
|
||||
|
||||
for debian & debian-based distros such as Ubuntu & Mint:
|
||||
|
||||
sudo apt-get install git gettext python3-mako python3-lxml python3-gi-cairo python3-cairo gstreamer1.0-plugins-ugly gstreamer1.0-plugins-good gstreamer1.0-plugins-bad rhythmbox-plugins
|
||||
|
||||
for fedora and similar:
|
||||
|
||||
yum install git gettext python-mako python-lxml
|
||||
sudo yum install git gettext python3-mako python3-lxml python3-cairo
|
||||
|
||||
Then install the plugin:
|
||||
NOTE: it is assumed that you have separately installed the patent encumbered codecs found in the good/bad & ugly packages
|
||||
To install the plugin:
|
||||
|
||||
<pre>
|
||||
rm -rf ~/.local/share/rhythmbox/plugins/coverart_browser
|
||||
git clone https://github.com/fossfreedom/coverart-browser.git
|
||||
cd coverart-browser
|
||||
sh ./install.sh
|
||||
./install.sh
|
||||
</pre>
|
||||
|
||||
To uninstall the plugin:
|
||||
|
||||
<pre>
|
||||
cd coverart-browser
|
||||
./install.sh --uninstall
|
||||
</pre>
|
||||
|
||||
Note 1 - the CoverArt Browser plugin also requires installing the following plugin:
|
||||
|
||||
- https://github.com/fossfreedom/coverart-search-providers
|
||||
|
||||
Note 2 - Due to upstream changes this plugin does NOT work with rhythmbox 2.99. Patches are most welcome to support this version of rhythmbox.
|
||||
|
||||
*For Ubuntu 12.04 & 12.10:*
|
||||
*For Ubuntu 14.04 and later:*
|
||||
|
||||
This is now available in my rhythmbox PPA - installation instructions in this AskUbuntu Q&A:
|
||||
V2.0 is now available in my rhythmbox PPA - installation instructions in this AskUbuntu Q&A:
|
||||
|
||||
http://askubuntu.com/questions/147942/how-do-i-install-third-party-rhythmbox-plugins
|
||||
|
||||
@@ -99,12 +116,15 @@ Credits:
|
||||
- thanks to Luqman Aden <laden@uwaterloo.ca> for the coverart-search plugin which our cover-search pane is based upon
|
||||
- thanks to Canonical for the Star widget which the ratings capabilities use
|
||||
- our Translators: Launchpad Translation team - individual credits for each locale is shown in the plugin preferences dialog
|
||||
- Button Icons - jrbastien for the three toolbar icon-sets (standard, light & dark)
|
||||
- Button Icons - [jrbastien](https://github.com/jrbastien) for the five toolbar icon-sets
|
||||
- Flow view is based upon [Contentflow](http://jacksasylum.eu/ContentFlow)
|
||||
- Chief Tester and all-round good egg - jrbastien!
|
||||
|
||||
Licenses:
|
||||
|
||||
This plugin code is released under the GPL3+ license.
|
||||
|
||||
Contentflow source is released under the MIT license
|
||||
|
||||
All translations are released under the BSD license
|
||||
|
||||
|
||||
@@ -5,19 +5,26 @@
|
||||
# Section 1: Developers Only
|
||||
#+++++++++++++++++++++++++++
|
||||
#for each ui file run the following to create translation .h files
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_listwindow.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_artistview.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_artist_pop_rb3.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_browser_pop_rb3.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_browser_prefs.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_browser.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_entryview.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_sidebar.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_topbar.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_entryview_compact_pop_rb3.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_entryview_full_pop_rb3.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_exportembed.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_iconview.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_leftsidebar.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_listwindow.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_play_pop_rb3.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_rightsidebar.ui
|
||||
intltool-extract --local --type=gettext/glade ui/coverart_topbar.ui
|
||||
intltool-extract --local --type=gettext/xml img/popups.xml.in
|
||||
|
||||
#create a new template file called po/package.pot by running below
|
||||
|
||||
#create a template file for the mako templates
|
||||
pybabel extract -F babel.cfg -o po/coverartbrowser.pot .
|
||||
pybabel extract -F babel.cfg -o po/coverartbrowser.pot -c "TRANSLATORS:" .
|
||||
|
||||
# po/files_to_be_translated are all the .h files generated by intltool
|
||||
xgettext -c -a -j -f po/files_to_be_translated -o po/coverartbrowser.pot
|
||||
|
||||
@@ -1,38 +1,54 @@
|
||||
[Plugin]
|
||||
Loader=python
|
||||
Loader=python3
|
||||
Module=coverart_browser
|
||||
IAge=2
|
||||
Depends=rb;coverart_search_providers
|
||||
Name=CoverArt Browser
|
||||
Name[ast]=Navegador de portaes
|
||||
Name[az]=CoverArt gəzgini
|
||||
Name[bg]=CoverArt Browser
|
||||
Name[ca]=Navegador de Portades
|
||||
Name[cs]=Prohlížeč CoverArt
|
||||
Name[de]=CoverArt Browser
|
||||
Name[en_GB]=CoverArt Browser
|
||||
Name[en_US]=CoverArt Browser
|
||||
Name[es]=Navegador de carátulas
|
||||
Name[fi]=Kansikuvaselain
|
||||
Name[fr]=Navigateur de jaquettes
|
||||
Name[fr_CA]=Navigateur de pochettes
|
||||
Name[gl]=Navegador de cubertas
|
||||
Name[hr]=CoverArt Preglednik
|
||||
Name[it]=Gestore di CoverArt
|
||||
Name[ko]=앨범 표지 찾아보기
|
||||
Name[ms]=Pelayar CoverArt
|
||||
Name[pl]=Przeglądarka okładek
|
||||
Name[pt]=Arte das Capas
|
||||
Name[pt_BR]=Arte das Capas
|
||||
Name[ro]=Navigator CoverArt
|
||||
Name[zh_CN]=封面浏览器
|
||||
Description=Browse and play your albums through their covers
|
||||
Description[ast]=Navegar y reproducir los álbumes per aciu de les portaes
|
||||
Description[az]=Üz şəklinə görə albomlara bax və oxud
|
||||
Description[bg]=Търсете и слушайте албумите си посредством обложките им
|
||||
Description[ca]=Navega i reprodueix els àlbums mitjançant les seues portades
|
||||
Description[en_GB]=Browse and play your albums through their covers
|
||||
Description[en_US]=Browse and play your albums through their covers
|
||||
Description[es]=Navegue y reproduzca sus álbumes mediante sus carátulas
|
||||
Description[fi]=Selaa ja toista levyjäsi kansikuvien kautta
|
||||
Description[fr]=Parcourir les jaquettes de vos albums et les jouer
|
||||
Description[fr_CA]=Parcourir les pochettes de vos albums et les jouer
|
||||
Description[gl]=Examinar e reproducir os seus álbums a través das súas cubertas
|
||||
Description[hr]=Pregledavajte i slušajte albume preko omota
|
||||
Description[it]=Sfoglia e riproduce gli album per copertina
|
||||
Description[ko]=앨범을 표지로 찾아보고 연주합니다.
|
||||
Description[ms]=Layar dan mainkan album anda menerusi kulit album mereka
|
||||
Description[pl]=Przeglądaj i odtwarzaj Twoje albumy według ich okładek
|
||||
Description[pt]=Navegue e toque seus álbums através de suas capas
|
||||
Description[pt_BR]=Navegue e toque seus álbums através de suas capas
|
||||
Description[ro]=Parcurge și redă albumele prin intermediul coperților lor
|
||||
Description[zh_CN]=浏览封面并播放专辑
|
||||
Authors=fossfreedom <foss.freedom@gmail.com>, Agustín Carrasco <asermax@gmail.com>
|
||||
Copyright=© 2012 fossfreedom, Agustín Carrasco © 2007 Alexandre Rosenfeld
|
||||
Website=http://github.com/fossfreedom/coverart-browser
|
||||
Help=https://github.com/fossfreedom/coverart-browser/blob/release-0.8/README.md
|
||||
Version=0.8
|
||||
Help=https://github.com/fossfreedom/coverart-browser/blob/release-2.0/README.md
|
||||
Version=2.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[Plugin]
|
||||
Loader=python
|
||||
Loader=python3
|
||||
Module=coverart_browser
|
||||
IAge=2
|
||||
Depends=rb;coverart_search_providers
|
||||
@@ -8,5 +8,5 @@ _Description=Browse and play your albums through their covers
|
||||
Authors=fossfreedom <foss.freedom@gmail.com>, Agustín Carrasco <asermax@gmail.com>
|
||||
Copyright=© 2012 fossfreedom, Agustín Carrasco © 2007 Alexandre Rosenfeld
|
||||
Website=http://github.com/fossfreedom/coverart-browser
|
||||
Help=https://github.com/fossfreedom/coverart-browser/blob/release-0.8/README.md
|
||||
Version=0.8
|
||||
Help=https://github.com/fossfreedom/coverart-browser/blob/release-2.0/README.md
|
||||
Version=2.0
|
||||
|
||||
@@ -18,33 +18,34 @@
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# define plugin
|
||||
import rb
|
||||
import locale
|
||||
import gettext
|
||||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import RB
|
||||
from gi.repository import GdkPixbuf
|
||||
from gi.repository import Peas
|
||||
from gi.repository import Gio
|
||||
from gi.repository import GLib
|
||||
|
||||
from coverart_browser_prefs import Preferences
|
||||
import rb
|
||||
from coverart_browser_prefs import GSetting
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
from coverart_browser_prefs import Preferences
|
||||
from coverart_browser_source import CoverArtBrowserSource
|
||||
from coverart_utils import Theme
|
||||
from coverart_listview import ListView
|
||||
from coverart_queueview import QueueView
|
||||
from coverart_playsourceview import PlaySourceView
|
||||
from coverart_toolbar import TopToolbar
|
||||
|
||||
class CoverArtBrowserEntryType(RB.RhythmDBEntryType):
|
||||
'''
|
||||
Entry type for our source.
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
'''
|
||||
Initializes the entry type.
|
||||
'''
|
||||
RB.RhythmDBEntryType.__init__(self, name='CoverArtBrowserEntryType')
|
||||
|
||||
|
||||
class CoverArtBrowserPlugin(GObject.Object, Peas.Activatable):
|
||||
'''
|
||||
Main class of the plugin. Manages the activation and deactivation of the
|
||||
@@ -58,7 +59,6 @@ class CoverArtBrowserPlugin(GObject.Object, Peas.Activatable):
|
||||
Initialises the plugin object.
|
||||
'''
|
||||
GObject.Object.__init__(self)
|
||||
GObject.threads_init()
|
||||
|
||||
def do_activate(self):
|
||||
'''
|
||||
@@ -67,61 +67,58 @@ class CoverArtBrowserPlugin(GObject.Object, Peas.Activatable):
|
||||
preferences.
|
||||
'''
|
||||
|
||||
# define .plugin text strings used for translation
|
||||
plugin = _('CoverArt Browser')
|
||||
desc = _('Browse and play your albums through their covers')
|
||||
|
||||
print "CoverArtBrowser DEBUG - do_activate"
|
||||
print("CoverArtBrowser DEBUG - do_activate")
|
||||
self.shell = self.object
|
||||
self.db = self.shell.props.db
|
||||
|
||||
try:
|
||||
entry_type = CoverArtBrowserEntryType()
|
||||
self.db.register_entry_type(entry_type)
|
||||
except NotImplementedError:
|
||||
entry_type = self.db.entry_register_type(
|
||||
'CoverArtBrowserEntryType')
|
||||
self.entry_type = CoverArtBrowserEntryType()
|
||||
self.db.register_entry_type(self.entry_type)
|
||||
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
entry_type.category = RB.RhythmDBEntryCategory.NORMAL
|
||||
self.entry_type.category = RB.RhythmDBEntryCategory.NORMAL
|
||||
|
||||
group = RB.DisplayPageGroup.get_by_id('library')
|
||||
|
||||
# load plugin icon
|
||||
theme = Gtk.IconTheme.get_default()
|
||||
rb.append_plugin_source_path(theme, '/icons')
|
||||
|
||||
what, width, height = Gtk.icon_size_lookup(Gtk.IconSize.LARGE_TOOLBAR)
|
||||
pxbf = GdkPixbuf.Pixbuf.new_from_file_at_size(
|
||||
rb.find_plugin_file(self, 'img/' + Theme(self).current\
|
||||
+ '/covermgr.png'), width, height)
|
||||
iconfile = Gio.File.new_for_path(
|
||||
rb.find_plugin_file(self, 'img/covermgr_rb3.png'))
|
||||
|
||||
group = RB.DisplayPageGroup.get_by_id('library')
|
||||
|
||||
self.source = CoverArtBrowserSource(shell=self.shell,
|
||||
name=_("CoverArt"), entry_type=entry_type,
|
||||
plugin=self, pixbuf=pxbf,
|
||||
self.source = CoverArtBrowserSource(
|
||||
shell=self.shell,
|
||||
name=_("CoverArt"),
|
||||
entry_type=self.entry_type,
|
||||
plugin=self,
|
||||
icon=Gio.FileIcon.new(iconfile),
|
||||
query_model=self.shell.props.library_source.props.base_query_model)
|
||||
|
||||
self.shell.register_entry_type_for_source(self.source, entry_type)
|
||||
self.shell.register_entry_type_for_source(self.source, self.entry_type)
|
||||
self.shell.append_display_page(self.source, group)
|
||||
|
||||
self.source.props.query_model.connect('complete', self.load_complete)
|
||||
self._externalmenu = ExternalPluginMenu(self)
|
||||
|
||||
print "CoverArtBrowser DEBUG - end do_activate"
|
||||
cl.switch_locale(cl.Locale.RB)
|
||||
print("CoverArtBrowser DEBUG - end do_activate")
|
||||
|
||||
def do_deactivate(self):
|
||||
'''
|
||||
Called by Rhythmbox when the plugin is deactivated. It makes sure to
|
||||
free all the resources used by the plugin.
|
||||
'''
|
||||
print "CoverArtBrowser DEBUG - do_deactivate"
|
||||
print("CoverArtBrowser DEBUG - do_deactivate")
|
||||
self.source.delete_thyself()
|
||||
if self._externalmenu:
|
||||
self._externalmenu.cleanup()
|
||||
del self.shell
|
||||
del self.db
|
||||
del self.source
|
||||
|
||||
print "CoverArtBrowser DEBUG - end do_deactivate"
|
||||
print("CoverArtBrowser DEBUG - end do_deactivate")
|
||||
|
||||
def load_complete(self, *args, **kwargs):
|
||||
'''
|
||||
@@ -133,5 +130,156 @@ class CoverArtBrowserPlugin(GObject.Object, Peas.Activatable):
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
if setting[gs.PluginKey.AUTOSTART]:
|
||||
GObject.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.source)
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.source)
|
||||
|
||||
def _translation_helper(self):
|
||||
'''
|
||||
a method just to help out with translation strings
|
||||
it is not meant to be called by itself
|
||||
'''
|
||||
|
||||
# define .plugin text strings used for translation
|
||||
plugin = _('CoverArt Browser')
|
||||
desc = _('Browse and play your albums through their covers')
|
||||
|
||||
#. TRANSLATORS: This is the icon-grid view that the user sees
|
||||
tile = _('Tiles')
|
||||
|
||||
#. TRANSLATORS: This is the cover-flow view the user sees - they can swipe album covers from side-to-side
|
||||
artist = _('Flow')
|
||||
|
||||
#. TRANSLATORS: percentage size that the image will be expanded
|
||||
scale = _('Scale by %:')
|
||||
|
||||
# stop PyCharm removing the Preference import on optimisation
|
||||
pref = Preferences()
|
||||
|
||||
|
||||
class ExternalPluginMenu(GObject.Object):
|
||||
toolbar_pos = GObject.property(type=str, default=TopToolbar.name)
|
||||
|
||||
def __init__(self, plugin):
|
||||
super(ExternalPluginMenu, self).__init__()
|
||||
|
||||
self.plugin = plugin
|
||||
self.shell = plugin.shell
|
||||
self.source = plugin.source
|
||||
self.app_id = None
|
||||
from coverart_browser_source import Views
|
||||
|
||||
self._views = Views(self.shell)
|
||||
|
||||
self._connect_properties()
|
||||
self._connect_signals()
|
||||
|
||||
self._create_menu()
|
||||
|
||||
def _connect_signals(self):
|
||||
self.connect('notify::toolbar-pos', self._on_notify_toolbar_pos)
|
||||
self.shell.props.display_page_tree.connect(
|
||||
"selected", self.on_page_change
|
||||
)
|
||||
|
||||
def _connect_properties(self):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting.bind(gs.PluginKey.TOOLBAR_POS, self, 'toolbar_pos',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _on_notify_toolbar_pos(self, *args):
|
||||
if self.toolbar_pos == TopToolbar.name:
|
||||
self._create_menu()
|
||||
else:
|
||||
self.cleanup()
|
||||
|
||||
def cleanup(self):
|
||||
if self.app_id:
|
||||
app = Gio.Application.get_default()
|
||||
for location in self.locations:
|
||||
app.remove_plugin_menu_item(location, self.app_id)
|
||||
self.app_id = None
|
||||
|
||||
def _create_menu(self):
|
||||
app = Gio.Application.get_default()
|
||||
self.app_id = 'coverart-browser'
|
||||
|
||||
self.locations = ['library-toolbar', 'queue-toolbar', 'playsource-toolbar']
|
||||
action_name = 'coverart-browser-views'
|
||||
self.action = Gio.SimpleAction.new_stateful(
|
||||
action_name, GLib.VariantType.new('s'),
|
||||
self._views.get_action_name(ListView.name)
|
||||
)
|
||||
self.action.connect("activate", self.view_change_cb)
|
||||
app.add_action(self.action)
|
||||
|
||||
menu_item = Gio.MenuItem()
|
||||
section = Gio.Menu()
|
||||
menu = Gio.Menu()
|
||||
toolbar_item = Gio.MenuItem()
|
||||
|
||||
for view_name in self._views.get_view_names():
|
||||
menu_item.set_label(self._views.get_menu_name(view_name))
|
||||
menu_item.set_action_and_target_value(
|
||||
'app.' + action_name, self._views.get_action_name(view_name)
|
||||
)
|
||||
section.append_item(menu_item)
|
||||
|
||||
menu.append_section(None, section)
|
||||
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
toolbar_item.set_label('…')
|
||||
cl.switch_locale(cl.Locale.RB)
|
||||
|
||||
toolbar_item.set_submenu(menu)
|
||||
for location in self.locations:
|
||||
app.add_plugin_menu_item(location, self.app_id, toolbar_item)
|
||||
|
||||
|
||||
def on_page_change(self, display_page_tree, page):
|
||||
'''
|
||||
Called when the display page changes. Grabs query models and sets the
|
||||
active view.
|
||||
'''
|
||||
|
||||
if page == self.shell.props.library_source:
|
||||
self.action.set_state(self._views.get_action_name(ListView.name))
|
||||
elif page == self.shell.props.queue_source:
|
||||
self.action.set_state(self._views.get_action_name(QueueView.name))
|
||||
#elif page == self.source.playlist_source:
|
||||
# self.action.set_state(self._views.get_action_name(PlaySourceView.name))
|
||||
|
||||
|
||||
def view_change_cb(self, action, current):
|
||||
'''
|
||||
Called when the view state on a page is changed. Sets the new
|
||||
state.
|
||||
'''
|
||||
action.set_state(current)
|
||||
view_name = self._views.get_view_name_for_action(current)
|
||||
if view_name != ListView.name and \
|
||||
view_name != QueueView.name:# and \
|
||||
#view_name != PlaySourceView.name:
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting[gs.PluginKey.VIEW_NAME] = view_name
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.source)
|
||||
elif view_name == ListView.name:
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.shell.props.library_source)
|
||||
elif view_name == QueueView.name:
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.shell.props.queue_source)
|
||||
#elif view_name == PlaySourceView.name:
|
||||
# if not hasattr(self.source, 'playlist_source'):
|
||||
# return
|
||||
|
||||
# print ("test selectable")
|
||||
# path = self.shell.props.display_page_tree.props.model
|
||||
# #self.source.activate()
|
||||
# overlay = self.source.get_children()[0]
|
||||
|
||||
# GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
# self.source.playlist_source)
|
||||
|
||||
@@ -16,19 +16,35 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
from gi.repository import Gio
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import PeasGtk
|
||||
from gi.repository import RB
|
||||
|
||||
import rb
|
||||
import locale
|
||||
import gettext
|
||||
import os
|
||||
import shutil
|
||||
import webbrowser
|
||||
|
||||
from gi.repository import Gio
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import PeasGtk
|
||||
from gi.repository import Peas
|
||||
from gi.repository import RB
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
import rb
|
||||
from stars import ReactiveStar
|
||||
from stars import StarSize
|
||||
import coverart_rb3compat as rb3compat
|
||||
|
||||
|
||||
def webkit_support():
|
||||
'''
|
||||
function that returns True/False if webkit technology is supported
|
||||
'''
|
||||
gs = GSetting()
|
||||
settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
return settings[gs.PluginKey.WEBKIT]
|
||||
|
||||
|
||||
class CoverLocale:
|
||||
'''
|
||||
@@ -117,8 +133,9 @@ class GSetting:
|
||||
|
||||
self.PluginKey = self._enum(
|
||||
CUSTOM_STATUSBAR='custom-statusbar',
|
||||
DISPLAY_BOTTOM='display-bottom',
|
||||
DISPLAY_TEXT='display-text',
|
||||
DISPLAY_TEXT_POS='display-text-pos',
|
||||
RANDOM='random-queue',
|
||||
DISPLAY_TEXT_LOADING='display-text-loading',
|
||||
DISPLAY_TEXT_ELLIPSIZE='display-text-ellipsize',
|
||||
DISPLAY_TEXT_ELLIPSIZE_LENGTH='display-text-ellipsize-length',
|
||||
@@ -129,12 +146,32 @@ class GSetting:
|
||||
PANED_POSITION='paned-position',
|
||||
SORT_BY='sort-by',
|
||||
SORT_ORDER='sort-order',
|
||||
SORT_BY_ARTIST='sort-by-artist',
|
||||
SORT_ORDER_ARTIST='sort-order-artist',
|
||||
RATING='rating-threshold',
|
||||
AUTOSTART='autostart',
|
||||
TOOLBAR_POS='toolbar-pos',
|
||||
BUTTON_RELIEF='button-relief',
|
||||
THEME='theme',
|
||||
NEW_GENRE_ICON='new-genre-icon')
|
||||
NEW_GENRE_ICON='new-genre-icon',
|
||||
ICON_PADDING='icon-padding',
|
||||
ICON_SPACING='icon-spacing',
|
||||
ICON_AUTOMATIC='icon-automatic',
|
||||
VIEW_NAME='view-name',
|
||||
FLOW_APPEARANCE='flow-appearance',
|
||||
FLOW_HIDE_CAPTION='flow-hide-caption',
|
||||
FLOW_SCALE='flow-scale',
|
||||
FLOW_BACKGROUND_COLOUR='flow-background-colour',
|
||||
FLOW_AUTOMATIC='flow-automatic',
|
||||
FLOW_WIDTH='flow-width',
|
||||
FLOW_MAX='flow-max-albums',
|
||||
WEBKIT='webkit-support',
|
||||
ARTIST_PANED_POSITION='artist-paned-pos',
|
||||
USE_FAVOURITES='use-favourites',
|
||||
ARTIST_INFO_PANED_POSITION='artist-info-paned-pos',
|
||||
LAST_GENRE_FOLDER='last-genre-folder',
|
||||
ENTRY_VIEW_MODE='entry-view-mode',
|
||||
FOLLOWING='following')
|
||||
|
||||
self.setting = {}
|
||||
|
||||
@@ -145,7 +182,7 @@ class GSetting:
|
||||
try:
|
||||
setting = self.setting[path]
|
||||
except:
|
||||
self.setting[path] = Gio.Settings(path)
|
||||
self.setting[path] = Gio.Settings.new(path)
|
||||
setting = self.setting[path]
|
||||
|
||||
return setting
|
||||
@@ -194,6 +231,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
'''
|
||||
__gtype_name__ = 'CoverArtBrowserPreferences'
|
||||
object = GObject.property(type=GObject.Object)
|
||||
|
||||
GENRE_POPUP = 1
|
||||
GENRE_LIST = 2
|
||||
|
||||
@@ -206,20 +244,68 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
gs = GSetting()
|
||||
self.settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
self._first_run = True
|
||||
self._cover_size = 0
|
||||
self._cover_size_delay = 0
|
||||
|
||||
def do_create_configure_widget(self):
|
||||
'''
|
||||
Creates the plugin's preferences dialog
|
||||
'''
|
||||
return self._create_display_contents(self)
|
||||
|
||||
def display_preferences_dialog(self, plugin):
|
||||
print ("DEBUG - display_preferences_dialog")
|
||||
if self._first_run:
|
||||
self._first_run = False
|
||||
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
self._dialog = Gtk.Dialog(modal=True, destroy_with_parent=True)
|
||||
self._dialog.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK)
|
||||
self._dialog.set_title(_('Browser Preferences'))
|
||||
content_area = self._dialog.get_content_area()
|
||||
content_area.pack_start(self._create_display_contents(plugin), True, True, 0)
|
||||
|
||||
helpbutton = self._dialog.add_button(Gtk.STOCK_HELP, Gtk.ResponseType.HELP)
|
||||
helpbutton.connect('clicked', self._display_help)
|
||||
|
||||
self._dialog.show_all()
|
||||
|
||||
print ("shown")
|
||||
|
||||
while True:
|
||||
response = self._dialog.run()
|
||||
|
||||
print ("and run")
|
||||
|
||||
if response != Gtk.ResponseType.HELP:
|
||||
break
|
||||
|
||||
self._dialog.hide()
|
||||
|
||||
print ("DEBUG - display_preferences_dialog end")
|
||||
|
||||
def _display_help(self, *args):
|
||||
peas = Peas.Engine.get_default()
|
||||
uri = peas.get_plugin_info('coverart_browser').get_help_uri()
|
||||
|
||||
webbrowser.open(uri)
|
||||
|
||||
def _create_display_contents(self, plugin):
|
||||
print ("DEBUG - create_display_contents")
|
||||
# create the ui
|
||||
self._first_run = True
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
builder = Gtk.Builder()
|
||||
builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN)
|
||||
builder.add_from_file(rb.find_plugin_file(self,
|
||||
'ui/coverart_browser_prefs.ui'))
|
||||
builder.add_from_file(rb.find_plugin_file(plugin,
|
||||
'ui/coverart_browser_prefs.ui'))
|
||||
self.launchpad_button = builder.get_object('show_launchpad')
|
||||
self.launchpad_label = builder.get_object('launchpad_label')
|
||||
|
||||
|
||||
builder.connect_signals(self)
|
||||
|
||||
#. TRANSLATORS: Do not translate this string.
|
||||
@@ -229,54 +315,68 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
self.launchpad_label.set_text(translators)
|
||||
else:
|
||||
self.launchpad_button.set_visible(False)
|
||||
|
||||
|
||||
gs = GSetting()
|
||||
# bind the toggles to the settings
|
||||
toggle_statusbar = builder.get_object('custom_statusbar_checkbox')
|
||||
self.settings.bind(gs.PluginKey.CUSTOM_STATUSBAR,
|
||||
toggle_statusbar, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
toggle_bottom = builder.get_object('display_bottom_checkbox')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_BOTTOM, toggle_bottom,
|
||||
'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
toggle_statusbar, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
toggle_text = builder.get_object('display_text_checkbox')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT, toggle_text, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
|
||||
box_text = builder.get_object('display_text_box')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT, box_text, 'sensitive',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
self.display_text_pos = self.settings[gs.PluginKey.DISPLAY_TEXT_POS]
|
||||
self.display_text_under_radiobutton = builder.get_object('display_text_under_radiobutton')
|
||||
self.display_text_within_radiobutton = builder.get_object('display_text_within_radiobutton')
|
||||
|
||||
if self.display_text_pos:
|
||||
self.display_text_under_radiobutton.set_active(True)
|
||||
else:
|
||||
self.display_text_within_radiobutton.set_active(True)
|
||||
|
||||
random_scale = builder.get_object('random_adjustment')
|
||||
self.settings.bind(gs.PluginKey.RANDOM, random_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
toggle_text_ellipsize = builder.get_object(
|
||||
'display_text_ellipsize_checkbox')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE,
|
||||
toggle_text_ellipsize, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
toggle_text_ellipsize, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
box_text_ellipsize_length = builder.get_object(
|
||||
'display_text_ellipsize_length_box')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE,
|
||||
box_text_ellipsize_length, 'sensitive', Gio.SettingsBindFlags.GET)
|
||||
box_text_ellipsize_length, 'sensitive', Gio.SettingsBindFlags.GET)
|
||||
|
||||
spinner_text_ellipsize_length = builder.get_object(
|
||||
'display_text_ellipsize_length_spin')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE_LENGTH,
|
||||
spinner_text_ellipsize_length, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
spinner_text_ellipsize_length, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
spinner_font_size = builder.get_object(
|
||||
'display_font_spin')
|
||||
self.settings.bind(gs.PluginKey.DISPLAY_FONT_SIZE,
|
||||
spinner_font_size, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
spinner_font_size, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
cover_size_scale = builder.get_object('cover_size_adjustment')
|
||||
self.settings.bind(gs.PluginKey.COVER_SIZE, cover_size_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
#self.settings.bind(gs.PluginKey.COVER_SIZE, cover_size_scale, 'value',
|
||||
# Gio.SettingsBindFlags.DEFAULT)
|
||||
self._cover_size = self.settings[gs.PluginKey.COVER_SIZE]
|
||||
cover_size_scale.set_value(self._cover_size)
|
||||
cover_size_scale.connect('value-changed', self.on_cover_size_scale_changed)
|
||||
|
||||
add_shadow = builder.get_object('add_shadow_checkbox')
|
||||
self.settings.bind(gs.PluginKey.ADD_SHADOW, add_shadow, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
rated_box = builder.get_object('rated_box')
|
||||
self.stars = ReactiveStar(size=StarSize.BIG)
|
||||
@@ -291,45 +391,55 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
|
||||
autostart = builder.get_object('autostart_checkbox')
|
||||
self.settings.bind(gs.PluginKey.AUTOSTART,
|
||||
autostart, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
autostart, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
toolbar_pos_combo = builder.get_object('show_in_combobox')
|
||||
renderer = Gtk.CellRendererText()
|
||||
toolbar_pos_combo.pack_start(renderer, True)
|
||||
toolbar_pos_combo.add_attribute(renderer, 'text', 1)
|
||||
self.settings.bind(gs.PluginKey.TOOLBAR_POS, toolbar_pos_combo,
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
light_source_combo = builder.get_object('light_source_combobox')
|
||||
renderer = Gtk.CellRendererText()
|
||||
light_source_combo.pack_start(renderer, True)
|
||||
light_source_combo.add_attribute(renderer, 'text', 1)
|
||||
self.settings.bind(gs.PluginKey.SHADOW_IMAGE, light_source_combo,
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
combo_liststore = builder.get_object('combo_liststore')
|
||||
|
||||
from coverart_utils import Theme
|
||||
|
||||
|
||||
for theme in Theme(self).themes:
|
||||
combo_liststore.append([theme, theme])
|
||||
|
||||
|
||||
theme_combo = builder.get_object('theme_combobox')
|
||||
renderer = Gtk.CellRendererText()
|
||||
theme_combo.pack_start(renderer, True)
|
||||
theme_combo.add_attribute(renderer, 'text', 1)
|
||||
self.settings.bind(gs.PluginKey.THEME, theme_combo,
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
button_relief = builder.get_object('button_relief_checkbox')
|
||||
self.settings.bind(gs.PluginKey.BUTTON_RELIEF, button_relief, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
# create user data files
|
||||
popup = RB.find_user_data_file('plugins/coverart_browser/img/usericons/popups.xml')
|
||||
|
||||
cachedir = RB.user_cache_dir() + "/coverart_browser/usericons"
|
||||
if not os.path.exists(cachedir):
|
||||
os.makedirs(cachedir)
|
||||
|
||||
popup = cachedir + "/popups.xml"
|
||||
|
||||
temp = RB.find_user_data_file('plugins/coverart_browser/img/usericons/popups.xml')
|
||||
|
||||
# lets see if there is a legacy file - if necessary copy it to the cache dir
|
||||
if os.path.isfile(temp) and not os.path.isfile(popup):
|
||||
shutil.copyfile(temp, popup)
|
||||
|
||||
if not os.path.isfile(popup):
|
||||
template = rb.find_plugin_file(self, 'template/popups.xml')
|
||||
template = rb.find_plugin_file(plugin, 'template/popups.xml')
|
||||
folder = os.path.split(popup)[0]
|
||||
if not os.path.exists(folder):
|
||||
os.makedirs(folder)
|
||||
@@ -338,22 +448,21 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
# now prepare the genre tab
|
||||
from coverart_utils import GenreConfiguredSpriteSheet
|
||||
from coverart_utils import get_stock_size
|
||||
from coverart_utils import GenreType
|
||||
|
||||
self._sheet = GenreConfiguredSpriteSheet(self, "genre", get_stock_size())
|
||||
self._sheet = GenreConfiguredSpriteSheet(plugin, "genre", get_stock_size())
|
||||
|
||||
self.alt_liststore = builder.get_object('alt_liststore')
|
||||
self.alt_user_liststore = builder.get_object('alt_user_liststore')
|
||||
self._iters = {}
|
||||
for key in self._sheet.keys():
|
||||
for key in list(self._sheet.keys()):
|
||||
store_iter = self.alt_liststore.append([key, self._sheet[key]])
|
||||
self._iters[(key,self.GENRE_POPUP)] = store_iter
|
||||
self._iters[(key, self.GENRE_POPUP)] = store_iter
|
||||
|
||||
for key, value in self._sheet.genre_alternate.iteritems():
|
||||
for key, value in self._sheet.genre_alternate.items():
|
||||
if key.genre_type == GenreConfiguredSpriteSheet.GENRE_USER:
|
||||
store_iter = self.alt_user_liststore.append([key.name,
|
||||
self._sheet[self._sheet.genre_alternate[key]],
|
||||
self._sheet.genre_alternate[key]])
|
||||
self._sheet[self._sheet.genre_alternate[key]],
|
||||
self._sheet.genre_alternate[key]])
|
||||
self._iters[(key.name, self.GENRE_LIST)] = store_iter
|
||||
|
||||
self.amend_mode = False
|
||||
@@ -363,12 +472,127 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
self.genre_view = builder.get_object('genre_view')
|
||||
self.save_button = builder.get_object('save_button')
|
||||
self.filechooserdialog = builder.get_object('filechooserdialog')
|
||||
|
||||
last_genre_folder = self.settings[gs.PluginKey.LAST_GENRE_FOLDER]
|
||||
if last_genre_folder != "":
|
||||
self.filechooserdialog.set_current_folder(last_genre_folder)
|
||||
|
||||
padding_scale = builder.get_object('padding_adjustment')
|
||||
self.settings.bind(gs.PluginKey.ICON_PADDING, padding_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
spacing_scale = builder.get_object('spacing_adjustment')
|
||||
self.settings.bind(gs.PluginKey.ICON_SPACING, spacing_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
icon_automatic = builder.get_object('icon_automatic_checkbox')
|
||||
self.settings.bind(gs.PluginKey.ICON_AUTOMATIC,
|
||||
icon_automatic, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
#flow tab
|
||||
flow_combo = builder.get_object('flow_combobox')
|
||||
renderer = Gtk.CellRendererText()
|
||||
flow_combo.pack_start(renderer, True)
|
||||
flow_combo.add_attribute(renderer, 'text', 1)
|
||||
self.settings.bind(gs.PluginKey.FLOW_APPEARANCE, flow_combo,
|
||||
'active-id', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_hide = builder.get_object('hide_caption_checkbox')
|
||||
self.settings.bind(gs.PluginKey.FLOW_HIDE_CAPTION,
|
||||
flow_hide, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_scale = builder.get_object('cover_scale_adjustment')
|
||||
self.settings.bind(gs.PluginKey.FLOW_SCALE, flow_scale, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_width = builder.get_object('cover_width_adjustment')
|
||||
self.settings.bind(gs.PluginKey.FLOW_WIDTH, flow_width, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_max = builder.get_object('flow_max_adjustment')
|
||||
self.settings.bind(gs.PluginKey.FLOW_MAX, flow_max, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
flow_automatic = builder.get_object('automatic_checkbox')
|
||||
self.settings.bind(gs.PluginKey.FLOW_AUTOMATIC,
|
||||
flow_automatic, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
self.background_colour = self.settings[gs.PluginKey.FLOW_BACKGROUND_COLOUR]
|
||||
self.white_radiobutton = builder.get_object('white_radiobutton')
|
||||
self.black_radiobutton = builder.get_object('black_radiobutton')
|
||||
|
||||
if self.background_colour == 'W':
|
||||
self.white_radiobutton.set_active(True)
|
||||
else:
|
||||
self.black_radiobutton.set_active(True)
|
||||
|
||||
# return the dialog
|
||||
self._first_run = False
|
||||
print ("end create dialog contents")
|
||||
return builder.get_object('main_notebook')
|
||||
|
||||
def on_cover_size_scale_changed(self, scale):
|
||||
self._cover_size = scale.get_value()
|
||||
|
||||
def delay(*args):
|
||||
print ('delay')
|
||||
print (self._cover_size_delay)
|
||||
self._cover_size_delay = self._cover_size_delay + 1
|
||||
|
||||
if self._cover_size_delay >=8:
|
||||
gs = GSetting()
|
||||
self.settings[gs.PluginKey.COVER_SIZE] = self._cover_size
|
||||
self._cover_size_delay = 0
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
if self._cover_size_delay == 0:
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 100, delay, None)
|
||||
else:
|
||||
self._cover_size_delay = 1
|
||||
|
||||
def on_flow_combobox_changed(self, combobox):
|
||||
current_val = combobox.get_model()[combobox.get_active()][0]
|
||||
gs = GSetting()
|
||||
if self.settings[gs.PluginKey.FLOW_APPEARANCE] != current_val:
|
||||
if current_val == 'flow-vert':
|
||||
default_size = 150
|
||||
else:
|
||||
default_size = 600
|
||||
|
||||
self.settings[gs.PluginKey.FLOW_WIDTH] = default_size
|
||||
|
||||
if current_val == 'carousel':
|
||||
self.settings[gs.PluginKey.FLOW_HIDE_CAPTION] = True
|
||||
|
||||
def on_background_radio_toggled(self, button):
|
||||
if button.get_active():
|
||||
gs = GSetting()
|
||||
if button == self.white_radiobutton:
|
||||
self.settings[gs.PluginKey.FLOW_BACKGROUND_COLOUR] = 'W'
|
||||
else:
|
||||
self.settings[gs.PluginKey.FLOW_BACKGROUND_COLOUR] = 'B'
|
||||
|
||||
def on_display_text_pos_radio_toggled(self, button):
|
||||
if self._first_run:
|
||||
return
|
||||
|
||||
if button.get_active():
|
||||
gs = GSetting()
|
||||
if button == self.display_text_under_radiobutton:
|
||||
self.settings[gs.PluginKey.DISPLAY_TEXT_POS] = True
|
||||
else:
|
||||
self.settings[gs.PluginKey.DISPLAY_TEXT_POS] = False
|
||||
self.settings[gs.PluginKey.ADD_SHADOW] = False
|
||||
|
||||
def on_add_shadow_checkbox_toggled(self, button):
|
||||
if button.get_active():
|
||||
#gs = GSetting()
|
||||
#self.settings[gs.PluginKey.DISPLAY_TEXT_POS] = True
|
||||
self.display_text_under_radiobutton.set_active(True)
|
||||
|
||||
def rating_changed_callback(self, stars):
|
||||
print "rating_changed_callback"
|
||||
print("rating_changed_callback")
|
||||
gs = GSetting()
|
||||
self.settings[gs.PluginKey.RATING] = self.stars.get_rating()
|
||||
|
||||
@@ -376,32 +600,32 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
'''
|
||||
action when genre edit area is saved
|
||||
'''
|
||||
entry_value = self.genre_entry.get_text()
|
||||
entry_value = self.genre_entry.get_text()
|
||||
treeiter = self.genre_combobox.get_active_iter()
|
||||
icon_value = self.alt_liststore[treeiter][0]
|
||||
# model 0 is the icon name, model 1 is the pixbuf
|
||||
|
||||
|
||||
if self.amend_mode:
|
||||
key = self._sheet.amend_genre_info(self.current_genre,
|
||||
entry_value, icon_value)
|
||||
entry_value, icon_value)
|
||||
|
||||
self.alt_user_liststore[self._iters[(self.current_genre,
|
||||
self.GENRE_LIST)]][1]=self._sheet[self._sheet.genre_alternate[key]]
|
||||
self.GENRE_LIST)]][1] = self._sheet[self._sheet.genre_alternate[key]]
|
||||
self.alt_user_liststore[self._iters[(self.current_genre,
|
||||
self.GENRE_LIST)]][0]=key.name
|
||||
self.GENRE_LIST)]][0] = key.name
|
||||
store_iter = self._iters[(self.current_genre, self.GENRE_LIST)]
|
||||
del self._iters[(self.current_genre, self.GENRE_LIST)]
|
||||
self._iters[(key.name, self.GENRE_LIST)] = store_iter
|
||||
|
||||
|
||||
else:
|
||||
self.amend_mode = True
|
||||
key = self._sheet.amend_genre_info('',
|
||||
entry_value, icon_value)
|
||||
entry_value, icon_value)
|
||||
self.current_genre = key.name
|
||||
|
||||
store_iter = self.alt_user_liststore.append([key.name,
|
||||
self._sheet[self._sheet.genre_alternate[key]],
|
||||
self._sheet.genre_alternate[key]])
|
||||
self._sheet[self._sheet.genre_alternate[key]],
|
||||
self._sheet.genre_alternate[key]])
|
||||
self._iters[(key.name, self.GENRE_LIST)] = store_iter
|
||||
selection = self.genre_view.get_selection()
|
||||
selection.select_iter(store_iter)
|
||||
@@ -409,15 +633,23 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
self.save_button.set_sensitive(False)
|
||||
self._toggle_new_genre_state()
|
||||
|
||||
|
||||
|
||||
def on_genre_filechooserbutton_file_set(self, filechooser):
|
||||
'''
|
||||
action when genre new icon button is pressed
|
||||
'''
|
||||
key = self._sheet.add_genre_icon( self.filechooserdialog.get_filename() )
|
||||
key = self._sheet.add_genre_icon(self.filechooserdialog.get_filename())
|
||||
store_iter = self.alt_liststore.append([key.name, self._sheet[key.name]])
|
||||
self._iters[(key.name,self.GENRE_POPUP)] = store_iter
|
||||
|
||||
self._iters[(key.name, self.GENRE_POPUP)] = store_iter
|
||||
|
||||
gs = GSetting()
|
||||
last_genre_folder = self.filechooserdialog.get_current_folder()
|
||||
|
||||
print(last_genre_folder)
|
||||
print(self.filechooserdialog.get_filename())
|
||||
if last_genre_folder:
|
||||
self.settings[gs.PluginKey.LAST_GENRE_FOLDER] = last_genre_folder
|
||||
|
||||
def on_genre_view_selection_changed(self, view):
|
||||
'''
|
||||
action when user selects a row in the list of genres
|
||||
@@ -429,7 +661,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
if index != '':
|
||||
self.genre_combobox.set_active_iter(self._iters[(index, self.GENRE_POPUP)])
|
||||
self.amend_mode = True
|
||||
self.current_genre=unicode(model[genre_iter][0], 'utf-8')
|
||||
self.current_genre = rb3compat.unicodestr(model[genre_iter][0], 'utf-8')
|
||||
else:
|
||||
self.genre_entry.set_text('')
|
||||
self.genre_combobox.set_active_iter(None)
|
||||
@@ -443,7 +675,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
self.blank_iter = None
|
||||
except:
|
||||
self.blank_iter = None
|
||||
|
||||
|
||||
def on_add_button_clicked(self, button):
|
||||
'''
|
||||
action when a new genre is added to the table
|
||||
@@ -454,8 +686,8 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
self.blank_iter = self.alt_user_liststore.append(['', None, ''])
|
||||
selection = self.genre_view.get_selection()
|
||||
selection.select_iter(self.blank_iter)
|
||||
|
||||
|
||||
|
||||
|
||||
def on_delete_button_clicked(self, button):
|
||||
'''
|
||||
action when a genre is to be deleted
|
||||
@@ -464,7 +696,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
|
||||
model, genre_iter = selection.get_selected()
|
||||
if genre_iter:
|
||||
index = unicode(model[genre_iter][0],'utf-8')
|
||||
index = rb3compat.unicodestr(model[genre_iter][0], 'utf-8')
|
||||
model.remove(genre_iter)
|
||||
|
||||
if index:
|
||||
@@ -472,7 +704,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
self._sheet.delete_genre(index)
|
||||
|
||||
self._toggle_new_genre_state()
|
||||
|
||||
|
||||
def set_save_sensitivity(self, _):
|
||||
'''
|
||||
action to toggle the state of the save button depending
|
||||
@@ -481,7 +713,7 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
entry_value = self.genre_entry.get_text()
|
||||
treeiter = self.genre_combobox.get_active_iter()
|
||||
|
||||
entry_value = unicode(entry_value, 'utf-8')
|
||||
entry_value = rb3compat.unicodestr(entry_value, 'utf-8')
|
||||
enable = False
|
||||
try:
|
||||
test = self._iters[(entry_value, self.GENRE_LIST)]
|
||||
@@ -512,8 +744,9 @@ class Preferences(GObject.Object, PeasGtk.Configurable):
|
||||
else:
|
||||
test = True
|
||||
|
||||
self.settings[gs.PluginKey.NEW_GENRE_ICON]=test
|
||||
|
||||
self.settings[gs.PluginKey.NEW_GENRE_ICON] = test
|
||||
|
||||
def on_show_launchpad_toggled(self, button):
|
||||
self.launchpad_label.set_visible(button.get_active())
|
||||
|
||||
|
||||
|
||||
@@ -16,11 +16,17 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
from gi.repository import GdkPixbuf
|
||||
|
||||
from datetime import date
|
||||
from collections import OrderedDict
|
||||
from collections import namedtuple
|
||||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import RB
|
||||
from gi.repository import Gio
|
||||
from gi.repository import GLib
|
||||
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
from coverart_browser_prefs import GSetting
|
||||
from coverart_utils import create_pixbuf_from_file_at_size
|
||||
@@ -29,17 +35,22 @@ from coverart_utils import ConfiguredSpriteSheet
|
||||
from coverart_utils import get_stock_size
|
||||
from coverart_utils import CaseInsensitiveDict
|
||||
from coverart_utils import Theme
|
||||
from datetime import date
|
||||
from collections import OrderedDict
|
||||
import rb
|
||||
|
||||
|
||||
class OptionsController(GObject.Object):
|
||||
MenuNodeT = namedtuple('MenuNode', 'label menutype typevalue')
|
||||
|
||||
|
||||
def MenuNode(label, menutype=None, typevalue=None):
|
||||
return MenuNodeT(label, menutype, typevalue)
|
||||
|
||||
|
||||
class OptionsController(GObject.Object):
|
||||
# properties
|
||||
options = GObject.property(type=object, default=None)
|
||||
current_key = GObject.property(type=str, default=None)
|
||||
update_image = GObject.property(type=bool, default=False)
|
||||
enabled = GObject.property(type=bool, default=True)
|
||||
|
||||
def __init__(self):
|
||||
super(OptionsController, self).__init__()
|
||||
@@ -76,10 +87,10 @@ class OptionsController(GObject.Object):
|
||||
'''
|
||||
if sheet:
|
||||
del sheet
|
||||
|
||||
|
||||
return ConfiguredSpriteSheet(plugin, typestr, get_stock_size())
|
||||
|
||||
def create_button_image( self, plugin, image, icon_name):
|
||||
def create_button_image(self, plugin, image, icon_name):
|
||||
'''
|
||||
helper function to create a button image
|
||||
'''
|
||||
@@ -87,13 +98,13 @@ class OptionsController(GObject.Object):
|
||||
del image
|
||||
|
||||
path = 'img/' + Theme(self.plugin).current + '/'
|
||||
|
||||
|
||||
return create_pixbuf_from_file_at_size(
|
||||
rb.find_plugin_file(self.plugin, path + icon_name),
|
||||
*get_stock_size())
|
||||
|
||||
class PlaylistPopupController(OptionsController):
|
||||
|
||||
class PlaylistPopupController(OptionsController):
|
||||
def __init__(self, plugin, album_model):
|
||||
super(PlaylistPopupController, self).__init__()
|
||||
|
||||
@@ -113,10 +124,9 @@ class PlaylistPopupController(OptionsController):
|
||||
|
||||
self._spritesheet = None
|
||||
self._update_options(shell)
|
||||
|
||||
# get the playlist manager and it's model
|
||||
playlist_manager = shell.props.playlist_manager
|
||||
playlist_model = playlist_manager.props.display_page_model
|
||||
|
||||
# get the playlist model so we can monitor changes
|
||||
playlist_model = shell.props.display_page_model
|
||||
|
||||
# connect signals to update playlists
|
||||
playlist_model.connect('row-inserted', self._update_options, shell)
|
||||
@@ -124,8 +134,8 @@ class PlaylistPopupController(OptionsController):
|
||||
playlist_model.connect('row-changed', self._update_options, shell)
|
||||
|
||||
def update_images(self, *args):
|
||||
self._spritesheet = self.create_spritesheet( self.plugin,
|
||||
self._spritesheet, 'playlist')
|
||||
self._spritesheet = self.create_spritesheet(self.plugin,
|
||||
self._spritesheet, 'playlist')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
@@ -133,10 +143,10 @@ class PlaylistPopupController(OptionsController):
|
||||
def _update_options(self, *args):
|
||||
shell = args[-1]
|
||||
self.update_images(False)
|
||||
|
||||
|
||||
playlist_manager = shell.props.playlist_manager
|
||||
still_exists = self.current_key == self._library_name or\
|
||||
self.current_key == self._queue_name
|
||||
still_exists = self.current_key == self._library_name or \
|
||||
self.current_key == self._queue_name
|
||||
|
||||
# retrieve the options
|
||||
values = OrderedDict()
|
||||
@@ -156,9 +166,9 @@ class PlaylistPopupController(OptionsController):
|
||||
still_exists = still_exists or name == self.current_key
|
||||
|
||||
self.values = values
|
||||
self.options = values.keys()
|
||||
self.options = list(values.keys())
|
||||
|
||||
self.current_key = self.current_key if still_exists else\
|
||||
self.current_key = self.current_key if still_exists else \
|
||||
self._library_name
|
||||
|
||||
def do_action(self):
|
||||
@@ -168,7 +178,7 @@ class PlaylistPopupController(OptionsController):
|
||||
self._album_model.remove_filter('model')
|
||||
else:
|
||||
self._album_model.replace_filter('model',
|
||||
playlist.get_query_model())
|
||||
playlist.get_query_model())
|
||||
|
||||
def get_current_image(self):
|
||||
playlist = self.values[self.current_key]
|
||||
@@ -202,7 +212,7 @@ class GenrePopupController(OptionsController):
|
||||
|
||||
# create a new property model for the genres
|
||||
genres_model = RB.RhythmDBPropertyModel.new(shell.props.db,
|
||||
RB.RhythmDBPropType.GENRE)
|
||||
RB.RhythmDBPropType.GENRE)
|
||||
|
||||
query = shell.props.library_source.props.base_query_model
|
||||
genres_model.props.query_model = query
|
||||
@@ -216,21 +226,21 @@ class GenrePopupController(OptionsController):
|
||||
|
||||
self._connect_properties()
|
||||
self._connect_signals(query, genres_model)
|
||||
|
||||
|
||||
# generate initial popup
|
||||
self._update_options(genres_model)
|
||||
|
||||
def update_images(self, *args):
|
||||
if self._spritesheet:
|
||||
del self._spritesheet
|
||||
|
||||
|
||||
self._spritesheet = GenreConfiguredSpriteSheet(self.plugin,
|
||||
'genre', get_stock_size())
|
||||
self._default_image = self.create_button_image( self.plugin,
|
||||
self._default_image, 'default_genre.png')
|
||||
self._unrecognised_image = self.create_button_image( self.plugin,
|
||||
self._unrecognised_image, 'unrecognised_genre.png')
|
||||
|
||||
'genre', get_stock_size())
|
||||
self._default_image = self.create_button_image(self.plugin,
|
||||
self._default_image, 'default_genre.png')
|
||||
self._unrecognised_image = self.create_button_image(self.plugin,
|
||||
self._unrecognised_image, 'unrecognised_genre.png')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
|
||||
@@ -246,13 +256,13 @@ class GenrePopupController(OptionsController):
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
setting.bind(gs.PluginKey.NEW_GENRE_ICON, self, 'new_genre_icon',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _update_options(self, *args):
|
||||
genres_model = args[-1]
|
||||
|
||||
self.update_images(False)
|
||||
|
||||
|
||||
still_exists = False
|
||||
|
||||
# retrieve the options
|
||||
@@ -260,6 +270,8 @@ class GenrePopupController(OptionsController):
|
||||
row_num = 0
|
||||
for row in genres_model:
|
||||
if row_num == 0:
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
genre = _('All Genres')
|
||||
row_num = row_num + 1
|
||||
else:
|
||||
@@ -271,7 +283,7 @@ class GenrePopupController(OptionsController):
|
||||
|
||||
self.options = options
|
||||
|
||||
self.current_key = self.current_key if still_exists else\
|
||||
self.current_key = self.current_key if still_exists else \
|
||||
self._initial_genre
|
||||
|
||||
def do_action(self):
|
||||
@@ -293,7 +305,7 @@ class GenrePopupController(OptionsController):
|
||||
image = self._find_alternates(test_genre)
|
||||
|
||||
if image == self._unrecognised_image and \
|
||||
test_genre in self._spritesheet:
|
||||
test_genre in self._spritesheet:
|
||||
image = self._spritesheet[test_genre]
|
||||
|
||||
return image
|
||||
@@ -313,15 +325,15 @@ class GenrePopupController(OptionsController):
|
||||
# in a mixture of cases, both unicode (normalized or not) and str
|
||||
# and as usual python cannot mix and match these types.
|
||||
|
||||
|
||||
|
||||
test_genre = RB.search_fold(test_genre)
|
||||
|
||||
|
||||
ret, sprite = self._match_genres(test_genre, self._spritesheet.GENRE_USER)
|
||||
if ret:
|
||||
return sprite
|
||||
|
||||
|
||||
for genre in sorted(self._spritesheet.locale_names,
|
||||
key=lambda b: (-len(b), b)):
|
||||
key=lambda b: (-len(b), b)):
|
||||
if RB.search_fold(genre) in test_genre:
|
||||
return self._spritesheet[self._spritesheet.locale_names[genre]]
|
||||
|
||||
@@ -333,23 +345,23 @@ class GenrePopupController(OptionsController):
|
||||
ret, sprite = self._match_genres(test_genre, self._spritesheet.GENRE_SYSTEM)
|
||||
if ret:
|
||||
return sprite
|
||||
|
||||
|
||||
# check if any of the default genres are a substring
|
||||
# of test_genre - check in reverse order so that we
|
||||
# test largest strings first (prevents spurious matches with
|
||||
# short strings)
|
||||
for genre in sorted(self._spritesheet.names,
|
||||
key=lambda b: (-len(b), b)):
|
||||
key=lambda b: (-len(b), b)):
|
||||
if RB.search_fold(genre) in test_genre:
|
||||
return self._spritesheet[genre]
|
||||
|
||||
|
||||
# if no matches then default to unrecognised image
|
||||
return self._unrecognised_image
|
||||
|
||||
def _match_genres(self, test_genre, genre_type):
|
||||
case_search = CaseInsensitiveDict(
|
||||
dict((k.name, v) for k, v in self._spritesheet.genre_alternate.iteritems()
|
||||
if k.genre_type==genre_type))
|
||||
dict((k.name, v) for k, v in self._spritesheet.genre_alternate.items()
|
||||
if k.genre_type == genre_type))
|
||||
|
||||
if test_genre in case_search:
|
||||
return (True, self._spritesheet[case_search[test_genre]])
|
||||
@@ -358,6 +370,8 @@ class GenrePopupController(OptionsController):
|
||||
|
||||
|
||||
def get_current_description(self):
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
if self.current_key == self._initial_genre:
|
||||
return _('All Genres')
|
||||
else:
|
||||
@@ -365,23 +379,22 @@ class GenrePopupController(OptionsController):
|
||||
|
||||
|
||||
class SortPopupController(OptionsController):
|
||||
|
||||
def __init__(self, plugin, album_model):
|
||||
def __init__(self, plugin, viewmgr):
|
||||
super(SortPopupController, self).__init__()
|
||||
|
||||
self._album_model = album_model
|
||||
self._viewmgr = viewmgr
|
||||
self.plugin = plugin
|
||||
# sorts dictionary
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
self.values = OrderedDict([(_('Sort by album name'), 'name'),
|
||||
(_('Sort by album artist'), 'artist'),
|
||||
(_('Sort by year'), 'year'),
|
||||
(_('Sort by rating'), 'rating')])
|
||||
(_('Sort by album artist'), 'artist'),
|
||||
(_('Sort by year'), 'year'),
|
||||
(_('Sort by rating'), 'rating')])
|
||||
|
||||
self.options = list(self.values.keys())
|
||||
|
||||
self.options = self.values.keys()
|
||||
|
||||
# get the current sort key and initialise the superclass
|
||||
gs = GSetting()
|
||||
source_settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
@@ -389,17 +402,17 @@ class SortPopupController(OptionsController):
|
||||
|
||||
self._spritesheet = None
|
||||
self.update_images(False)
|
||||
|
||||
self.current_key = self.values.keys()[
|
||||
self.values.values().index(value)]
|
||||
|
||||
self.current_key = list(self.values.keys())[
|
||||
list(self.values.values()).index(value)]
|
||||
|
||||
def update_images(self, *args):
|
||||
self._spritesheet = self.create_spritesheet( self.plugin,
|
||||
self._spritesheet, 'sort')
|
||||
|
||||
self._spritesheet = self.create_spritesheet(self.plugin,
|
||||
self._spritesheet, 'sort')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
|
||||
|
||||
def do_action(self):
|
||||
sort = self.values[self.current_key]
|
||||
|
||||
@@ -407,15 +420,152 @@ class SortPopupController(OptionsController):
|
||||
settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
settings[gs.PluginKey.SORT_BY] = sort
|
||||
|
||||
self._album_model.sort(sort)
|
||||
self._viewmgr.current_view.get_default_manager().emit('sort', "album")
|
||||
|
||||
def get_current_image(self):
|
||||
sort = self.values[self.current_key]
|
||||
return self._spritesheet[sort]
|
||||
|
||||
|
||||
class DecadePopupController(OptionsController):
|
||||
class ArtistSortPopupController(OptionsController):
|
||||
def __init__(self, plugin, viewmgr):
|
||||
super(ArtistSortPopupController, self).__init__()
|
||||
|
||||
self._viewmgr = viewmgr
|
||||
self.plugin = plugin
|
||||
# sorts dictionary
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
self.values = OrderedDict([(_('Sort by album name'), 'name_artist'),
|
||||
(_('Sort by year'), 'year_artist'),
|
||||
(_('Sort by rating'), 'rating_artist')])
|
||||
|
||||
self.options = list(self.values.keys())
|
||||
|
||||
# get the current sort key and initialise the superclass
|
||||
gs = GSetting()
|
||||
source_settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
value = source_settings[gs.PluginKey.SORT_BY_ARTIST]
|
||||
|
||||
if value not in list(self.values.values()):
|
||||
print("here")
|
||||
value = 'name_artist'
|
||||
source_settings[gs.PluginKey.SORT_BY_ARTIST] = value
|
||||
|
||||
self._spritesheet = None
|
||||
self.update_images(False)
|
||||
|
||||
self.current_key = list(self.values.keys())[
|
||||
list(self.values.values()).index(value)]
|
||||
print(self.current_key)
|
||||
|
||||
def update_images(self, *args):
|
||||
self._spritesheet = self.create_spritesheet(self.plugin,
|
||||
self._spritesheet, 'sort_artist')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
|
||||
def do_action(self):
|
||||
sort = self.values[self.current_key]
|
||||
|
||||
gs = GSetting()
|
||||
settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
settings[gs.PluginKey.SORT_BY_ARTIST] = sort
|
||||
|
||||
self._viewmgr.current_view.get_default_manager().emit('sort', "artist")
|
||||
|
||||
def get_current_image(self):
|
||||
sort = self.values[self.current_key]
|
||||
return self._spritesheet[sort]
|
||||
|
||||
|
||||
class PropertiesMenuController(OptionsController):
|
||||
favourites = GObject.property(type=bool, default=False)
|
||||
follow = GObject.property(type=bool, default=False)
|
||||
|
||||
def __init__(self, plugin, source):
|
||||
super(PropertiesMenuController, self).__init__()
|
||||
|
||||
self._source = source
|
||||
self.plugin = plugin
|
||||
self._connect_properties()
|
||||
# sorts dictionary
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
# options
|
||||
self.values = OrderedDict()
|
||||
self.values[MenuNode(_('Download all covers'))] = 'download'
|
||||
self.values[MenuNode(_('Play random album'))] = 'random'
|
||||
self.values[MenuNode(_('Follow playing song'), 'check',
|
||||
(True if self.follow else False))] = 'follow'
|
||||
self.values[MenuNode('separator1', 'separator')] = ''
|
||||
self.values[MenuNode(_('Use favourites only'), 'check',
|
||||
(True if self.favourites else False))] = 'favourite'
|
||||
self.values[MenuNode('separator2', 'separator')] = ''
|
||||
self.values[MenuNode(_('Browser Preferences'))] = 'browser prefs'
|
||||
self.values[MenuNode(_('Search Preferences'))] = 'search prefs'
|
||||
|
||||
self.options = list(self.values.keys())
|
||||
|
||||
self.update_images(False)
|
||||
|
||||
if self.favourites:
|
||||
self._source.propertiesbutton_callback('favourite')
|
||||
|
||||
if self.follow:
|
||||
self._source.propertiesbutton_callback('follow')
|
||||
|
||||
self.current_key = None
|
||||
|
||||
def _connect_properties(self):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting.bind(
|
||||
gs.PluginKey.USE_FAVOURITES,
|
||||
self,
|
||||
'favourites',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
setting.bind(
|
||||
gs.PluginKey.FOLLOWING,
|
||||
self,
|
||||
'follow',
|
||||
Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
def _change_key(self, dict, old, new):
|
||||
for i in range(len(dict)):
|
||||
k, v = dict.popitem(False)
|
||||
dict[new if old == k else k] = v
|
||||
|
||||
def update_images(self, *args):
|
||||
self._image = self.create_button_image(self.plugin,
|
||||
None, 'properties.png')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
|
||||
def do_action(self):
|
||||
if self.current_key:
|
||||
key = [node for node in self.values if node.label == self.current_key]
|
||||
|
||||
if self.current_key == _('Use favourites only'):
|
||||
self.favourites = not self.favourites
|
||||
|
||||
if self.current_key == _('Follow playing song'):
|
||||
self.follow = not self.follow
|
||||
|
||||
self._source.propertiesbutton_callback(self.values[key[0]])
|
||||
self.current_key = None
|
||||
|
||||
def get_current_image(self):
|
||||
return self._image
|
||||
|
||||
def get_current_description(self):
|
||||
return _('Properties')
|
||||
|
||||
|
||||
class DecadePopupController(OptionsController):
|
||||
def __init__(self, plugin, album_model):
|
||||
super(DecadePopupController, self).__init__()
|
||||
|
||||
@@ -423,7 +573,7 @@ class DecadePopupController(OptionsController):
|
||||
self.plugin = plugin
|
||||
|
||||
self._spritesheet = None
|
||||
|
||||
|
||||
# decade options
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
@@ -454,7 +604,7 @@ class DecadePopupController(OptionsController):
|
||||
#'Older' as in 'older than the year 1930'
|
||||
self.values[_('Older')] = [-1, 'Older']
|
||||
|
||||
self.options = self.values.keys()
|
||||
self.options = list(self.values.keys())
|
||||
|
||||
# if we aren't on the 20s yet, remove it
|
||||
if date.today().year < 2020:
|
||||
@@ -463,13 +613,13 @@ class DecadePopupController(OptionsController):
|
||||
# define a initial decade an set the initial key
|
||||
self._initial_decade = self.options[0]
|
||||
self.update_images(False)
|
||||
|
||||
|
||||
self.current_key = self._initial_decade
|
||||
|
||||
def update_images(self, *args):
|
||||
self._spritesheet = self.create_spritesheet( self.plugin,
|
||||
self._spritesheet, 'decade')
|
||||
|
||||
self._spritesheet = self.create_spritesheet(self.plugin,
|
||||
self._spritesheet, 'decade')
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
|
||||
@@ -478,7 +628,7 @@ class DecadePopupController(OptionsController):
|
||||
self._album_model.remove_filter('decade')
|
||||
else:
|
||||
self._album_model.replace_filter('decade',
|
||||
self.values[self.current_key][0])
|
||||
self.values[self.current_key][0])
|
||||
|
||||
def get_current_image(self):
|
||||
decade = self.values[self.current_key][1]
|
||||
@@ -489,56 +639,66 @@ class DecadePopupController(OptionsController):
|
||||
|
||||
|
||||
class SortOrderToggleController(OptionsController):
|
||||
toolbar_type = "album"
|
||||
|
||||
def __init__(self, plugin, album_model):
|
||||
def __init__(self, plugin, viewmgr):
|
||||
super(SortOrderToggleController, self).__init__()
|
||||
|
||||
self._album_model = album_model
|
||||
self._viewmgr = viewmgr
|
||||
self.plugin = plugin
|
||||
|
||||
# options
|
||||
self.values = OrderedDict([(_('Sort in descending order'), False),
|
||||
(_('Sort in ascending order'), True)])
|
||||
self.options = self.values.keys()
|
||||
(_('Sort in ascending order'), True)])
|
||||
self.options = list(self.values.keys())
|
||||
|
||||
self._images = []
|
||||
|
||||
|
||||
# set the current key
|
||||
self.gs = GSetting()
|
||||
self.settings = self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
sort_order = self.settings[self.gs.PluginKey.SORT_ORDER]
|
||||
self.current_key = self.values.keys()[
|
||||
self.values.values().index(sort_order)]
|
||||
self.key = self.get_key()
|
||||
sort_order = self.settings[self.key]
|
||||
self.current_key = list(self.values.keys())[
|
||||
list(self.values.values()).index(sort_order)]
|
||||
self.update_images(False)
|
||||
|
||||
|
||||
def get_key(self):
|
||||
return self.gs.PluginKey.SORT_ORDER
|
||||
|
||||
def update_images(self, *args):
|
||||
# initialize images
|
||||
if len(self._images) > 0:
|
||||
del self._images[:]
|
||||
|
||||
self._images.append(self.create_button_image( self.plugin,
|
||||
None, 'arrow_down.png'))
|
||||
self._images.append(self.create_button_image( self.plugin,
|
||||
None, 'arrow_up.png'))
|
||||
|
||||
self._images.append(self.create_button_image(self.plugin,
|
||||
None, 'arrow_down.png'))
|
||||
self._images.append(self.create_button_image(self.plugin,
|
||||
None, 'arrow_up.png'))
|
||||
|
||||
if args[-1]:
|
||||
self.update_image = True
|
||||
|
||||
|
||||
def do_action(self):
|
||||
sort_order = self.values[self.current_key]
|
||||
|
||||
if not sort_order or\
|
||||
sort_order != self.settings[self.gs.PluginKey.SORT_ORDER]:
|
||||
self._album_model.sort(reverse=True)
|
||||
|
||||
self.settings[self.gs.PluginKey.SORT_ORDER] = sort_order
|
||||
self.settings[self.key] = sort_order
|
||||
self._viewmgr.current_view.get_default_manager().emit('sort', self.toolbar_type)
|
||||
|
||||
def get_current_image(self):
|
||||
return self._images[self.get_current_key_index()]
|
||||
|
||||
|
||||
class AlbumSearchEntryController(OptionsController):
|
||||
class ArtistSortOrderToggleController(SortOrderToggleController):
|
||||
toolbar_type = "artist"
|
||||
|
||||
def __init__(self, plugin, model):
|
||||
super(ArtistSortOrderToggleController, self).__init__(plugin, model)
|
||||
|
||||
def get_key(self):
|
||||
return self.gs.PluginKey.SORT_ORDER_ARTIST
|
||||
|
||||
|
||||
class AlbumSearchEntryController(OptionsController):
|
||||
# properties
|
||||
search_text = GObject.property(type=str, default='')
|
||||
|
||||
@@ -553,22 +713,47 @@ class AlbumSearchEntryController(OptionsController):
|
||||
self.values[_('Search all fields')] = 'all'
|
||||
self.values[_('Search album artists')] = 'album_artist'
|
||||
self.values[_('Search track artists')] = 'artist'
|
||||
self.values[_('Search composers')] = 'composers'
|
||||
self.values[_('Search albums')] = 'album_name'
|
||||
self.values[_('Search tracks')] = 'track'
|
||||
self.values[_('Search titles')] = 'track'
|
||||
|
||||
self.options = self.values.keys()
|
||||
self.current_key = self.values.keys()[0]
|
||||
self.options = list(self.values.keys())
|
||||
self.current_key = list(self.values.keys())[0]
|
||||
|
||||
self._typing = False
|
||||
self._typing_counter = 0
|
||||
self._current_search_text = ""
|
||||
|
||||
def do_action(self):
|
||||
# remove old filter
|
||||
self._album_model.remove_filter(self._filter_type, False)
|
||||
|
||||
# asign the new filter
|
||||
# assign the new filter
|
||||
self._filter_type = self.values[self.current_key]
|
||||
|
||||
self.do_search(self.search_text, True)
|
||||
|
||||
def _search_typing(self, *args):
|
||||
self._typing_counter = self._typing_counter + 1
|
||||
|
||||
if self._typing_counter >= 4 and self._typing:
|
||||
self._typing = False
|
||||
self._change_filter(self._current_search_text, False)
|
||||
|
||||
return self._typing
|
||||
|
||||
def _change_filter(self, search_text, force):
|
||||
#self.search_text = search_text
|
||||
self._current_search_text = search_text
|
||||
|
||||
if search_text:
|
||||
self._album_model.replace_filter(self._filter_type,
|
||||
search_text)
|
||||
elif not force:
|
||||
self._album_model.remove_filter(self._filter_type)
|
||||
|
||||
def do_search(self, search_text, force=False):
|
||||
'''
|
||||
if self.search_text != search_text or force:
|
||||
self.search_text = search_text
|
||||
|
||||
@@ -578,8 +763,28 @@ class AlbumSearchEntryController(OptionsController):
|
||||
elif not force:
|
||||
self._album_model.remove_filter(self._filter_type)
|
||||
|
||||
class AlbumQuickSearchController(object):
|
||||
'''
|
||||
#self.search_text = search_text
|
||||
if force:
|
||||
self._typing_counter = 99
|
||||
self._typing = False
|
||||
self._change_filter(search_text, force)
|
||||
return
|
||||
|
||||
if self._current_search_text != search_text:
|
||||
|
||||
#self.search_text = search_text
|
||||
self._current_search_text = search_text
|
||||
self._typing_counter = 0
|
||||
|
||||
if not self._typing:
|
||||
self._typing = True
|
||||
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 100,
|
||||
self._search_typing)
|
||||
|
||||
|
||||
class AlbumQuickSearchController(object):
|
||||
def __init__(self, album_manager):
|
||||
self._album_manager = album_manager
|
||||
|
||||
@@ -590,14 +795,14 @@ class AlbumQuickSearchController(object):
|
||||
|
||||
def _on_quick_search(self, quick_search, search_text, *args):
|
||||
album = self._album_manager.model.find_first_visible('album_name',
|
||||
search_text)
|
||||
search_text)
|
||||
|
||||
if album:
|
||||
path = self._album_manager.model.get_path(album)
|
||||
self._album_manager.cover_view.select_and_scroll_to_path(path)
|
||||
self._album_manager.current_view.select_and_scroll_to_path(path)
|
||||
|
||||
def _on_arrow_pressed(self, quick_search, key, *args):
|
||||
current = self._album_manager.cover_view.get_selected_objects()[0]
|
||||
current = self._album_manager.current_view.get_selected_objects()[0]
|
||||
search_text = quick_search.get_text()
|
||||
album = None
|
||||
|
||||
@@ -610,7 +815,35 @@ class AlbumQuickSearchController(object):
|
||||
|
||||
if album:
|
||||
path = self._album_manager.model.get_path(album)
|
||||
self._album_manager.cover_view.select_and_scroll_to_path(path)
|
||||
self._album_manager.current_view.select_and_scroll_to_path(path)
|
||||
|
||||
def _on_hide(self, quick_search, *args):
|
||||
self._album_manager.cover_view.grab_focus()
|
||||
self._album_manager.current_view.grab_focus()
|
||||
|
||||
|
||||
class ViewController(OptionsController):
|
||||
def __init__(self, shell, viewmgr):
|
||||
super(ViewController, self).__init__()
|
||||
|
||||
self._viewmgr = viewmgr
|
||||
|
||||
from coverart_browser_source import Views
|
||||
|
||||
views = Views(shell)
|
||||
|
||||
self.values = OrderedDict()
|
||||
for view_name in views.get_view_names():
|
||||
self.values[views.get_menu_name(view_name)] = view_name
|
||||
print(view_name)
|
||||
|
||||
self.options = list(self.values.keys())
|
||||
viewmgr.connect('new-view', self.on_notify_view_name)
|
||||
|
||||
def on_notify_view_name(self, *args):
|
||||
for key in self.options:
|
||||
if self.values[key] == self._viewmgr.view_name:
|
||||
self.current_key = key
|
||||
|
||||
def do_action(self):
|
||||
if self._viewmgr.view_name != self.values[self.current_key]:
|
||||
self._viewmgr.view_name = self.values[self.current_key]
|
||||
|
||||
@@ -0,0 +1,436 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import json
|
||||
import os
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gio
|
||||
|
||||
from coverart_browser_prefs import GSetting
|
||||
from coverart_browser_prefs import webkit_support
|
||||
from coverart_widgets import AbstractView
|
||||
from coverart_widgets import PanedCollapsible
|
||||
import rb
|
||||
|
||||
|
||||
class FlowShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
the view that makes use of the `AlbumsModel`.
|
||||
'''
|
||||
|
||||
def __init__(self, flow_view):
|
||||
super(FlowShowingPolicy, self).__init__()
|
||||
|
||||
self._flow_view = flow_view
|
||||
self.counter = 0
|
||||
self._has_initialised = False
|
||||
|
||||
def initialise(self, album_manager):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
self._album_manager = album_manager
|
||||
self._model = album_manager.model
|
||||
|
||||
|
||||
class CoverFlowView(AbstractView):
|
||||
__gtype_name__ = "CoverFlowView"
|
||||
|
||||
name = 'coverflowview'
|
||||
|
||||
#properties
|
||||
flow_background = GObject.property(type=str, default='W')
|
||||
flow_automatic = GObject.property(type=bool, default=False)
|
||||
flow_scale = GObject.property(type=int, default=100)
|
||||
flow_hide = GObject.property(type=bool, default=False)
|
||||
flow_width = GObject.property(type=int, default=600)
|
||||
flow_appearance = GObject.property(type=str, default='coverflow')
|
||||
flow_max = GObject.property(type=int, default=100)
|
||||
panedposition = PanedCollapsible.Paned.EXPAND
|
||||
|
||||
def __init__(self):
|
||||
super(CoverFlowView, self).__init__()
|
||||
|
||||
self.show_policy = FlowShowingPolicy(self)
|
||||
if webkit_support():
|
||||
from gi.repository import WebKit
|
||||
|
||||
self.view = WebKit.WebView()
|
||||
else:
|
||||
self.view = None
|
||||
|
||||
self._last_album = None
|
||||
self._has_initialised = False
|
||||
self._filter_changed_inprogress = False
|
||||
self._on_first_use = True
|
||||
|
||||
def _connect_properties(self):
|
||||
gs = GSetting()
|
||||
settings = gs.get_setting(gs.Path.PLUGIN)
|
||||
settings.bind(gs.PluginKey.FLOW_APPEARANCE, self,
|
||||
'flow_appearance', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_HIDE_CAPTION, self,
|
||||
'flow_hide', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_SCALE, self,
|
||||
'flow_scale', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_AUTOMATIC, self,
|
||||
'flow_automatic', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_BACKGROUND_COLOUR, self,
|
||||
'flow_background', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_WIDTH, self,
|
||||
'flow_width', Gio.SettingsBindFlags.GET)
|
||||
settings.bind(gs.PluginKey.FLOW_MAX, self,
|
||||
'flow_max', Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _connect_signals(self, source):
|
||||
self.connect('notify::flow-background',
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-scale',
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-hide',
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-width',
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-appearance',
|
||||
self.filter_changed)
|
||||
self.connect('notify::flow-max',
|
||||
self.filter_changed)
|
||||
|
||||
def filter_changed(self, *args):
|
||||
# we can get several filter_changed calls per second
|
||||
# lets simplify the processing & potential flickering when the
|
||||
# call to this method has slowed stopped
|
||||
|
||||
self._filter_changed_event = True
|
||||
|
||||
if self._filter_changed_inprogress:
|
||||
return
|
||||
|
||||
self._filter_changed_inprogress = True
|
||||
|
||||
def filter_events(*args):
|
||||
if not self._filter_changed_event:
|
||||
self._filter_changed()
|
||||
self._filter_changed_inprogress = False
|
||||
else:
|
||||
self._filter_changed_event = False
|
||||
return True
|
||||
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250, filter_events, None)
|
||||
|
||||
|
||||
def _filter_changed(self, *args):
|
||||
path = rb.find_plugin_file(self.plugin, 'coverflow/index.html')
|
||||
f = open(path)
|
||||
string = f.read()
|
||||
f.close()
|
||||
|
||||
if self.flow_background == 'W':
|
||||
background_colour = 'white'
|
||||
if len(self.album_manager.model.store) <= self.flow_max:
|
||||
foreground_colour = 'white'
|
||||
else:
|
||||
foreground_colour = 'black'
|
||||
else:
|
||||
background_colour = 'black'
|
||||
if len(self.album_manager.model.store) <= self.flow_max:
|
||||
foreground_colour = 'black'
|
||||
else:
|
||||
foreground_colour = 'white'
|
||||
|
||||
string = string.replace('#BACKGROUND_COLOUR', background_colour)
|
||||
string = string.replace('#FOREGROUND_COLOUR', foreground_colour)
|
||||
string = string.replace('#FACTOR', str(float(self.flow_scale) / 100))
|
||||
|
||||
if self.flow_hide:
|
||||
caption = ""
|
||||
else:
|
||||
caption = '<div class="globalCaption"></div>'
|
||||
|
||||
string = string.replace('#GLOBAL_CAPTION', caption)
|
||||
|
||||
addon = background_colour
|
||||
if self.flow_appearance == 'flow-vert':
|
||||
addon += " vertical"
|
||||
elif self.flow_appearance == 'carousel':
|
||||
addon += " carousel"
|
||||
elif self.flow_appearance == 'roundabout':
|
||||
addon += " roundabout"
|
||||
|
||||
string = string.replace('#ADDON', addon)
|
||||
|
||||
string = string.replace('#WIDTH', str(self.flow_width))
|
||||
|
||||
identifier = self.flow.get_identifier(self.last_album)
|
||||
if not identifier:
|
||||
identifier = "'start'"
|
||||
else:
|
||||
identifier = str(identifier)
|
||||
|
||||
string = string.replace('#START', identifier)
|
||||
|
||||
#TRANSLATORS: for example 'Number of covers limited to 150'
|
||||
display_message = _("Number of covers limited to %d") % self.flow_max
|
||||
string = string.replace('#MAXCOVERS',
|
||||
'<p>' + display_message + '</p>')
|
||||
|
||||
items = self.flow.initialise(self.album_manager.model, self.flow_max)
|
||||
|
||||
string = string.replace('#ITEMS', items)
|
||||
|
||||
base = os.path.dirname(path) + "/"
|
||||
Gdk.threads_enter()
|
||||
print(string)
|
||||
self.view.load_string(string, "text/html", "UTF-8", "file://" + base)
|
||||
Gdk.threads_leave()
|
||||
|
||||
if self._on_first_use:
|
||||
self._on_first_use = False
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
self.source.show_hide_pane, (self.last_album, PanedCollapsible.Paned.EXPAND))
|
||||
|
||||
def get_view_icon_name(self):
|
||||
return "flowview.png"
|
||||
|
||||
def initialise(self, source):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
super(CoverFlowView, self).initialise(source)
|
||||
|
||||
self.album_manager = source.album_manager
|
||||
self.ext_menu_pos = 6
|
||||
|
||||
self._connect_properties()
|
||||
self._connect_signals(source)
|
||||
|
||||
# lets check that all covers have finished loading before
|
||||
# initialising the flowcontrol and other signals
|
||||
if not self.album_manager.cover_man.has_finished_loading:
|
||||
self.album_manager.cover_man.connect('load-finished', self._covers_loaded)
|
||||
else:
|
||||
self._covers_loaded()
|
||||
|
||||
def _covers_loaded(self, *args):
|
||||
self.flow = FlowControl(self)
|
||||
self.view.connect("notify::title", self.flow.receive_message_signal)
|
||||
|
||||
#self.album_manager.model.connect('album-updated', self.flow.update_album, self.view)
|
||||
#self.album_manager.model.connect('visual-updated', self.flow.update_album, self.view)
|
||||
self.album_manager.model.connect('album-updated', self.filter_changed)
|
||||
self.album_manager.model.connect('visual-updated', self.filter_changed)
|
||||
self.album_manager.model.connect('filter-changed', self.filter_changed)
|
||||
|
||||
self.filter_changed()
|
||||
|
||||
@property
|
||||
def last_album(self):
|
||||
return self._last_album
|
||||
|
||||
@last_album.setter
|
||||
def last_album(self, new_album):
|
||||
if self._last_album != new_album:
|
||||
self._last_album = new_album
|
||||
self.source.click_count = 0
|
||||
self.selectionchanged_callback()
|
||||
|
||||
def item_rightclicked_callback(self, album):
|
||||
self.last_album = album
|
||||
self.popup.popup(self.source, 'popup_menu', 3, Gtk.get_current_event_time())
|
||||
|
||||
def item_clicked_callback(self, album):
|
||||
'''
|
||||
Callback called when the user clicks somewhere on the flow_view.
|
||||
Along with source "show_hide_pane", takes care of showing/hiding the bottom
|
||||
pane after a second click on a selected album.
|
||||
'''
|
||||
# to expand the entry view
|
||||
if self.flow_automatic:
|
||||
self.source.click_count += 1
|
||||
|
||||
self.last_album = album
|
||||
|
||||
if self.source.click_count == 1:
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
self.source.show_hide_pane, album)
|
||||
|
||||
def item_activated_callback(self, album):
|
||||
'''
|
||||
Callback called when the flow view is double clicked. It plays the selected album
|
||||
'''
|
||||
self.last_album = album
|
||||
self.source.play_selected_album()
|
||||
|
||||
return True
|
||||
|
||||
def item_drop_callback(self, album, webpath):
|
||||
'''
|
||||
Callback called when something is dropped onto the flow view - hopefully a webpath
|
||||
to a picture
|
||||
'''
|
||||
print("item_drop_callback %s" % webpath)
|
||||
print("dropped on album %s" % album)
|
||||
self.album_manager.cover_man.update_cover(album, uri=webpath)
|
||||
|
||||
def get_selected_objects(self):
|
||||
if self.last_album:
|
||||
return [self.last_album]
|
||||
else:
|
||||
return []
|
||||
|
||||
def select_and_scroll_to_path(self, path):
|
||||
album = self.source.album_manager.model.get_from_path(path)
|
||||
self.flow.scroll_to_album(album, self.view)
|
||||
self.item_clicked_callback(album)
|
||||
|
||||
def switch_to_view(self, source, album):
|
||||
self.initialise(source)
|
||||
self.show_policy.initialise(source.album_manager)
|
||||
|
||||
self.last_album = album
|
||||
self.scroll_to_album(self.last_album)
|
||||
|
||||
def grab_focus(self):
|
||||
self.view.grab_focus()
|
||||
|
||||
def scroll_to_album(self, album):
|
||||
self.flow.scroll_to_album(album, self.view)
|
||||
|
||||
|
||||
class FlowControl(object):
|
||||
def __init__(self, callback_view):
|
||||
self.callback_view = callback_view
|
||||
self.album_identifier = {}
|
||||
|
||||
def get_identifier(self, album):
|
||||
index = -1
|
||||
for row in self.album_identifier:
|
||||
if self.album_identifier[row] == album:
|
||||
index = row
|
||||
break
|
||||
|
||||
if index == -1:
|
||||
return None
|
||||
else:
|
||||
return row
|
||||
|
||||
def update_album(self, model, album_path, album_iter, webview):
|
||||
album = model.get_from_path(album_path)
|
||||
index = -1
|
||||
for row in self.album_identifier:
|
||||
if self.album_identifier[row] == album:
|
||||
index = row
|
||||
break
|
||||
|
||||
if index == -1:
|
||||
return
|
||||
|
||||
obj = {}
|
||||
obj['filename'] = album.cover.original
|
||||
obj['title'] = album.artist
|
||||
obj['caption'] = album.name
|
||||
obj['identifier'] = str(index)
|
||||
|
||||
webview.execute_script("update_album('%s')" % json.dumps(obj))
|
||||
|
||||
def receive_message_signal(self, webview, param):
|
||||
# this will be key to passing stuff back and forth - need
|
||||
# to develop some-sort of message protocol to distinguish "events"
|
||||
|
||||
title = webview.get_title()
|
||||
if (not title) or (title == '"clear"'):
|
||||
return
|
||||
|
||||
args = json.loads(title)
|
||||
try:
|
||||
signal = args["signal"]
|
||||
except:
|
||||
print("unhandled: %s " % title)
|
||||
return
|
||||
|
||||
if signal == 'clickactive':
|
||||
self.callback_view.item_clicked_callback(self.album_identifier[int(args['param'][0])])
|
||||
elif signal == 'rightclickactive':
|
||||
self.callback_view.item_rightclicked_callback(
|
||||
self.album_identifier[int(args['param'][0])])
|
||||
elif signal == 'doubleclickactive':
|
||||
self.callback_view.item_activated_callback(self.album_identifier[int(args['param'][0])])
|
||||
elif signal == 'dropactive':
|
||||
self.callback_view.item_drop_callback(self.album_identifier[int(args['param'][0])],
|
||||
args['param'][1])
|
||||
else:
|
||||
print("unhandled signal: %s" % signal)
|
||||
|
||||
def scroll_to_album(self, album, webview):
|
||||
for row in self.album_identifier:
|
||||
if self.album_identifier[row] == album:
|
||||
webview.execute_script("scroll_to_identifier('%s')" % str(row))
|
||||
break
|
||||
|
||||
def initialise(self, model, max_covers):
|
||||
|
||||
album_col = model.columns['album']
|
||||
index = 0
|
||||
items = ""
|
||||
self.album_identifier = {}
|
||||
|
||||
def html_elements(fullfilename, title, caption, identifier):
|
||||
|
||||
return '<div class="item"><img class="content" src="' + \
|
||||
escape(fullfilename) + '" title="' + \
|
||||
escape(title) + '" identifier="' + \
|
||||
identifier + '"/> <div class="caption">' + \
|
||||
escape(caption) + '</div> </div>'
|
||||
|
||||
|
||||
for row in model.store:
|
||||
|
||||
cover = row[album_col].cover.original
|
||||
cover = cover.replace(
|
||||
'rhythmbox-missing-artwork.svg',
|
||||
'rhythmbox-missing-artwork.png') ## need a white vs black when we change the background colour
|
||||
|
||||
self.album_identifier[index] = row[album_col]
|
||||
items += html_elements(
|
||||
fullfilename=cover,
|
||||
caption=row[album_col].name,
|
||||
title=row[album_col].artist,
|
||||
identifier=str(index))
|
||||
|
||||
index += 1
|
||||
|
||||
if index == max_covers:
|
||||
break
|
||||
|
||||
if index != 0:
|
||||
#self.callback_view.last_album = self.album_identifier[0]
|
||||
pass
|
||||
else:
|
||||
self.callback_view.last_album = None
|
||||
|
||||
return items
|
||||
@@ -0,0 +1,690 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gio
|
||||
from gi.repository import Pango
|
||||
from gi.repository import PangoCairo
|
||||
from gi.repository import GdkPixbuf
|
||||
|
||||
from coverart_widgets import EnhancedIconView
|
||||
from coverart_browser_prefs import GSetting
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
from coverart_album import AlbumsModel
|
||||
from coverart_widgets import AbstractView
|
||||
from coverart_widgets import PanedCollapsible
|
||||
import coverart_rb3compat as rb3compat
|
||||
import rb
|
||||
import gettext
|
||||
|
||||
PLAY_SIZE_X = 30
|
||||
PLAY_SIZE_Y = 30
|
||||
|
||||
|
||||
class CellRendererThumb(Gtk.CellRendererPixbuf):
|
||||
markup = GObject.property(type=str, default="")
|
||||
|
||||
def __init__(self, font_description, cell_area_source):
|
||||
super(CellRendererThumb, self).__init__()
|
||||
self.font_description = font_description
|
||||
self.cell_area_source = cell_area_source
|
||||
ypad = 0
|
||||
|
||||
def do_render(self, cr, widget,
|
||||
background_area,
|
||||
cell_area,
|
||||
flags):
|
||||
|
||||
|
||||
x_offset = cell_area.x + 1
|
||||
y_offset = cell_area.y + 1
|
||||
wi = 0
|
||||
he = 0
|
||||
#IMAGE
|
||||
pixbuf = self.props.pixbuf.scale_simple(cell_area.width - 2, cell_area.height - 2,
|
||||
GdkPixbuf.InterpType.NEAREST)
|
||||
Gdk.cairo_set_source_pixbuf(cr, pixbuf, x_offset, y_offset)
|
||||
cr.paint()
|
||||
|
||||
alpha = 0.40
|
||||
|
||||
if ((flags & Gtk.CellRendererState.PRELIT) == Gtk.CellRendererState.PRELIT):
|
||||
alpha -= 0.15
|
||||
|
||||
if hasattr(Gtk.IconView, "get_cell_rect") and self.cell_area_source.hover_pixbuf:
|
||||
# this only works on Gtk+3.6 and later
|
||||
Gdk.cairo_set_source_pixbuf(cr,
|
||||
self.cell_area_source.hover_pixbuf, x_offset, y_offset)
|
||||
cr.paint()
|
||||
|
||||
#if((flags & Gtk.CellRendererState.SELECTED) == Gtk.CellRendererState.SELECTED or \
|
||||
# (flags & Gtk.CellRendererState.FOCUSED) == Gtk.CellRendererState.FOCUSED):
|
||||
# alpha -= 0.15
|
||||
|
||||
|
||||
if not (self.cell_area_source.display_text and self.cell_area_source.display_text_pos == False):
|
||||
return
|
||||
|
||||
#PANGO LAYOUT
|
||||
layout_width = cell_area.width - 2
|
||||
pango_layout = PangoCairo.create_layout(cr)
|
||||
pango_layout.set_markup(self.markup, -1)
|
||||
pango_layout.set_alignment(Pango.Alignment.CENTER)
|
||||
pango_layout.set_font_description(self.font_description)
|
||||
pango_layout.set_width(int(layout_width * Pango.SCALE))
|
||||
pango_layout.set_wrap(Pango.WrapMode.WORD_CHAR)
|
||||
wi, he = pango_layout.get_pixel_size()
|
||||
|
||||
rect_offset = y_offset + (int((2.0 * self.cell_area_source.cover_size) / 3.0))
|
||||
rect_height = int(self.cell_area_source.cover_size / 3.0)
|
||||
was_to_large = False;
|
||||
if (he > rect_height):
|
||||
was_to_large = True
|
||||
pango_layout.set_ellipsize(Pango.EllipsizeMode.END)
|
||||
pango_layout.set_height(int((self.cell_area_source.cover_size / 3.0) * Pango.SCALE))
|
||||
wi, he = pango_layout.get_pixel_size()
|
||||
|
||||
#RECTANGLE
|
||||
cr.set_source_rgba(0.0, 0.0, 0.0, alpha)
|
||||
cr.set_line_width(0)
|
||||
cr.rectangle(x_offset,
|
||||
rect_offset,
|
||||
cell_area.width - 1,
|
||||
rect_height - 1)
|
||||
cr.fill()
|
||||
|
||||
#DRAW FONT
|
||||
cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
|
||||
cr.move_to(x_offset,
|
||||
y_offset
|
||||
+ 2.0 * self.cell_area_source.cover_size / 3.0
|
||||
+ (((self.cell_area_source.cover_size / 3.0) - he) / 2.0)
|
||||
)
|
||||
PangoCairo.show_layout(cr, pango_layout)
|
||||
|
||||
|
||||
class AlbumArtCellArea(Gtk.CellAreaBox):
|
||||
font_family = GObject.property(type=str, default="Sans")
|
||||
font_size = GObject.property(type=int, default=10)
|
||||
cover_size = GObject.property(type=int, default=0)
|
||||
display_text_pos = GObject.property(type=bool, default=False)
|
||||
display_text = GObject.property(type=bool, default=False)
|
||||
hover_pixbuf = GObject.property(type=object, default=None)
|
||||
|
||||
def __init__(self, ):
|
||||
super(AlbumArtCellArea, self).__init__()
|
||||
|
||||
self.font_description = Pango.FontDescription.new()
|
||||
self.font_description.set_family(self.font_family)
|
||||
self.font_description.set_size(int(self.font_size * Pango.SCALE))
|
||||
|
||||
self._connect_properties()
|
||||
|
||||
#Add own cellrenderer
|
||||
renderer_thumb = CellRendererThumb(self.font_description, self)
|
||||
|
||||
self.pack_start(renderer_thumb, False, False, False)
|
||||
self.attribute_connect(renderer_thumb, "pixbuf", AlbumsModel.columns['pixbuf'])
|
||||
self.attribute_connect(renderer_thumb, "markup", AlbumsModel.columns['markup'])
|
||||
self.props.spacing = 2
|
||||
|
||||
def _connect_properties(self):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
|
||||
setting.bind(gs.PluginKey.COVER_SIZE, self, 'cover-size',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(gs.PluginKey.DISPLAY_TEXT_POS, self, 'display-text-pos',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(gs.PluginKey.DISPLAY_TEXT, self, 'display-text',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
|
||||
class AlbumShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
the view that makes use of the `AlbumsModel`.
|
||||
'''
|
||||
|
||||
def __init__(self, cover_view):
|
||||
super(AlbumShowingPolicy, self).__init__()
|
||||
|
||||
self._cover_view = cover_view # this will need to be reworked for all views
|
||||
self._visible_paths = None
|
||||
self._has_initialised = False
|
||||
|
||||
def initialise(self, album_manager):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._album_manager = album_manager
|
||||
self._model = album_manager.model
|
||||
self._connect_signals()
|
||||
self._has_initialised = True
|
||||
|
||||
def _connect_signals(self):
|
||||
self._cover_view.props.vadjustment.connect('value-changed',
|
||||
self._viewport_changed)
|
||||
self._model.connect('album-updated', self._album_updated)
|
||||
self._model.connect('visual-updated', self._album_updated)
|
||||
|
||||
def _viewport_changed(self, *args):
|
||||
visible_range = self._cover_view.get_visible_range()
|
||||
|
||||
if visible_range:
|
||||
init, end = visible_range
|
||||
|
||||
# i have to use the tree iter instead of the path to iterate since
|
||||
# for some reason path.next doesn't work with the filtermodel
|
||||
tree_iter = self._model.store.get_iter(init)
|
||||
|
||||
self._visible_paths = []
|
||||
|
||||
while init and init != end:
|
||||
self._visible_paths.append(init)
|
||||
|
||||
tree_iter = self._model.store.iter_next(tree_iter)
|
||||
init = self._model.store.get_path(tree_iter)
|
||||
|
||||
self._visible_paths.append(end)
|
||||
|
||||
def _album_updated(self, model, album_path, album_iter):
|
||||
# get the currently showing paths
|
||||
if not self._visible_paths:
|
||||
self._viewport_changed()
|
||||
|
||||
if (album_path and self._visible_paths) and album_path in self._visible_paths:
|
||||
# if our path is on the viewport, emit the signal to update it
|
||||
self._cover_view.queue_draw()
|
||||
|
||||
|
||||
class CoverIconView(EnhancedIconView, AbstractView):
|
||||
__gtype_name__ = "CoverIconView"
|
||||
|
||||
icon_spacing = GObject.property(type=int, default=0)
|
||||
icon_padding = GObject.property(type=int, default=0)
|
||||
icon_automatic = GObject.property(type=bool, default=True)
|
||||
|
||||
display_text_enabled = GObject.property(type=bool, default=False)
|
||||
display_text_pos = GObject.property(type=bool, default=False)
|
||||
name = 'coverview'
|
||||
panedposition = PanedCollapsible.Paned.COLLAPSE
|
||||
|
||||
__gsignals__ = {
|
||||
'update-toolbar': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if not rb3compat.compare_pygobject_version("3.9"):
|
||||
super(CoverIconView, self).__init__(cell_area=AlbumArtCellArea(), *args, **kwargs)
|
||||
else:
|
||||
# this works in trusty but not in earlier versions - define in the super above
|
||||
super(CoverIconView, self).__init__(*args, **kwargs)
|
||||
self.props.cell_area = AlbumArtCellArea()
|
||||
|
||||
self.gs = GSetting()
|
||||
# custom text renderer
|
||||
self._text_renderer = None
|
||||
self.show_policy = AlbumShowingPolicy(self)
|
||||
self.view = self
|
||||
self._has_initialised = False
|
||||
self._last_path = None
|
||||
self._calc_motion_step = 0
|
||||
|
||||
def initialise(self, source):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
self.view_name = "covers_view"
|
||||
super(CoverIconView, self).initialise(source)
|
||||
|
||||
self.shell = source.shell
|
||||
self.album_manager = source.album_manager
|
||||
|
||||
# setup iconview drag&drop support
|
||||
# first drag and drop on the coverart view to receive coverart
|
||||
self.enable_model_drag_dest([], Gdk.DragAction.COPY)
|
||||
self.drag_dest_add_image_targets()
|
||||
self.drag_dest_add_text_targets()
|
||||
self.connect('drag-drop', self.on_drag_drop)
|
||||
self.connect('drag-data-received',
|
||||
self.on_drag_data_received)
|
||||
self.source.paned.connect("expanded", self.bottom_expander_expanded_callback)
|
||||
|
||||
# lastly support drag-drop from coverart to devices/nautilus etc
|
||||
self.connect('drag-begin', self.on_drag_begin)
|
||||
self.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
|
||||
[], Gdk.DragAction.COPY)
|
||||
#targets = Gtk.TargetList.new([Gtk.TargetEntry.new("application/x-rhythmbox-entry", 0, 0),
|
||||
# Gtk.TargetEntry.new("text/uri-list", 0, 1) ])
|
||||
targets = Gtk.TargetList.new([Gtk.TargetEntry.new("text/uri-list", 0, 0)])
|
||||
# N.B. values taken from rhythmbox v2.97 widgets/rb_entry_view.c
|
||||
targets.add_uri_targets(1)
|
||||
|
||||
self.drag_source_set_target_list(targets)
|
||||
self.connect("drag-data-get", self.on_drag_data_get)
|
||||
|
||||
# set the model to the view
|
||||
#self.set_pixbuf_column(AlbumsModel.columns['pixbuf'])
|
||||
self.set_model(self.album_manager.model.store)
|
||||
|
||||
# setup view to monitor mouse movements
|
||||
self.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
|
||||
|
||||
self.hover_pixbufs = {
|
||||
'button_play': None,
|
||||
'button_play_hover': None,
|
||||
'button_playpause': None,
|
||||
'button_playpause_hover': None,
|
||||
'button_queue': None,
|
||||
'button_queue_hover': None,
|
||||
}
|
||||
|
||||
for pixbuf_type in self.hover_pixbufs:
|
||||
filename = 'img/' + pixbuf_type + '.png'
|
||||
filename = rb.find_plugin_file(self.plugin, filename)
|
||||
self.hover_pixbufs[pixbuf_type] = GdkPixbuf.Pixbuf.new_from_file_at_size(filename,
|
||||
PLAY_SIZE_X, PLAY_SIZE_Y)
|
||||
|
||||
self._connect_properties()
|
||||
self._connect_signals()
|
||||
|
||||
self._activate_markup()
|
||||
self.on_notify_icon_padding()
|
||||
self.on_notify_icon_spacing()
|
||||
|
||||
def _connect_properties(self):
|
||||
setting = self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
setting.bind(
|
||||
self.gs.PluginKey.ICON_SPACING,
|
||||
self,
|
||||
'icon_spacing',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
setting.bind(
|
||||
self.gs.PluginKey.ICON_PADDING,
|
||||
self,
|
||||
'icon_padding',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(self.gs.PluginKey.DISPLAY_TEXT, self,
|
||||
'display_text_enabled', Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(self.gs.PluginKey.ICON_AUTOMATIC, self,
|
||||
'icon_automatic', Gio.SettingsBindFlags.GET)
|
||||
|
||||
setting.bind(self.gs.PluginKey.DISPLAY_TEXT_POS, self,
|
||||
'display-text-pos', Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.connect("item-clicked", self.item_clicked_callback)
|
||||
self.connect("selection-changed", self.selectionchanged_callback)
|
||||
self.connect("item-activated", self.item_activated_callback)
|
||||
self.connect('notify::icon-spacing',
|
||||
self.on_notify_icon_spacing)
|
||||
self.connect('notify::icon-padding',
|
||||
self.on_notify_icon_padding)
|
||||
self.connect('notify::display-text-enabled',
|
||||
self._activate_markup)
|
||||
self.connect('notify::display-text-pos',
|
||||
self._activate_markup)
|
||||
self.connect("motion-notify-event", self.on_pointer_motion)
|
||||
|
||||
def get_view_icon_name(self):
|
||||
return "iconview.png"
|
||||
|
||||
def resize_icon(self, cover_size):
|
||||
'''
|
||||
Callback called when to resize the icon
|
||||
[common to all views]
|
||||
'''
|
||||
self.set_item_width(cover_size)
|
||||
|
||||
def on_drag_drop(self, widget, context, x, y, time):
|
||||
'''
|
||||
Callback called when a drag operation finishes over the cover view
|
||||
of the source. It decides if the dropped item can be processed as
|
||||
an image to use as a cover.
|
||||
'''
|
||||
|
||||
# stop the propagation of the signal (deactivates superclass callback)
|
||||
widget.stop_emission_by_name('drag-drop')
|
||||
|
||||
# obtain the path of the icon over which the drag operation finished
|
||||
path, pos = widget.get_dest_item_at_pos(x, y)
|
||||
result = path is not None
|
||||
|
||||
if result:
|
||||
target = self.drag_dest_find_target(context, None)
|
||||
widget.drag_get_data(context, target, time)
|
||||
|
||||
return result
|
||||
|
||||
def on_drag_data_received(self, widget, drag_context, x, y, data, info,
|
||||
time):
|
||||
'''
|
||||
Callback called when the drag source has prepared the data (pixbuf)
|
||||
for us to use.
|
||||
'''
|
||||
|
||||
# stop the propagation of the signal (deactivates superclass callback)
|
||||
widget.stop_emission_by_name('drag-data-received')
|
||||
|
||||
# get the album and the info and ask the loader to update the cover
|
||||
path, pos = widget.get_dest_item_at_pos(x, y)
|
||||
album = widget.get_model()[path][2]
|
||||
|
||||
pixbuf = data.get_pixbuf()
|
||||
|
||||
if pixbuf:
|
||||
self.album_manager.cover_man.update_cover(album, pixbuf)
|
||||
else:
|
||||
uri = data.get_text()
|
||||
self.album_manager.cover_man.update_cover(album, uri=uri)
|
||||
|
||||
# call the context drag_finished to inform the source about it
|
||||
drag_context.finish(True, False, time)
|
||||
|
||||
|
||||
def on_drag_data_get(self, widget, drag_context, data, info, time):
|
||||
'''
|
||||
Callback called when the drag destination (playlist) has
|
||||
requested what album (icon) has been dragged
|
||||
'''
|
||||
|
||||
uris = []
|
||||
for album in widget.get_selected_objects():
|
||||
for track in album.get_tracks():
|
||||
uris.append(track.location)
|
||||
|
||||
sel = data.set_uris(uris)
|
||||
# stop the propagation of the signal (deactivates superclass callback)
|
||||
widget.stop_emission_by_name('drag-data-get')
|
||||
|
||||
def on_drag_begin(self, widget, context):
|
||||
'''
|
||||
Callback called when the drag-drop from coverview has started
|
||||
Changes the drag icon as appropriate
|
||||
'''
|
||||
album_number = len(widget.get_selected_objects())
|
||||
|
||||
if album_number == 1:
|
||||
item = Gtk.STOCK_DND
|
||||
else:
|
||||
item = Gtk.STOCK_DND_MULTIPLE
|
||||
|
||||
widget.drag_source_set_icon_stock(item)
|
||||
widget.stop_emission_by_name('drag-begin')
|
||||
|
||||
def _cover_play_hotspot(self, path, in_vacinity=False):
|
||||
if path:
|
||||
valid, rect = self.get_cell_rect(path, None) # rect of widget coords
|
||||
|
||||
cursor_x, cursor_y = self.get_pointer() # returns widget coords
|
||||
c_x = cursor_x - rect.x - (self.icon_padding / 2) - (self.icon_spacing / 2)
|
||||
c_y = cursor_y - rect.y - (self.icon_padding / 2) - (self.icon_spacing / 2)
|
||||
|
||||
sizing = (rect.width / 2) if in_vacinity else 0
|
||||
|
||||
if c_x < (PLAY_SIZE_X + sizing) and \
|
||||
c_y < (PLAY_SIZE_Y + sizing) and \
|
||||
c_x > 0 and \
|
||||
c_y > 0:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def on_pointer_motion(self, widget, event):
|
||||
self._current_mouse_x = event.x
|
||||
self._current_mouse_y = event.y
|
||||
|
||||
if self._calc_motion_step == 0:
|
||||
self._calc_motion_step = 1
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 100,
|
||||
self._calculate_hotspot)
|
||||
else:
|
||||
path = self.get_path_at_pos(self._current_mouse_x,
|
||||
self._current_mouse_y)
|
||||
|
||||
if not self._last_path or self._last_path != path:
|
||||
self._display_icon(None, self._last_path)
|
||||
|
||||
def _display_icon(self, icon, path):
|
||||
self.props.cell_area.hover_pixbuf = icon
|
||||
if path:
|
||||
valid, rect = self.get_cell_rect(path, None)
|
||||
self.props.window.invalidate_rect(rect, True)
|
||||
|
||||
self.queue_draw()
|
||||
|
||||
def _calculate_hotspot(self, *args):
|
||||
|
||||
path = self.get_path_at_pos(self._current_mouse_x,
|
||||
self._current_mouse_y)
|
||||
|
||||
# if the current path was not the same as the last path then
|
||||
# reset the counter
|
||||
if not self._last_path or self._last_path != path:
|
||||
self._display_icon(None, self._last_path)
|
||||
self._last_path = path
|
||||
self._calc_motion_step = 0
|
||||
return False
|
||||
|
||||
self._calc_motion_step = self._calc_motion_step + 1
|
||||
|
||||
# if havent yet reached the requisite number of steps then
|
||||
# let the thread roll to the next increment
|
||||
if self._calc_motion_step < 8:
|
||||
return True
|
||||
|
||||
if not self._cover_play_hotspot(path, in_vacinity = True):
|
||||
# we are not near the hot-spot so decrement the counter
|
||||
# hoping next time around we are near
|
||||
self._calc_motion_step = self._calc_motion_step - 1
|
||||
self._display_icon(None, self._last_path)
|
||||
return True
|
||||
|
||||
# from here on in, we are going to display a hotspot icon
|
||||
# so lets decide which one
|
||||
|
||||
(_, playing) = self.shell.props.shell_player.get_playing()
|
||||
|
||||
calc_path = -1
|
||||
if playing:
|
||||
entry = self.shell.props.shell_player.get_playing_entry()
|
||||
album = self.album_manager.model.get_from_dbentry(entry)
|
||||
calc_path = self.album_manager.model.get_path(album)
|
||||
|
||||
if playing and calc_path == path:
|
||||
icon = 'button_playpause'
|
||||
elif playing:
|
||||
icon = 'button_queue'
|
||||
else:
|
||||
icon = 'button_play'
|
||||
|
||||
# now we've got the icon - lets double check that we are
|
||||
# actually hovering exactly on the hotspot because the icon will visually change
|
||||
|
||||
exact_hotspot = self._cover_play_hotspot(path)
|
||||
if exact_hotspot:
|
||||
icon = icon + '_hover'
|
||||
|
||||
hover = self.hover_pixbufs[icon]
|
||||
|
||||
self._display_icon(hover, path)
|
||||
self._calc_motion_step = self._calc_motion_step - 1
|
||||
|
||||
return True
|
||||
|
||||
def item_clicked_callback(self, iconview, event, path):
|
||||
'''
|
||||
Callback called when the user clicks somewhere on the cover_view.
|
||||
Along with source "show_hide_pane", takes care of showing/hiding the bottom
|
||||
pane after a second click on a selected album.
|
||||
'''
|
||||
|
||||
# first test if we've clicked on the cover-play icon
|
||||
if self._cover_play_hotspot(path):
|
||||
(_, playing) = self.shell.props.shell_player.get_playing()
|
||||
|
||||
# first see if anything is playing...
|
||||
if playing:
|
||||
entry = self.shell.props.shell_player.get_playing_entry()
|
||||
album = self.album_manager.model.get_from_dbentry(entry)
|
||||
|
||||
# if the current playing entry corresponds to the album
|
||||
# we are hovering over then we are requesting to pause
|
||||
if self.album_manager.model.get_from_path(path) == album:
|
||||
self._last_path = path
|
||||
self.shell.props.shell_player.pause()
|
||||
self.on_pointer_motion(self, event)
|
||||
return
|
||||
|
||||
# this must be a new album so we are asking just
|
||||
# to play this new album ... just need a short interval
|
||||
# for the selection event to kick in first
|
||||
def delay(*args):
|
||||
if playing: # if we are playing then queue up the next album
|
||||
self.source.queue_selected_album(None, self.source.favourites)
|
||||
album = self.get_selected_objects()[0]
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
message = gettext.gettext('Album has added to list of playing albums')
|
||||
self.display_notification(album.name,
|
||||
message,
|
||||
album.cover.original)
|
||||
else: # otherwise just play it
|
||||
self._last_path = path
|
||||
self.source.play_selected_album(self.source.favourites)
|
||||
|
||||
icon = 'button_play_hover'
|
||||
self.props.cell_area.hover_pixbuf = \
|
||||
self.hover_pixbufs[icon]
|
||||
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
delay, None)
|
||||
|
||||
return
|
||||
|
||||
# to expand the entry view
|
||||
ctrl = event.state & Gdk.ModifierType.CONTROL_MASK
|
||||
shift = event.state & Gdk.ModifierType.SHIFT_MASK
|
||||
|
||||
if self.icon_automatic:
|
||||
self.source.click_count += 1 if not ctrl and not shift else 0
|
||||
|
||||
if self.source.click_count == 1:
|
||||
album = self.album_manager.model.get_from_path(path) \
|
||||
if path else None
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
|
||||
self.source.show_hide_pane, album)
|
||||
|
||||
def item_activated_callback(self, iconview, path):
|
||||
'''
|
||||
Callback called when the cover view is double clicked or space-bar
|
||||
is pressed. It plays the selected album
|
||||
'''
|
||||
self.source.play_selected_album(self.source.favourites)
|
||||
|
||||
return True
|
||||
|
||||
def on_notify_icon_padding(self, *args):
|
||||
'''
|
||||
Callback called when the icon-padding gsetting value is changed
|
||||
'''
|
||||
self.set_item_padding(self.icon_padding)
|
||||
|
||||
def on_notify_icon_spacing(self, *args):
|
||||
'''
|
||||
Callback called when the icon-spacing gsetting value is changed
|
||||
'''
|
||||
self.set_row_spacing(self.icon_spacing)
|
||||
self.set_column_spacing(self.icon_spacing)
|
||||
|
||||
def _create_and_configure_renderer(self):
|
||||
#Add own cellrenderer
|
||||
self._text_renderer = Gtk.CellRendererText()
|
||||
|
||||
self._text_renderer.props.alignment = Pango.Alignment.CENTER
|
||||
self._text_renderer.props.wrap_mode = Pango.WrapMode.WORD
|
||||
self._text_renderer.props.xalign = 0.5
|
||||
self._text_renderer.props.yalign = 0
|
||||
self._text_renderer.props.width = \
|
||||
self.album_manager.cover_man.cover_size
|
||||
self._text_renderer.props.wrap_width = \
|
||||
self.album_manager.cover_man.cover_size
|
||||
|
||||
def _activate_markup(self, *args):
|
||||
'''
|
||||
Utility method to activate/deactivate the markup text on the
|
||||
cover view.
|
||||
'''
|
||||
if self.display_text_enabled and self.display_text_pos:
|
||||
if not self._text_renderer:
|
||||
# create and configure the custom cell renderer
|
||||
self._create_and_configure_renderer()
|
||||
|
||||
# set the renderer
|
||||
self.pack_end(self._text_renderer, False)
|
||||
self.add_attribute(self._text_renderer,
|
||||
'markup', AlbumsModel.columns['markup'])
|
||||
elif self._text_renderer:
|
||||
# remove the cell renderer
|
||||
self.props.cell_area.remove(self._text_renderer)
|
||||
|
||||
if self.display_text_enabled:
|
||||
self.set_tooltip_column(-1) # turnoff tooltips
|
||||
else:
|
||||
self.set_tooltip_column(AlbumsModel.columns['tooltip'])
|
||||
|
||||
def bottom_expander_expanded_callback(self, paned, expand):
|
||||
'''
|
||||
Callback connected to expanded signal of the paned GtkExpander
|
||||
'''
|
||||
if expand:
|
||||
# accommodate the viewport if there's an album selected
|
||||
if self.source.last_selected_album:
|
||||
def scroll_to_album(*args):
|
||||
# accommodate the viewport if there's an album selected
|
||||
path = self.album_manager.model.get_path(
|
||||
self.source.last_selected_album)
|
||||
|
||||
self.scroll_to_path(path, False, 0, 0)
|
||||
|
||||
return False
|
||||
|
||||
Gdk.threads_add_idle(GObject.PRIORITY_DEFAULT_IDLE,
|
||||
scroll_to_album, None)
|
||||
|
||||
|
||||
def switch_to_view(self, source, album):
|
||||
self.initialise(source)
|
||||
self.show_policy.initialise(source.album_manager)
|
||||
|
||||
self.scroll_to_album(album)
|
||||
|
||||
def grab_focus(self):
|
||||
super(EnhancedIconView, self).grab_focus()
|
||||
@@ -17,17 +17,399 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from gi.repository import RB
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import GdkPixbuf
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
import rb
|
||||
|
||||
from coverart_rb3compat import Menu
|
||||
from coverart_rb3compat import ActionGroup
|
||||
from coverart_browser_prefs import GSetting
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
from coverart_external_plugins import CreateExternalPluginMenu
|
||||
from coverart_playlists import LastFMTrackPlaylist
|
||||
from coverart_playlists import EchoNestPlaylist
|
||||
from coverart_playlists import EchoNestGenrePlaylist
|
||||
from coverart_utils import create_button_image
|
||||
from coverart_external_plugins import ExternalPlugin
|
||||
from stars import ReactiveStar
|
||||
from coverart_search import CoverSearchPane
|
||||
from coverart_widgets import PixbufButton
|
||||
|
||||
class CoverArtEntryView(RB.EntryView):
|
||||
|
||||
MIN_IMAGE_SIZE = 100
|
||||
|
||||
|
||||
class EntryViewPane(object):
|
||||
'''
|
||||
encapulates all of the Track Pane objects
|
||||
'''
|
||||
|
||||
def __init__(self, shell, plugin, source, entry_view_grid, viewmgr):
|
||||
self.gs = GSetting()
|
||||
|
||||
self.entry_view_grid = entry_view_grid
|
||||
self.shell = shell
|
||||
self.viewmgr = viewmgr
|
||||
self.plugin = plugin
|
||||
self.source = source
|
||||
|
||||
# setup entry-view objects and widgets
|
||||
self.stack = Gtk.Stack()
|
||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
||||
self.stack.set_transition_duration(750)
|
||||
|
||||
# create entry views. Don't allow to reorder until the load is finished
|
||||
self.entry_view_compact = CoverArtCompactEntryView(self.shell, self.source)
|
||||
self.entry_view_full = CoverArtEntryView(self.shell, self.source)
|
||||
self.entry_view = self.entry_view_compact
|
||||
self.shell.props.library_source.get_entry_view().set_columns_clickable(
|
||||
False)
|
||||
|
||||
self.entry_view_results = ResultsGrid()
|
||||
self.entry_view_results.initialise(self.entry_view_grid)
|
||||
|
||||
self.stack.add_titled(self.entry_view_results, "notebook_tracks", _("Tracks"))
|
||||
self.entry_view_grid.attach(self.stack, 0, 0, 3, 1)
|
||||
|
||||
def setup_source(self):
|
||||
|
||||
colour = self.viewmgr.get_selection_colour()
|
||||
self.cover_search_pane = CoverSearchPane(self.plugin, colour)
|
||||
|
||||
self.stack.add_titled(self.cover_search_pane, "notebook_covers", _("Covers"))
|
||||
|
||||
# define entry-view toolbar
|
||||
self.stars = ReactiveStar()
|
||||
self.stars.set_rating(0)
|
||||
self.stars.connect('changed', self.rating_changed_callback)
|
||||
self.stars.props.valign = Gtk.Align.CENTER
|
||||
self.entry_view_grid.attach(self.stars, 1, 1, 1, 1)
|
||||
stack_switcher = Gtk.StackSwitcher()
|
||||
stack_switcher.set_stack(self.stack)
|
||||
self.entry_view_grid.attach(stack_switcher, 0, 1, 1, 1)
|
||||
viewtoggle = PixbufButton()
|
||||
viewtoggle.set_image(create_button_image(self.plugin, "entryview.png"))
|
||||
self.viewtoggle_id = None
|
||||
|
||||
setting = self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
viewtoggle.set_active(not setting[self.gs.PluginKey.ENTRY_VIEW_MODE])
|
||||
self.entry_view_toggled(viewtoggle, True)
|
||||
viewtoggle.connect('toggled', self.entry_view_toggled)
|
||||
|
||||
smallwindowbutton = PixbufButton()
|
||||
smallwindowbutton.set_image(create_button_image(self.plugin, "view-restore.png"))
|
||||
smallwindowbutton.connect('toggled', self.smallwindowbutton_callback)
|
||||
|
||||
self.smallwindowext = ExternalPlugin()
|
||||
self.smallwindowext.appendattribute('plugin_name', 'smallwindow')
|
||||
self.smallwindowext.appendattribute('action_group_name', 'small window actions')
|
||||
self.smallwindowext.appendattribute('action_name', 'SmallWindow')
|
||||
self.smallwindowext.appendattribute('action_type', 'app')
|
||||
|
||||
whatsplayingtoggle = PixbufButton()
|
||||
whatsplayingtoggle.set_image(create_button_image(self.plugin, "whatsplaying.png"))
|
||||
whatsplayingtoggle.connect('toggled', self.whatsplayingtoggle_callback)
|
||||
|
||||
rightgrid = Gtk.Grid()
|
||||
rightgrid.props.halign = Gtk.Align.END
|
||||
|
||||
#rightgrid.attach(whatsplayingtoggle, 0, 0, 1, 1)
|
||||
rightgrid.attach(viewtoggle, 1, 0, 1, 1)
|
||||
rightgrid.attach(smallwindowbutton, 2, 0, 1, 1)
|
||||
|
||||
self.entry_view_grid.attach_next_to(rightgrid, self.stars, Gtk.PositionType.RIGHT, 1, 1)
|
||||
self.stack.set_visible_child(self.entry_view_results)
|
||||
self.stack.connect('notify::visible-child-name', self.notebook_switch_page_callback)
|
||||
|
||||
self.entry_view_grid.show_all()
|
||||
smallwindowbutton.set_visible(self.smallwindowext.is_activated())
|
||||
|
||||
def whatsplayingtoggle_callback(self, widget):
|
||||
self.entry_view_results.emit('whats-playing', widget.get_active())
|
||||
|
||||
|
||||
def smallwindowbutton_callback(self, widget):
|
||||
if widget.get_active():
|
||||
self.smallwindowext.activate(self.shell)
|
||||
widget.emit('clicked')
|
||||
|
||||
def entry_view_toggled(self, widget, initialised=False):
|
||||
print("DEBUG - entry_view_toggled")
|
||||
if widget.get_active():
|
||||
next_view = self.entry_view_full
|
||||
show_coverart = False
|
||||
if self.viewtoggle_id:
|
||||
self.shell.props.window.disconnect(self.viewtoggle_id)
|
||||
self.viewtoggle_id = None
|
||||
else:
|
||||
next_view = self.entry_view_compact
|
||||
show_coverart = True
|
||||
self.viewtoggle_id = self.shell.props.window.connect('check_resize', self.entry_view_results.window_resize)
|
||||
|
||||
setting = self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
setting[self.gs.PluginKey.ENTRY_VIEW_MODE] = not widget.get_active()
|
||||
|
||||
self.entry_view_results.change_view(next_view, show_coverart)
|
||||
self.entry_view = next_view
|
||||
if not initialised:
|
||||
self.source.update_with_selection()
|
||||
|
||||
def notebook_switch_page_callback(self, *args):
|
||||
'''
|
||||
Callback called when the notebook page gets switched. It initiates
|
||||
the cover search when the cover search pane's page is selected.
|
||||
'''
|
||||
print("CoverArtBrowser DEBUG - notebook_switch_page_callback")
|
||||
|
||||
if self.stack.get_visible_child_name() == 'notebook_covers':
|
||||
self.viewmgr.current_view.switch_to_coverpane(self.cover_search_pane)
|
||||
else:
|
||||
entries = self.entry_view.get_selected_entries()
|
||||
if entries and len(entries) > 0:
|
||||
self.entry_view_results.emit('update-cover', self.source, entries[0])
|
||||
else:
|
||||
selected = self.viewmgr.current_view.get_selected_objects()
|
||||
tracks = selected[0].get_tracks()
|
||||
self.entry_view_results.emit('update-cover', self.source, tracks[0].entry)
|
||||
|
||||
print("CoverArtBrowser DEBUG - end notebook_switch_page_callback")
|
||||
|
||||
def rating_changed_callback(self, widget):
|
||||
'''
|
||||
Callback called when the Rating stars is changed
|
||||
'''
|
||||
print("CoverArtBrowser DEBUG - rating_changed_callback")
|
||||
|
||||
rating = widget.get_rating()
|
||||
|
||||
for album in self.viewmgr.current_view.get_selected_objects():
|
||||
album.rating = rating
|
||||
|
||||
print("CoverArtBrowser DEBUG - end rating_changed_callback")
|
||||
|
||||
def get_entry_view(self):
|
||||
return self.entry_view
|
||||
|
||||
def update_cover(self, album_artist, manager):
|
||||
if not self.stack.get_visible_child_name() == "notebook_covers":
|
||||
return
|
||||
|
||||
self.cover_search_pane.clear()
|
||||
self.cover_search(album_artist, manager)
|
||||
|
||||
def cover_search(self, album_artist, manager):
|
||||
self.cover_search_pane.do_search(album_artist,
|
||||
manager.cover_man.update_cover)
|
||||
|
||||
def update_selection(self, last_selected_album, click_count):
|
||||
'''
|
||||
Update the source view when an item gets selected.
|
||||
'''
|
||||
print("DEBUG - update_with_selection")
|
||||
selected = self.viewmgr.current_view.get_selected_objects()
|
||||
|
||||
# clear the entry view
|
||||
self.entry_view.clear()
|
||||
|
||||
cover_search_pane_visible = self.stack.get_visible_child_name() == "notebook_covers"
|
||||
|
||||
if not selected:
|
||||
# clean cover tab if selected
|
||||
if cover_search_pane_visible:
|
||||
self.cover_search_pane.clear()
|
||||
|
||||
self.entry_view_results.emit('update-cover', self.source, None)
|
||||
return last_selected_album, click_count
|
||||
elif len(selected) == 1:
|
||||
self.stars.set_rating(selected[0].rating)
|
||||
|
||||
if selected[0] is not last_selected_album:
|
||||
# when the selection changes we've to take into account two
|
||||
# things
|
||||
if not click_count:
|
||||
# we may be using the arrows, so if there is no mouse
|
||||
# involved, we should change the last selected
|
||||
last_selected_album = selected[0]
|
||||
else:
|
||||
# we may've doing a fast change after a valid second click,
|
||||
# so it shouldn't be considered a double click
|
||||
click_count -= 1
|
||||
else:
|
||||
self.stars.set_rating(0)
|
||||
|
||||
if len(selected) == 1:
|
||||
self.source.artist_info.emit('selected',
|
||||
selected[0].artist,
|
||||
selected[0].name)
|
||||
|
||||
self.entry_view.set_sorting_order('track-number', Gtk.SortType.ASCENDING)
|
||||
|
||||
for album in selected:
|
||||
# add the album to the entry_view
|
||||
self.entry_view.add_album(album)
|
||||
|
||||
if len(selected) > 0:
|
||||
|
||||
def cover_update(*args):
|
||||
print ("emitting")
|
||||
self.entry_view_results.emit('update-cover',
|
||||
self.source,
|
||||
selected[0].get_tracks()[0].entry)
|
||||
|
||||
# add a short delay to give the entry-pane time to expand etc.
|
||||
Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250, cover_update, None)
|
||||
|
||||
# update the cover search pane with the first selected album
|
||||
if cover_search_pane_visible:
|
||||
self.cover_search_pane.do_search(selected[0],
|
||||
self.source.album_manager.cover_man.update_cover)
|
||||
|
||||
return last_selected_album, click_count
|
||||
|
||||
|
||||
class ResultsGrid(Gtk.Grid):
|
||||
# signals
|
||||
__gsignals__ = {
|
||||
'update-cover': (GObject.SIGNAL_RUN_LAST, None, (GObject.Object, RB.RhythmDBEntry)),
|
||||
'whats-playing': (GObject.SIGNAL_RUN_LAST, None, (bool,))
|
||||
}
|
||||
image_width = 0
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ResultsGrid, self).__init__(*args, **kwargs)
|
||||
|
||||
def initialise(self, entry_view_grid):
|
||||
self.pixbuf = None
|
||||
|
||||
self.entry_view_grid = entry_view_grid
|
||||
|
||||
self.oldval = 0
|
||||
self.stack = Gtk.Stack()
|
||||
self.stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
|
||||
self.stack.set_transition_duration(350)
|
||||
|
||||
self.image1 = Gtk.Image()
|
||||
self.image1.props.hexpand = True
|
||||
self.image1.props.vexpand = True
|
||||
self.stack.add_named(self.image1, "image1")
|
||||
|
||||
self.image2 = Gtk.Image()
|
||||
self.image2.props.hexpand = True
|
||||
self.image2.props.vexpand = True
|
||||
self.stack.add_named(self.image2, "image2")
|
||||
|
||||
self.frame = Gtk.Frame.new() #"", 0.5, 0.5, 1, False)
|
||||
self.update_cover(None, None, None)
|
||||
self.scroll = Gtk.ScrolledWindow()
|
||||
self.scroll.add(self.stack)
|
||||
self.scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
||||
|
||||
self.scroll.set_resize_mode(Gtk.ResizeMode.QUEUE)
|
||||
|
||||
self.frame.add(self.scroll)
|
||||
self._signal_connected = None
|
||||
|
||||
self.attach(self.frame, 6, 0, 1, 1)
|
||||
self.connect('update-cover', self.update_cover)
|
||||
self.connect('whats-playing', self.display_whats_playing)
|
||||
|
||||
#lets fix the situation where some-themes background colour is incorrectly defined
|
||||
#in these cases the background colour is black
|
||||
context = self.get_style_context()
|
||||
bg_colour = context.get_background_color(Gtk.StateFlags.NORMAL)
|
||||
if bg_colour == Gdk.RGBA(0, 0, 0, 0):
|
||||
color = context.get_color(Gtk.StateFlags.NORMAL)
|
||||
self.override_background_color(Gtk.StateType.NORMAL, color)
|
||||
|
||||
def update_cover(self, widget, source, entry):
|
||||
|
||||
print ('update_cover')
|
||||
self.oldval = 0 # force a redraw
|
||||
if entry:
|
||||
print ('entry')
|
||||
album = source.album_manager.model.get_from_dbentry(entry)
|
||||
self.pixbuf = GdkPixbuf.Pixbuf().new_from_file(album.cover.original)
|
||||
self.window_resize(None)
|
||||
self.frame.set_shadow_type(Gtk.ShadowType.NONE)
|
||||
else:
|
||||
print ('no pixbuf')
|
||||
self.pixbuf = None
|
||||
self.frame.set_shadow_type(Gtk.ShadowType.ETCHED_OUT)
|
||||
|
||||
if self.stack.get_visible_child_name() == "image1":
|
||||
self.image1.queue_draw()
|
||||
else:
|
||||
self.image2.queue_draw()
|
||||
|
||||
def display_whats_playing(self, show_playing):
|
||||
view = self.get_child_at(0, 0)
|
||||
|
||||
view.display_playing_tracks(show_playing)
|
||||
|
||||
def window_resize(self, widget):
|
||||
alloc = self.get_allocation()
|
||||
if alloc.height < 10:
|
||||
return
|
||||
|
||||
entry_grid_alloc = self.entry_view_grid.get_allocation()
|
||||
|
||||
if (alloc.width / 3) <= (MIN_IMAGE_SIZE + 30) or \
|
||||
(entry_grid_alloc.height) <= (MIN_IMAGE_SIZE + 30):
|
||||
self.frame.props.visible = False
|
||||
return
|
||||
else:
|
||||
self.frame.props.visible = True
|
||||
vbar = self.scroll.get_vscrollbar()
|
||||
vbar.set_visible(False)
|
||||
hbar = self.scroll.get_hscrollbar()
|
||||
hbar.set_visible(False)
|
||||
|
||||
minval = min((alloc.width / 3), alloc.height)
|
||||
if self.oldval == minval:
|
||||
return
|
||||
self.oldval = minval
|
||||
if minval < MIN_IMAGE_SIZE:
|
||||
minval = MIN_IMAGE_SIZE
|
||||
|
||||
if self.pixbuf:
|
||||
p = self.pixbuf.scale_simple(minval, minval, GdkPixbuf.InterpType.BILINEAR)
|
||||
else:
|
||||
p = None
|
||||
|
||||
if self.stack.get_visible_child_name() == "image1":
|
||||
self.image2.set_from_pixbuf(p)
|
||||
self.stack.set_visible_child_name("image2")
|
||||
else:
|
||||
self.image1.set_from_pixbuf(p)
|
||||
self.stack.set_visible_child_name("image1")
|
||||
|
||||
def change_view(self, entry_view, show_coverart):
|
||||
print("debug - change_view")
|
||||
widget = self.get_child_at(0, 0)
|
||||
if widget:
|
||||
self.remove(widget)
|
||||
|
||||
if not show_coverart:
|
||||
widget = self.get_child_at(6, 0)
|
||||
if widget:
|
||||
self.remove(widget)
|
||||
|
||||
entry_view.props.hexpand = True
|
||||
entry_view.props.vexpand = True
|
||||
self.attach(entry_view, 0, 0, 3, 1)
|
||||
|
||||
if show_coverart:
|
||||
self.attach(self.frame, 6, 0, 1, 1)
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
class BaseView(RB.EntryView):
|
||||
|
||||
def __init__(self, shell, source):
|
||||
'''
|
||||
@@ -38,93 +420,79 @@ class CoverArtEntryView(RB.EntryView):
|
||||
self.plugin = self.source.props.plugin
|
||||
|
||||
super(RB.EntryView, self).__init__(db=shell.props.db,
|
||||
shell_player=shell.props.shell_player, is_drag_source=True,
|
||||
visible_columns=[])
|
||||
shell_player=shell.props.shell_player, is_drag_source=True,
|
||||
visible_columns=[])
|
||||
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.RB)
|
||||
|
||||
self.append_column(RB.EntryViewColumn.TRACK_NUMBER, False)
|
||||
self.append_column(RB.EntryViewColumn.TITLE, True) # always shown
|
||||
self.append_column(RB.EntryViewColumn.GENRE, False)
|
||||
self.append_column(RB.EntryViewColumn.ARTIST, False)
|
||||
self.append_column(RB.EntryViewColumn.ALBUM, False)
|
||||
self.append_column(RB.EntryViewColumn.DURATION, False)
|
||||
self.append_column(RB.EntryViewColumn.COMMENT, False)
|
||||
self.append_column(RB.EntryViewColumn.RATING, False)
|
||||
self.append_column(RB.EntryViewColumn.QUALITY, False)
|
||||
self.append_column(RB.EntryViewColumn.PLAY_COUNT, False)
|
||||
self.append_column(RB.EntryViewColumn.LAST_PLAYED, False)
|
||||
self.append_column(RB.EntryViewColumn.YEAR, False)
|
||||
self.append_column(RB.EntryViewColumn.FIRST_SEEN, False)
|
||||
self.append_column(RB.EntryViewColumn.LOCATION, False)
|
||||
self.append_column(RB.EntryViewColumn.BPM, False)
|
||||
self.display_columns()
|
||||
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
# UI elements need to be imported.
|
||||
ui = Gtk.Builder()
|
||||
ui.set_translation_domain(cl.Locale.LOCALE_DOMAIN)
|
||||
ui.add_from_file(rb.find_plugin_file(self.plugin,
|
||||
'ui/coverart_entryview.ui'))
|
||||
ui.connect_signals(self)
|
||||
|
||||
self.popup_menu = ui.get_object('entryview_popup_menu')
|
||||
self.define_menu()
|
||||
|
||||
# connect signals to the shell to know when the playing state changes
|
||||
self.shell.props.shell_player.connect('playing-song-changed',
|
||||
self.playing_song_changed)
|
||||
self.playing_song_changed)
|
||||
self.shell.props.shell_player.connect('playing-changed',
|
||||
self.playing_changed)
|
||||
self.playing_changed)
|
||||
|
||||
self.playlist_sub_menu_item = ui.get_object('playlist_sub_menu_item')
|
||||
self.actiongroup = Gtk.ActionGroup('coverentryplaylist_submenu')
|
||||
uim = self.shell.props.ui_manager
|
||||
uim.insert_action_group(self.actiongroup)
|
||||
self.actiongroup = ActionGroup(self.shell, 'coverentryplaylist_submenu')
|
||||
|
||||
self.external_plugins = \
|
||||
CreateExternalPluginMenu("ca_entryview", self.shell)
|
||||
|
||||
# connect the visible-columns global setting to update our entryview
|
||||
gs = GSetting()
|
||||
rhythm_settings = gs.get_setting(gs.Path.RBSOURCE)
|
||||
rhythm_settings.connect('changed::visible-columns',
|
||||
self.on_visible_columns_changed)
|
||||
self.on_visible_columns_changed(rhythm_settings, 'visible-columns')
|
||||
self.external_plugins = None
|
||||
|
||||
self.source_query_model = self.source.source_query_model # RB.RhythmDBQueryModel.new_empty(self.shell.props.db)
|
||||
self.qm = RB.RhythmDBQueryModel.new_empty(self.shell.props.db)
|
||||
self.set_model(self.qm)
|
||||
|
||||
# connect the sort-order to the library source sort
|
||||
library_view = self.shell.props.library_source.get_entry_view()
|
||||
library_view.connect('notify::sort-order',
|
||||
self._on_library_sorting_changed)
|
||||
self._on_library_sorting_changed(library_view,
|
||||
library_view.props.sort_order)
|
||||
self.connect_library_signals()
|
||||
self.echonest_similar_playlist = None
|
||||
self.echonest_similar_genre_playlist = None
|
||||
self.lastfm_similar_playlist = None
|
||||
|
||||
# connect to the sort-order property
|
||||
self.connect('notify::sort-order', self._notify_sort_order,
|
||||
library_view)
|
||||
self.connect('selection-changed', self.selection_changed)
|
||||
|
||||
self.artists = ""
|
||||
|
||||
print ("end constructor")
|
||||
|
||||
def __del__(self):
|
||||
uim = self.shell.props.ui_manager
|
||||
|
||||
uim.remove_action_group(self.action_group)
|
||||
uim.remove_ui(self.ui_id)
|
||||
uim.ensure_update()
|
||||
|
||||
del self.action_group
|
||||
del self.play_action
|
||||
del self.queue_action
|
||||
|
||||
def on_visible_columns_changed(self, settings, key):
|
||||
print "CoverArtBrowser DEBUG - on_visible_columns_changed()"
|
||||
# reset current columns
|
||||
self.props.visible_columns = settings[key]
|
||||
print "CoverArtBrowser DEBUG - end on_visible_columns_changed()"
|
||||
def connect_library_signals(self):
|
||||
# connect the sort-order to the library source sort
|
||||
library_view = self.shell.props.library_source.get_entry_view()
|
||||
library_view.connect('notify::sort-order',
|
||||
self._on_library_sorting_changed)
|
||||
self._on_library_sorting_changed(library_view,
|
||||
library_view.props.sort_order)
|
||||
|
||||
# connect to the sort-order property
|
||||
self.connect('notify::sort-order', self._notify_sort_order,
|
||||
library_view)
|
||||
|
||||
self.set_columns_clickable(False)
|
||||
|
||||
|
||||
def display_playing_tracks(self, show_playing):
|
||||
pass
|
||||
|
||||
def define_menu(self):
|
||||
pass
|
||||
|
||||
def display_columns(self):
|
||||
pass
|
||||
|
||||
def selection_changed(self, entry_view):
|
||||
entries = entry_view.get_selected_entries()
|
||||
if entries and len(entries) > 0:
|
||||
self.source.entryviewpane.entry_view_results.emit('update-cover', self.source, entries[0])
|
||||
|
||||
def add_album(self, album):
|
||||
print "CoverArtBrowser DEBUG - add_album()"
|
||||
print("CoverArtBrowser DEBUG - add_album()")
|
||||
tracks = album.get_tracks()
|
||||
|
||||
for track in tracks:
|
||||
@@ -132,69 +500,125 @@ class CoverArtEntryView(RB.EntryView):
|
||||
|
||||
(_, playing) = self.shell.props.shell_player.get_playing()
|
||||
self.playing_changed(self.shell.props.shell_player, playing)
|
||||
print "CoverArtBrowser DEBUG - add_album()"
|
||||
|
||||
artists = album.artists.split(', ')
|
||||
if self.artists == "":
|
||||
self.artists = artists
|
||||
else:
|
||||
self.artists = list(set(self.artists + artists))
|
||||
|
||||
print("CoverArtBrowser DEBUG - add_album()")
|
||||
|
||||
def clear(self):
|
||||
print "CoverArtBrowser DEBUG - clear()"
|
||||
# self.set_model(RB.RhythmDBQueryModel.new_empty(self.shell.props.db))
|
||||
print("CoverArtBrowser DEBUG - clear()")
|
||||
|
||||
for row in self.qm:
|
||||
self.qm.remove_entry(row[0])
|
||||
|
||||
print "CoverArtBrowser DEBUG - clear()"
|
||||
self.artists = ""
|
||||
|
||||
print("CoverArtBrowser DEBUG - clear()")
|
||||
|
||||
def do_entry_activated(self, entry):
|
||||
print "CoverArtBrowser DEBUG - do_entry_activated()"
|
||||
print("CoverArtBrowser DEBUG - do_entry_activated()")
|
||||
self.select_entry(entry)
|
||||
self.play_track_menu_item_callback(entry)
|
||||
print "CoverArtBrowser DEBUG - do_entry_activated()"
|
||||
print("CoverArtBrowser DEBUG - do_entry_activated()")
|
||||
return True
|
||||
|
||||
def pre_popup_menu_callback(self, *args):
|
||||
pass
|
||||
|
||||
def do_show_popup(self, over_entry):
|
||||
if over_entry:
|
||||
print "CoverArtBrowser DEBUG - do_show_popup()"
|
||||
self.external_plugins.create_menu(self.popup_menu, 3)
|
||||
self.popup_menu.popup(None, None, None, None, 0,
|
||||
Gtk.get_current_event_time())
|
||||
print("CoverArtBrowser DEBUG - do_show_popup()")
|
||||
|
||||
self.popup.popup(self.source,
|
||||
'entryview_popup_menu', 0, Gtk.get_current_event_time())
|
||||
|
||||
return over_entry
|
||||
|
||||
def play_track_menu_item_callback(self, _):
|
||||
print "CoverArtBrowser DEBUG - play_track_menu_item_callback()"
|
||||
|
||||
query_model = RB.RhythmDBQueryModel.new_empty(self.shell.props.db)
|
||||
def play_similar_artist_menu_item_callback(self, *args):
|
||||
if not self.echonest_similar_playlist:
|
||||
self.echonest_similar_playlist = \
|
||||
EchoNestPlaylist(self.shell,
|
||||
self.shell.props.queue_source)
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
entry = selected[0]
|
||||
|
||||
self.echonest_similar_playlist.start(entry, reinitialise=True)
|
||||
|
||||
def play_similar_genre_menu_item_callback(self, *args):
|
||||
if not self.echonest_similar_genre_playlist:
|
||||
self.echonest_similar_genre_playlist = \
|
||||
EchoNestGenrePlaylist(self.shell,
|
||||
self.shell.props.queue_source)
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
entry = selected[0]
|
||||
self.echonest_similar_genre_playlist.start(entry, reinitialise=True)
|
||||
|
||||
def play_similar_track_menu_item_callback(self, *args):
|
||||
if not self.lastfm_similar_playlist:
|
||||
self.lastfm_similar_playlist = \
|
||||
LastFMTrackPlaylist(self.shell,
|
||||
self.shell.props.queue_source)
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
entry = selected[0]
|
||||
self.lastfm_similar_playlist.start(entry, reinitialise=True)
|
||||
|
||||
|
||||
def play_track_menu_item_callback(self, *args):
|
||||
print("CoverArtBrowser DEBUG - play_track_menu_item_callback()")
|
||||
|
||||
for row in self.source_query_model:
|
||||
self.source_query_model.remove_entry(row[0])
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
entry = selected[0]
|
||||
|
||||
if len(selected) == 1:
|
||||
query_model.copy_contents(self.qm)
|
||||
self.source_query_model.copy_contents(self.qm)
|
||||
else:
|
||||
self.add_tracks_to_source(query_model)
|
||||
|
||||
self.source.props.query_model = query_model
|
||||
self.add_tracks_to_source(self.source_query_model)
|
||||
|
||||
self.source.props.query_model = self.source_query_model
|
||||
|
||||
#library_view = self.shell.props.library_source.get_entry_view()
|
||||
#library_view.set_sorting_order('track-number', Gtk.SortType.ASCENDING)
|
||||
#self.set_sorting_order('track-number', Gtk.SortType.ASCENDING)
|
||||
|
||||
# Start the music
|
||||
player = self.shell.props.shell_player
|
||||
player.play_entry(entry, self.source)
|
||||
|
||||
print "CoverArtBrowser DEBUG - play_track_menu_item_callback()"
|
||||
print("CoverArtBrowser DEBUG - play_track_menu_item_callback()")
|
||||
|
||||
def queue_track_menu_item_callback(self, entry):
|
||||
print "CoverArtBrowser DEBUG - queue_track_menu_item_callback()"
|
||||
def queue_track_menu_item_callback(self, *args):
|
||||
print("CoverArtBrowser DEBUG - queue_track_menu_item_callback()")
|
||||
|
||||
self.add_tracks_to_source(self.shell.props.queue_source)
|
||||
|
||||
def add_to_playing_menu_item_callback(self, *args):
|
||||
print("CoverArtBrowser DEBUG - add_to_playing_menu_item_callback()")
|
||||
self.add_tracks_to_source(None)
|
||||
|
||||
def add_tracks_to_source(self, source):
|
||||
|
||||
if source == None:
|
||||
source = self.source_query_model
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
selected.reverse()
|
||||
|
||||
selected = sorted(selected,
|
||||
key=lambda song: song.get_ulong(RB.RhythmDBPropType.TRACK_NUMBER))
|
||||
key=lambda song: song.get_ulong(RB.RhythmDBPropType.TRACK_NUMBER))
|
||||
|
||||
for entry in selected:
|
||||
source.add_entry(entry, -1)
|
||||
|
||||
print "CoverArtBrowser DEBUG - queue_track_menu_item_callback()"
|
||||
print("CoverArtBrowser DEBUG - queue_track_menu_item_callback()")
|
||||
|
||||
def love_track(self, rating):
|
||||
'''
|
||||
@@ -204,31 +628,30 @@ class CoverArtEntryView(RB.EntryView):
|
||||
|
||||
for entry in selected:
|
||||
self.shell.props.db.entry_set(entry, RB.RhythmDBPropType.RATING,
|
||||
rating)
|
||||
rating)
|
||||
|
||||
self.shell.props.db.commit()
|
||||
|
||||
def show_properties_menu_item_callback(self, entry):
|
||||
print "CoverArtBrowser DEBUG - show_properties_menu_item_callback()"
|
||||
def show_properties_menu_item_callback(self, *args):
|
||||
print("CoverArtBrowser DEBUG - show_properties_menu_item_callback()")
|
||||
|
||||
info_dialog = RB.SongInfo(source=self.source, entry_view=self)
|
||||
|
||||
info_dialog.show_all()
|
||||
|
||||
print "CoverArtBrowser DEBUG - show_properties_menu_item_callback()"
|
||||
print("CoverArtBrowser DEBUG - show_properties_menu_item_callback()")
|
||||
|
||||
def playing_song_changed(self, shell_player, entry):
|
||||
print "CoverArtBrowser DEBUG - playing_song_changed()"
|
||||
print("CoverArtBrowser DEBUG - playing_song_changed()")
|
||||
|
||||
if entry is not None and self.get_entry_contained(entry):
|
||||
self.set_state(RB.EntryViewState.PLAYING)
|
||||
else:
|
||||
self.set_state(RB.EntryViewState.NOT_PLAYING)
|
||||
|
||||
print "CoverArtBrowser DEBUG - playing_song_changed()"
|
||||
print("CoverArtBrowser DEBUG - playing_song_changed()")
|
||||
|
||||
def playing_changed(self, shell_player, playing):
|
||||
print "CoverArtBrowser DEBUG - playing_changed()"
|
||||
print("CoverArtBrowser DEBUG - playing_changed()")
|
||||
entry = shell_player.get_playing_entry()
|
||||
|
||||
if entry is not None and self.get_entry_contained(entry):
|
||||
@@ -239,25 +662,23 @@ class CoverArtEntryView(RB.EntryView):
|
||||
else:
|
||||
self.set_state(RB.EntryViewState.NOT_PLAYING)
|
||||
|
||||
print "CoverArtBrowser DEBUG - playing_changed()"
|
||||
print("CoverArtBrowser DEBUG - playing_changed()")
|
||||
|
||||
def add_playlist_menu_item_callback(self, menu_item):
|
||||
print "CoverArtBrowser DEBUG - add_playlist_menu_item_callback"
|
||||
def add_playlist_menu_item_callback(self, *args):
|
||||
print("CoverArtBrowser DEBUG - add_playlist_menu_item_callback")
|
||||
playlist_manager = self.shell.props.playlist_manager
|
||||
playlist = playlist_manager.new_playlist('', False)
|
||||
playlist = playlist_manager.new_playlist(_('New Playlist'), False)
|
||||
|
||||
self.add_tracks_to_source(playlist)
|
||||
|
||||
def playlist_menu_item_callback(self, menu_item):
|
||||
print "CoverArtBrowser DEBUG - playlist_menu_item_callback"
|
||||
def playlist_menu_item_callback(self, *args):
|
||||
pass
|
||||
|
||||
self.source.playlist_fillmenu(self.playlist_sub_menu_item,
|
||||
self.actiongroup, self.add_to_static_playlist_menu_item_callback)
|
||||
def add_to_static_playlist_menu_item_callback(self, action, param, args):
|
||||
print("CoverArtBrowser DEBUG - " + \
|
||||
"add_to_static_playlist_menu_item_callback")
|
||||
|
||||
def add_to_static_playlist_menu_item_callback(self, action, playlist,
|
||||
favourite):
|
||||
print "CoverArtBrowser DEBUG - " + \
|
||||
"add_to_static_playlist_menu_item_callback"
|
||||
playlist = args['playlist']
|
||||
self.add_tracks_to_source(playlist)
|
||||
|
||||
def _on_library_sorting_changed(self, view, _):
|
||||
@@ -272,4 +693,179 @@ class CoverArtEntryView(RB.EntryView):
|
||||
# update library source's view direction
|
||||
library_view.set_sorting_type(self.props.sort_order)
|
||||
|
||||
|
||||
class CoverArtCompactEntryView(BaseView):
|
||||
__hash__ = GObject.__hash__
|
||||
|
||||
def __init__(self, shell, source):
|
||||
'''
|
||||
Initializes the entryview.
|
||||
'''
|
||||
super(CoverArtCompactEntryView, self).__init__(shell, source)
|
||||
|
||||
def display_columns(self):
|
||||
|
||||
self.col_map = OrderedDict([
|
||||
('track-number', RB.EntryViewColumn.TRACK_NUMBER),
|
||||
('title', RB.EntryViewColumn.TITLE),
|
||||
('artist', RB.EntryViewColumn.ARTIST),
|
||||
('rating', RB.EntryViewColumn.RATING),
|
||||
('duration', RB.EntryViewColumn.DURATION)
|
||||
])
|
||||
|
||||
for entry in self.col_map:
|
||||
visible = False if entry == 'artist' else True
|
||||
self.append_column(self.col_map[entry], visible)
|
||||
|
||||
def add_album(self, album):
|
||||
super(CoverArtCompactEntryView, self).add_album(album)
|
||||
|
||||
if len(self.artists) > 1:
|
||||
self.get_column(RB.EntryViewColumn.ARTIST).set_visible(True)
|
||||
else:
|
||||
self.get_column(RB.EntryViewColumn.ARTIST).set_visible(False)
|
||||
|
||||
def define_menu(self):
|
||||
popup = Menu(self.plugin, self.shell)
|
||||
popup.load_from_file('N/A',
|
||||
'ui/coverart_entryview_compact_pop_rb3.ui')
|
||||
signals = {
|
||||
'ev_compact_play_track_menu_item': self.play_track_menu_item_callback,
|
||||
'ev_compact_queue_track_menu_item': self.queue_track_menu_item_callback,
|
||||
'ev_compact_add_to_playing_menu_item': self.add_to_playing_menu_item_callback,
|
||||
'ev_compact_new_playlist': self.add_playlist_menu_item_callback,
|
||||
'ev_compact_show_properties_menu_item': self.show_properties_menu_item_callback,
|
||||
'ev_compact_similar_track_menu_item': self.play_similar_track_menu_item_callback,
|
||||
'ev_compact_similar_artist_menu_item': self.play_similar_artist_menu_item_callback,
|
||||
'ev_compact_similar_genre_menu_item': self.play_similar_genre_menu_item_callback}
|
||||
|
||||
popup.connect_signals(signals)
|
||||
popup.connect('pre-popup', self.pre_popup_menu_callback)
|
||||
self.popup = popup
|
||||
|
||||
def playlist_menu_item_callback(self, *args):
|
||||
print("CoverArtBrowser DEBUG - playlist_menu_item_callback")
|
||||
|
||||
self.source.playlist_fillmenu(self.popup, 'ev_compact_playlist_sub_menu_item', 'ev_compact_playlist_section',
|
||||
self.actiongroup, self.add_to_static_playlist_menu_item_callback)
|
||||
|
||||
def pre_popup_menu_callback(self, *args):
|
||||
'''
|
||||
Callback when the popup menu is about to be displayed
|
||||
'''
|
||||
|
||||
state, sensitive = self.shell.props.shell_player.get_playing()
|
||||
if not state:
|
||||
sensitive = False
|
||||
|
||||
self.popup.set_sensitive('ev_compact_add_to_playing_menu_item', sensitive)
|
||||
|
||||
if not self.external_plugins:
|
||||
self.external_plugins = \
|
||||
CreateExternalPluginMenu("ev_compact_entryview", 5, self.popup)
|
||||
self.external_plugins.create_menu('entryview_compact_popup_menu')
|
||||
|
||||
self.playlist_menu_item_callback()
|
||||
|
||||
|
||||
class CoverArtEntryView(BaseView):
|
||||
__hash__ = GObject.__hash__
|
||||
|
||||
def __init__(self, shell, source):
|
||||
'''
|
||||
Initializes the entryview.
|
||||
'''
|
||||
super(CoverArtEntryView, self).__init__(shell, source)
|
||||
|
||||
def display_columns(self):
|
||||
|
||||
self.col_map = OrderedDict([
|
||||
('track-number', RB.EntryViewColumn.TRACK_NUMBER),
|
||||
('title', RB.EntryViewColumn.TITLE),
|
||||
('genre', RB.EntryViewColumn.GENRE),
|
||||
('artist', RB.EntryViewColumn.ARTIST),
|
||||
('album', RB.EntryViewColumn.ALBUM),
|
||||
('composer', RB.EntryViewColumn.COMPOSER),
|
||||
('date', RB.EntryViewColumn.YEAR),
|
||||
('duration', RB.EntryViewColumn.DURATION),
|
||||
('bitrate', RB.EntryViewColumn.QUALITY),
|
||||
('play-count', RB.EntryViewColumn.PLAY_COUNT),
|
||||
('beats-per-minute', RB.EntryViewColumn.BPM),
|
||||
('comment', RB.EntryViewColumn.COMMENT),
|
||||
('location', RB.EntryViewColumn.LOCATION),
|
||||
('rating', RB.EntryViewColumn.RATING),
|
||||
('last-played', RB.EntryViewColumn.LAST_PLAYED),
|
||||
('first-seen', RB.EntryViewColumn.FIRST_SEEN)
|
||||
])
|
||||
|
||||
for entry in self.col_map:
|
||||
visible = True if entry == 'title' else False
|
||||
self.append_column(self.col_map[entry], visible)
|
||||
|
||||
# connect the visible-columns global setting to update our entryview
|
||||
gs = GSetting()
|
||||
rhythm_settings = gs.get_setting(gs.Path.RBSOURCE)
|
||||
rhythm_settings.connect('changed::visible-columns',
|
||||
self.on_visible_columns_changed)
|
||||
self.on_visible_columns_changed(rhythm_settings, 'visible-columns')
|
||||
|
||||
def on_visible_columns_changed(self, settings, key):
|
||||
print("CoverArtBrowser DEBUG - on_visible_columns_changed()")
|
||||
# reset current columns
|
||||
print("CoverArtBrowser DEBUG - end on_visible_columns_changed()")
|
||||
for entry in self.col_map:
|
||||
col = self.get_column(self.col_map[entry])
|
||||
if entry in settings[key]:
|
||||
col.set_visible(True)
|
||||
else:
|
||||
if entry != 'title':
|
||||
col.set_visible(False)
|
||||
|
||||
print("CoverArtBrowser DEBUG - end on_visible_columns_changed()")
|
||||
|
||||
def define_menu(self):
|
||||
popup = Menu(self.plugin, self.shell)
|
||||
popup.load_from_file('N/A',
|
||||
'ui/coverart_entryview_full_pop_rb3.ui')
|
||||
signals = {
|
||||
'ev_full_play_track_menu_item': self.play_track_menu_item_callback,
|
||||
'ev_full_queue_track_menu_item': self.queue_track_menu_item_callback,
|
||||
'ev_full_add_to_playing_menu_item': self.add_to_playing_menu_item_callback,
|
||||
'ev_full_new_playlist': self.add_playlist_menu_item_callback,
|
||||
'ev_full_show_properties_menu_item': self.show_properties_menu_item_callback,
|
||||
'ev_full_similar_track_menu_item': self.play_similar_track_menu_item_callback,
|
||||
'ev_full_similar_artist_menu_item': self.play_similar_artist_menu_item_callback,
|
||||
'ev_full_similar_genre_menu_item': self.play_similar_genre_menu_item_callback}
|
||||
|
||||
popup.connect_signals(signals)
|
||||
popup.connect('pre-popup', self.pre_popup_menu_callback)
|
||||
self.popup = popup
|
||||
|
||||
def playlist_menu_item_callback(self, *args):
|
||||
print("CoverArtBrowser DEBUG - playlist_menu_item_callback")
|
||||
|
||||
self.source.playlist_fillmenu(self.popup, 'ev_full_playlist_sub_menu_item', 'ev_full_playlist_section',
|
||||
self.actiongroup, self.add_to_static_playlist_menu_item_callback)
|
||||
|
||||
def pre_popup_menu_callback(self, *args):
|
||||
'''
|
||||
Callback when the popup menu is about to be displayed
|
||||
'''
|
||||
|
||||
state, sensitive = self.shell.props.shell_player.get_playing()
|
||||
if not state:
|
||||
sensitive = False
|
||||
|
||||
self.popup.set_sensitive('ev_full_add_to_playing_menu_item', sensitive)
|
||||
|
||||
if not self.external_plugins:
|
||||
self.external_plugins = \
|
||||
CreateExternalPluginMenu("ev_full_entryview", 5, self.popup)
|
||||
self.external_plugins.create_menu('entryview_full_popup_menu')
|
||||
|
||||
self.playlist_menu_item_callback()
|
||||
|
||||
|
||||
GObject.type_register(CoverArtEntryView)
|
||||
GObject.type_register(CoverArtCompactEntryView)
|
||||
|
||||
|
||||
@@ -17,69 +17,87 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import shutil
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import RB
|
||||
from gi.repository import Gdk
|
||||
from coverart_album import Album
|
||||
from gi.repository import Peas
|
||||
from gi.repository import Gst
|
||||
|
||||
from coverart_utils import NaturalString
|
||||
import rb
|
||||
import shutil
|
||||
import urllib
|
||||
import os.path
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import coverart_rb3compat as rb3compat
|
||||
|
||||
|
||||
class CoverArtExport(GObject.Object):
|
||||
'''
|
||||
This class provides for various export routines
|
||||
|
||||
'''
|
||||
TARGET_BITRATE = 128
|
||||
|
||||
def __init__(self, plugin, shell, album_manager):
|
||||
self.plugin = plugin
|
||||
self.shell = shell
|
||||
self.album_manager = album_manager
|
||||
|
||||
|
||||
self._gstreamer_has_initialised = False
|
||||
|
||||
def is_search_plugin_enabled(self):
|
||||
# very dirty hack - lets tidy this correctly for v0.9
|
||||
|
||||
try:
|
||||
from coverart_search_tracks import CoverArtTracks
|
||||
except:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
peas = Peas.Engine.get_default()
|
||||
loaded_plugins = peas.get_loaded_plugins()
|
||||
|
||||
result = False
|
||||
if 'coverart_search_providers' in loaded_plugins:
|
||||
info = peas.get_plugin_info('coverart_search_providers')
|
||||
version = info.get_version()
|
||||
|
||||
if NaturalString(version) >= "0.9":
|
||||
result = True
|
||||
|
||||
return result
|
||||
|
||||
def embed_albums(self, selected_albums):
|
||||
'''
|
||||
method to create the menu items for all supported plugins
|
||||
|
||||
:selected_albums: `Album` - array of albums
|
||||
|
||||
'''
|
||||
# temporarily move this import to here for v0.8
|
||||
# need to separate the two plugins correctly for v0.9
|
||||
|
||||
self._initialise_gstreamer()
|
||||
|
||||
from coverart_search_tracks import CoverArtTracks
|
||||
|
||||
|
||||
search_tracks = CoverArtTracks()
|
||||
playlist_manager = self.shell.props.playlist_manager
|
||||
playlists_entries = playlist_manager.get_playlists()
|
||||
|
||||
ui = Gtk.Builder()
|
||||
ui.add_from_file(rb.find_plugin_file(self.plugin,
|
||||
'ui/coverart_exportembed.ui'))
|
||||
'ui/coverart_exportembed.ui'))
|
||||
ui.connect_signals(self)
|
||||
embeddialog = ui.get_object('exportembeddialog')
|
||||
folderchooserbutton = ui.get_object('folderchooserbutton')
|
||||
folderchooserbutton = ui.get_object('folderchooserbutton')
|
||||
use_album_name_checkbutton = ui.get_object('use_album_name_checkbutton')
|
||||
open_filemanager_checkbutton = ui.get_object('open_filemanager_checkbutton')
|
||||
|
||||
convert_checkbutton = ui.get_object('convert_checkbutton')
|
||||
bitrate_spinbutton = ui.get_object('bitrate_spinbutton')
|
||||
resize_checkbutton = ui.get_object('resize_checkbutton')
|
||||
resize_spinbutton = ui.get_object('resize_spinbutton')
|
||||
bitrate_spinbutton.set_value(self.TARGET_BITRATE)
|
||||
resize_spinbutton.set_value(128)
|
||||
|
||||
downloads_dir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DOWNLOAD)
|
||||
folderchooserbutton.set_current_folder(downloads_dir)
|
||||
|
||||
response = embeddialog.run()
|
||||
|
||||
|
||||
if response != Gtk.ResponseType.OK:
|
||||
embeddialog.destroy()
|
||||
return
|
||||
@@ -88,7 +106,14 @@ class CoverArtExport(GObject.Object):
|
||||
final_folder_store = folderchooserbutton.get_current_folder()
|
||||
use_album_name = use_album_name_checkbutton.get_active()
|
||||
open_filemanager = open_filemanager_checkbutton.get_active()
|
||||
|
||||
convert = convert_checkbutton.get_active()
|
||||
bitrate = bitrate_spinbutton.get_value()
|
||||
toresize = resize_checkbutton.get_active()
|
||||
if toresize:
|
||||
resize = int(resize_spinbutton.get_value())
|
||||
else:
|
||||
resize = -1
|
||||
|
||||
embeddialog.destroy()
|
||||
|
||||
albums = {}
|
||||
@@ -102,27 +127,28 @@ class CoverArtExport(GObject.Object):
|
||||
|
||||
def complete():
|
||||
self.album_manager.progress = 1
|
||||
|
||||
|
||||
if open_filemanager:
|
||||
#code taken from http://stackoverflow.com/questions/1795111/is-there-a-cross-platform-way-to-open-a-file-browser-in-python
|
||||
if sys.platform=='win32':
|
||||
import _winreg
|
||||
path= r('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon')
|
||||
for root in (_winreg.HKEY_CURRENT_USER, _winreg.HKEY_LOCAL_MACHINE):
|
||||
if sys.platform == 'win32':
|
||||
import winreg
|
||||
|
||||
path = r('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon')
|
||||
for root in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):
|
||||
try:
|
||||
with _winreg.OpenKey(root, path) as k:
|
||||
value, regtype= _winreg.QueryValueEx(k, 'Shell')
|
||||
with winreg.OpenKey(root, path) as k:
|
||||
value, regtype = winreg.QueryValueEx(k, 'Shell')
|
||||
except WindowsError:
|
||||
pass
|
||||
else:
|
||||
if regtype in (_winreg.REG_SZ, _winreg.REG_EXPAND_SZ):
|
||||
shell= value
|
||||
if regtype in (winreg.REG_SZ, winreg.REG_EXPAND_SZ):
|
||||
shell = value
|
||||
break
|
||||
else:
|
||||
shell= 'Explorer.exe'
|
||||
shell = 'Explorer.exe'
|
||||
subprocess.Popen([shell, final_folder_store])
|
||||
|
||||
elif sys.platform=='darwin':
|
||||
elif sys.platform == 'darwin':
|
||||
subprocess.Popen(['open', final_folder_store])
|
||||
|
||||
else:
|
||||
@@ -130,57 +156,174 @@ class CoverArtExport(GObject.Object):
|
||||
|
||||
self._albumiter = iter(albums)
|
||||
self._tracknumber = 0
|
||||
self._album = self._albumiter.next()
|
||||
|
||||
self._album = next(self._albumiter)
|
||||
|
||||
def idle_call(data):
|
||||
exit_idle = True
|
||||
|
||||
track = albums[self._album][self._tracknumber]
|
||||
|
||||
|
||||
if not process_track(self._album, track):
|
||||
exit_idle = False
|
||||
|
||||
self._tracknumber = self._tracknumber + 1
|
||||
|
||||
if self._tracknumber >= len(albums[self._album]):
|
||||
if self._tracknumber >= len(albums[self._album]):
|
||||
try:
|
||||
self._tracknumber = 0
|
||||
self._album = self._albumiter.next()
|
||||
self._album = next(self._albumiter)
|
||||
except StopIteration:
|
||||
exit_idle = False
|
||||
|
||||
|
||||
if not exit_idle:
|
||||
complete()
|
||||
|
||||
return exit_idle
|
||||
|
||||
|
||||
def process_track(album, track):
|
||||
self.album_manager.progress = self._track_count / total
|
||||
self._track_count = self._track_count + 1
|
||||
|
||||
key = album.create_ext_db_key()
|
||||
finalPath = urllib.unquote(track.location)[7:]
|
||||
finalPath = rb3compat.unquote(track.location)[7:]
|
||||
album_name = RB.search_fold(album.name)
|
||||
|
||||
|
||||
if use_album_name:
|
||||
folder_store = final_folder_store + '/' + album_name
|
||||
else:
|
||||
folder_store = final_folder_store
|
||||
|
||||
|
||||
try:
|
||||
if not os.path.exists(folder_store):
|
||||
os.makedirs(folder_store)
|
||||
shutil.copy(finalPath, folder_store)
|
||||
|
||||
if convert:
|
||||
self.convert_to_mp3(finalPath, folder_store, bitrate)
|
||||
finalPath = self._calc_mp3_filename(finalPath, folder_store)
|
||||
print(finalPath)
|
||||
else:
|
||||
shutil.copy(finalPath, folder_store)
|
||||
except IOError as err:
|
||||
print err.args[0]
|
||||
print(err.args[0])
|
||||
return False
|
||||
|
||||
dest = os.path.join(folder_store, os.path.basename(finalPath))
|
||||
desturi = 'file://' + urllib.pathname2url(dest)
|
||||
|
||||
return search_tracks.embed(desturi, key)
|
||||
desturi = 'file://' + rb3compat.pathname2url(dest)
|
||||
|
||||
return search_tracks.embed(desturi, key, resize)
|
||||
|
||||
data = None
|
||||
|
||||
|
||||
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE, idle_call, data)
|
||||
|
||||
|
||||
def _initialise_gstreamer(self):
|
||||
|
||||
if self._gstreamer_has_initialised:
|
||||
return
|
||||
|
||||
self._gstreamer_has_initialised = True
|
||||
Gst.init(None)
|
||||
|
||||
def on_new_decoded_pad(dbin, pad):
|
||||
decode = pad.get_parent()
|
||||
pipeline = decode.get_parent()
|
||||
convert = pipeline.get_by_name('convert')
|
||||
decode.link(convert)
|
||||
|
||||
#we are going to mimic the following
|
||||
# gst-launch-1.0 filesrc location="02 - ABBA - Knowing Me, Knowing You.ogg" !
|
||||
# decodebin ! audioconvert ! audioresample ! lamemp3enc target=bitrate bitrate=128 !
|
||||
# xingmux ! id3v2mux ! filesink location="mytrack.mp3"
|
||||
|
||||
converter = Gst.Pipeline.new('converter')
|
||||
|
||||
source = Gst.ElementFactory.make('filesrc', None)
|
||||
|
||||
decoder = Gst.ElementFactory.make('decodebin', 'decoder')
|
||||
convert = Gst.ElementFactory.make('audioconvert', 'convert')
|
||||
sample = Gst.ElementFactory.make('audioresample', 'sample')
|
||||
encoder = Gst.ElementFactory.make('lamemp3enc', 'encoder')
|
||||
encoder.set_property('target', 'bitrate')
|
||||
encoder.set_property('bitrate', self.TARGET_BITRATE)
|
||||
|
||||
xing = Gst.ElementFactory.make('xingmux', 'xing') # needed to make bitrate more accurate
|
||||
mux = Gst.ElementFactory.make('id3v2mux', 'mux')
|
||||
if not mux:
|
||||
# use id3mux where not available
|
||||
mux = Gst.ElementFactory.make('id3mux', 'mux')
|
||||
|
||||
sink = Gst.ElementFactory.make('filesink', 'sink')
|
||||
|
||||
converter.add(source)
|
||||
converter.add(decoder)
|
||||
converter.add(convert)
|
||||
converter.add(sample)
|
||||
converter.add(encoder)
|
||||
converter.add(xing)
|
||||
converter.add(mux)
|
||||
converter.add(sink)
|
||||
|
||||
Gst.Element.link(source, decoder)
|
||||
#note - a decodebin cannot be linked at compile since
|
||||
#it doesnt have source-pads (http://stackoverflow.com/questions/2993777/gstreamer-of-pythons-gst-linkerror-problem)
|
||||
|
||||
decoder.connect("pad-added", on_new_decoded_pad)
|
||||
|
||||
Gst.Element.link(convert, sample)
|
||||
Gst.Element.link(sample, encoder)
|
||||
Gst.Element.link(encoder, xing)
|
||||
Gst.Element.link(xing, mux)
|
||||
Gst.Element.link(mux, sink)
|
||||
|
||||
self.converter = converter
|
||||
self.source = source
|
||||
self.sink = sink
|
||||
self.encoder = encoder
|
||||
|
||||
def _calc_mp3_filename(self, filename, save_folder):
|
||||
finalname = os.path.basename(filename)
|
||||
finalname = finalname.rsplit('.')[0] + ".mp3"
|
||||
return save_folder + "/" + finalname
|
||||
|
||||
def convert_to_mp3(self, filename, save_folder, bitrate):
|
||||
|
||||
self.source.set_property('location', filename)
|
||||
self.sink.set_property('location', self._calc_mp3_filename(filename, save_folder))
|
||||
print(bitrate)
|
||||
if bitrate < 32:
|
||||
bitrate = self.TARGET_BITRATE
|
||||
|
||||
self.encoder.set_property('bitrate', int(bitrate))
|
||||
print(bitrate)
|
||||
|
||||
# Start playing
|
||||
ret = self.converter.set_state(Gst.State.PLAYING)
|
||||
|
||||
if ret == Gst.StateChangeReturn.FAILURE:
|
||||
print("Unable to set the pipeline to the playing state.", sys.stderr)
|
||||
exit(-1)
|
||||
|
||||
# Wait until error or EOS
|
||||
bus = self.converter.get_bus()
|
||||
try:
|
||||
msg = bus.timed_pop_filtered(
|
||||
Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS)
|
||||
except:
|
||||
# for some reason in ubuntu 12.04 Gst.CLOCK_TIME_NONE fails
|
||||
msg = bus.timed_pop_filtered(
|
||||
18446744073709551615, Gst.MessageType.ERROR | Gst.MessageType.EOS)
|
||||
|
||||
# Parse message
|
||||
if (msg):
|
||||
if msg.type == Gst.MessageType.ERROR:
|
||||
err, debug = msg.parse_error()
|
||||
print("Error received from element %s: %s" % (
|
||||
msg.src.get_name(), err), sys.stderr)
|
||||
print("Debugging information: %s" % debug, sys.stderr)
|
||||
elif msg.type == Gst.MessageType.EOS:
|
||||
print("End-Of-Stream reached.")
|
||||
else:
|
||||
print("Unexpected message received.", sys.stderr)
|
||||
|
||||
# Free resources
|
||||
self.converter.set_state(Gst.State.NULL)
|
||||
|
||||
@@ -19,25 +19,44 @@
|
||||
|
||||
from gi.repository import Peas
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
import lxml.etree as ET
|
||||
|
||||
import rb
|
||||
from coverart_rb3compat import ActionGroup
|
||||
from coverart_rb3compat import ApplicationShell
|
||||
from coverart_utils import CaseInsensitiveDict
|
||||
|
||||
|
||||
class ExternalPlugin(GObject.Object):
|
||||
'''
|
||||
Base class for all supported ExternalPlugins
|
||||
At a minimum, the following `attributes` keys must be defined:
|
||||
|
||||
:plugin_name: `str` module name of the plugin
|
||||
:action_group_name: `str` plugin GtkActionGroup
|
||||
:action: `str` plugin GtkAction - this is the action which is activated
|
||||
:is_album_menu: `bool` if the menu is applicable to albums
|
||||
by default, menus are created only for EntryViews
|
||||
class for all supported ExternalPlugins
|
||||
'''
|
||||
|
||||
def __init__(self, **kargs):
|
||||
super(ExternalPlugin, self).__init__(**kargs)
|
||||
|
||||
# dict of attributes associated with the external plugin
|
||||
self.attributes = {}
|
||||
self.attributes['is_album_menu'] = False
|
||||
self.attributes['new_menu_name'] = ''
|
||||
self.attributes['action_type'] = ''
|
||||
self.attributes['action_group_name'] = ''
|
||||
|
||||
def appendattribute(self, key, val):
|
||||
'''
|
||||
append another attribute to the dict
|
||||
|
||||
:param key: `str` name of attribute
|
||||
:param val: `str` value of attribute
|
||||
'''
|
||||
|
||||
if key == 'is_album_menu':
|
||||
if val == 'yes':
|
||||
self.attributes[key] = True
|
||||
else:
|
||||
self.attributes[key] = False
|
||||
else:
|
||||
self.attributes[key] = val
|
||||
|
||||
def is_activated(self):
|
||||
'''
|
||||
@@ -46,69 +65,61 @@ class ExternalPlugin(GObject.Object):
|
||||
peas = Peas.Engine.get_default()
|
||||
loaded_plugins = peas.get_loaded_plugins()
|
||||
|
||||
print loaded_plugins
|
||||
if self.attributes['plugin_name'] in loaded_plugins:
|
||||
if self.attributes['plugin_name'] in CaseInsensitiveDict(loaded_plugins):
|
||||
print("found %s" % self.attributes['plugin_name'])
|
||||
return True
|
||||
|
||||
print("search for %s" % self.attributes['plugin_name'])
|
||||
print(loaded_plugins)
|
||||
|
||||
return False
|
||||
|
||||
def create_menu_item(self, menu_name, shell,
|
||||
save_actiongroup, for_album = False):
|
||||
def create_menu_item(self, menubar, section_name, at_position,
|
||||
save_actiongroup, save_menu, for_album=False):
|
||||
'''
|
||||
method to create the menu item appropriate to the plugin
|
||||
method to create the menu item appropriate to the plugin.
|
||||
A plugin can have many menu items - all menuitems are enclosed
|
||||
in a section.
|
||||
|
||||
:menu_name: `str` unique name for the calling (popup) menu
|
||||
:shell: `RB.Shell` rhythmbox shell
|
||||
:save_actiongroup: `GtkActionGroup` - this is our action-group
|
||||
where our menus are described
|
||||
:for_album: `bool` create the menu for the album - if not given
|
||||
:param menubar: `str` name for the GtkMenu - ignored for RB2.99
|
||||
:param section_name: `str` unique name of the section holding the menu items
|
||||
:param at_position: `int` position within the GtkMenu to create menu - ignored for RB2.99
|
||||
:param save_actiongroup: `ActionGroup` container for all menu-item Actions
|
||||
:param save_menu: `Menu` whole popupmenu including sub-menus
|
||||
:param for_album: `bool` create the menu for the album - if not given
|
||||
then its assumed the menu item is appropriate just for tracks
|
||||
'''
|
||||
|
||||
if for_album and not self.attributes['is_album_menu']:
|
||||
return False
|
||||
|
||||
|
||||
if not self.is_activated():
|
||||
return False
|
||||
|
||||
uim = shell.props.ui_manager
|
||||
ui_actiongroups = uim.get_action_groups()
|
||||
|
||||
actiongroup = None
|
||||
for actiongroup in ui_actiongroups:
|
||||
if actiongroup.get_name() == self.attributes['action_group_name']:
|
||||
break
|
||||
|
||||
action = None
|
||||
if actiongroup:
|
||||
action = actiongroup.get_action(self.attributes['action_name'])
|
||||
action = ApplicationShell(save_menu.shell).lookup_action(self.attributes['action_group_name'],
|
||||
self.attributes['action_name'],
|
||||
self.attributes['action_type'])
|
||||
|
||||
if action:
|
||||
self.attributes['action']=action
|
||||
self.attributes['tooltip']=action.get_tooltip()
|
||||
self.attributes['action'] = action
|
||||
|
||||
if self.attributes['new_menu_name'] != '':
|
||||
self.attributes['label'] = self.attributes['new_menu_name']
|
||||
else:
|
||||
self.attributes['label']=action.get_label()
|
||||
self.attributes['visible']=action.get_visible()
|
||||
self.attributes['sensitive']=action.get_sensitive()
|
||||
self.attributes['label'] = action.label
|
||||
#self.attributes['sensitive']=action.get_sensitive()
|
||||
else:
|
||||
print("action not found")
|
||||
print(self.attributes)
|
||||
return False
|
||||
|
||||
new_menu_item = Gtk.MenuItem(label=self.attributes['label'])
|
||||
new_menu_item.set_visible(self.attributes['visible'])
|
||||
new_menu_item.set_sensitive(self.attributes['sensitive'])
|
||||
|
||||
action = Gtk.Action(label=self.attributes['label'],
|
||||
name=menu_name + self.attributes['label'],
|
||||
tooltip=self.attributes['tooltip'], stock_id=Gtk.STOCK_CLEAR)
|
||||
|
||||
action.connect('activate', self.menuitem_callback, for_album, shell)
|
||||
new_menu_item.set_related_action(action)
|
||||
save_actiongroup.add_action(action)
|
||||
action = save_actiongroup.add_action(func=self.menuitem_callback,
|
||||
action_name=self.attributes['action_name'], album=for_album,
|
||||
shell=save_menu.shell, label=self.attributes['label'])
|
||||
|
||||
new_menu_item = save_menu.insert_menu_item(menubar, section_name,
|
||||
at_position, action)
|
||||
return new_menu_item
|
||||
|
||||
|
||||
def do_deactivate(self):
|
||||
pass
|
||||
|
||||
@@ -125,141 +136,109 @@ class ExternalPlugin(GObject.Object):
|
||||
|
||||
page.get_entry_view().select_all()
|
||||
|
||||
def menuitem_callback(self, menu, for_album, shell):
|
||||
def activate(self, shell):
|
||||
'''
|
||||
method called when a menu-item is clicked
|
||||
method called to initiate the external plugin action
|
||||
the action is defined by defining the action_group_name, action_name and action_type
|
||||
'''
|
||||
|
||||
action = ApplicationShell(shell).lookup_action(self.attributes['action_group_name'],
|
||||
self.attributes['action_name'],
|
||||
self.attributes['action_type'])
|
||||
|
||||
if action:
|
||||
action.activate()
|
||||
|
||||
def menuitem_callback(self, action, param, args):
|
||||
'''
|
||||
method called when a menu-item is clicked. Basically, an Action
|
||||
is activated by the user
|
||||
|
||||
:param action: `Gio.SimpleAction` or `Gtk.Action`
|
||||
:param param: Not used
|
||||
:param args: dict associated with the action
|
||||
'''
|
||||
for_album = args['album']
|
||||
shell = args['shell']
|
||||
if for_album:
|
||||
self.set_entry_view_selected_entries(shell)
|
||||
|
||||
|
||||
self.attributes['action'].activate()
|
||||
|
||||
class OpenContainingFolder(ExternalPlugin):
|
||||
def __init__(self, **kargs):
|
||||
super(OpenContainingFolder, self).__init__(**kargs)
|
||||
|
||||
self.attributes['plugin_name'] = 'opencontainingfolder'
|
||||
self.attributes['action_group_name'] = 'OpenContainingFolderActions'
|
||||
self.attributes['action_name'] = 'OpenContainingFolder'
|
||||
self.attributes['is_album_menu'] = True
|
||||
|
||||
class SendFirst(ExternalPlugin):
|
||||
def __init__(self, **kargs):
|
||||
super(SendFirst, self).__init__(**kargs)
|
||||
|
||||
self.attributes['plugin_name'] = 'send_first'
|
||||
self.attributes['action_group_name'] = 'SendFirstPluginActionGroup'
|
||||
self.attributes['action_name'] = 'QueueFirstAction'
|
||||
self.attributes['is_album_menu'] = True
|
||||
|
||||
class SendTo(ExternalPlugin):
|
||||
def __init__(self, **kargs):
|
||||
super(SendTo, self).__init__(**kargs)
|
||||
|
||||
self.attributes['plugin_name'] = 'sendto'
|
||||
self.attributes['action_group_name'] = 'SendToActionGroup'
|
||||
self.attributes['action_name'] = 'SendTo'
|
||||
self.attributes['is_album_menu'] = True
|
||||
|
||||
class LastFMExtensionFingerprinter(ExternalPlugin):
|
||||
def __init__(self, **kargs):
|
||||
super(LastFMExtensionFingerprinter, self).__init__(**kargs)
|
||||
|
||||
self.attributes['plugin_name'] = 'lastfm_extension'
|
||||
self.attributes['action_group_name'] = 'LastFMExtensionFingerprinter'
|
||||
self.attributes['action_name'] = 'FingerprintSong'
|
||||
self.attributes['is_album_menu'] = False
|
||||
|
||||
class FileOrganizer(ExternalPlugin):
|
||||
def __init__(self, **kargs):
|
||||
super(FileOrganizer, self).__init__(**kargs)
|
||||
|
||||
self.attributes['plugin_name'] = 'fileorganizer'
|
||||
self.attributes['action_group_name'] = 'FileorganizerActions'
|
||||
self.attributes['action_name'] = 'OrganizeSelection'
|
||||
self.attributes['is_album_menu'] = True
|
||||
|
||||
class lLyrics(ExternalPlugin):
|
||||
def __init__(self, **kargs):
|
||||
super(lLyrics, self).__init__(**kargs)
|
||||
|
||||
self.attributes['plugin_name'] = 'lLyrics'
|
||||
self.attributes['action_group_name'] = 'lLyricsPluginPopupActions'
|
||||
self.attributes['action_name'] = 'lLyricsPopupAction'
|
||||
self.attributes['is_album_menu'] = False
|
||||
|
||||
class wikipediasearch(ExternalPlugin):
|
||||
def __init__(self, **kargs):
|
||||
super(wikipediasearch, self).__init__(**kargs)
|
||||
|
||||
self.attributes['plugin_name'] = 'WikipediaSearch'
|
||||
self.attributes['action_group_name'] = 'WikipediaActions'
|
||||
self.attributes['action_name'] = 'SearchWikipediaAlbum'
|
||||
self.attributes['new_menu_name'] = 'WikipediaSearch - Album'
|
||||
self.attributes['is_album_menu'] = True
|
||||
|
||||
class CreateExternalPluginMenu(GObject.Object):
|
||||
'''
|
||||
This is the key class called to initialise all supported plugins
|
||||
|
||||
:menu_name: `str` unique name of the (popup) menu
|
||||
:shell: `RB.Shell` plugin shell attribute
|
||||
:param section_name: `str` unique name of the section holding the menu items
|
||||
:param at_position: `int` position within the GtkMenu to create menu - ignored for RB2.99
|
||||
:param popup: `Menu` whole popupmenu including sub-menus
|
||||
'''
|
||||
def __init__(self, menu_name, shell, **kargs):
|
||||
|
||||
def __init__(self, section_name, at_position, popup, **kargs):
|
||||
super(CreateExternalPluginMenu, self).__init__(**kargs)
|
||||
|
||||
self.menu_name = menu_name
|
||||
self.shell = shell
|
||||
self._actiongroup = Gtk.ActionGroup(menu_name + '_externalplugins')
|
||||
self._menu_array = []
|
||||
self.menu = popup
|
||||
self.section_name = section_name
|
||||
self.at_position = at_position
|
||||
|
||||
# all supported plugins MUST be defined in the following array
|
||||
self.supported_plugins = [
|
||||
OpenContainingFolder(),
|
||||
SendFirst(),
|
||||
SendTo(),
|
||||
LastFMExtensionFingerprinter(),
|
||||
FileOrganizer(),
|
||||
lLyrics(),
|
||||
wikipediasearch() ]
|
||||
self._actiongroup = ActionGroup(popup.shell, section_name + '_externalplugins')
|
||||
|
||||
def create_menu(self, menu_bar, at_position, for_album = False):
|
||||
# all supported plugins will be defined in the following array by parsing
|
||||
# the plugins XML file for the definition.
|
||||
|
||||
self.supported_plugins = []
|
||||
|
||||
extplugins = rb.find_plugin_file(popup.plugin, 'ui/coverart_external_plugins.xml')
|
||||
root = ET.parse(open(extplugins)).getroot()
|
||||
|
||||
base = 'rb3/plugin'
|
||||
|
||||
for elem in root.xpath(base):
|
||||
pluginname = elem.attrib['name']
|
||||
|
||||
basemenu = base + "[@name='" + pluginname + "']/menu"
|
||||
|
||||
for menuelem in root.xpath(basemenu):
|
||||
ext = ExternalPlugin()
|
||||
ext.appendattribute('plugin_name', pluginname)
|
||||
|
||||
label = menuelem.attrib['label']
|
||||
if label != "":
|
||||
ext.appendattribute('new_menu_name', label)
|
||||
baseattrib = basemenu + "[@label='" + label + "']/attribute"
|
||||
else:
|
||||
baseattrib = basemenu + "/attribute"
|
||||
|
||||
for attribelem in root.xpath(baseattrib):
|
||||
key = attribelem.attrib['name']
|
||||
val = attribelem.text
|
||||
ext.appendattribute(key, val)
|
||||
|
||||
self.supported_plugins.append(ext)
|
||||
|
||||
def create_menu(self, menu_name, for_album=False):
|
||||
'''
|
||||
method to create the menu items for all supported plugins
|
||||
|
||||
:menu_bar: `GtkMenu` - where the menu-items are to be added
|
||||
:at_position: `int` - position in the menu list where menu-items
|
||||
are to be added
|
||||
:param menu_name: `str` unique name (GtkMenu) id for the menu to create
|
||||
:for_album: `bool` - create a menu applicable for Albums
|
||||
by default a menu is assumed to be applicable to a track in an
|
||||
EntryView
|
||||
'''
|
||||
|
||||
#tidy up old menu items before recreating the list
|
||||
for action in self._actiongroup.list_actions():
|
||||
print "removing"
|
||||
self._actiongroup.remove_action(action)
|
||||
self.menu_name = menu_name
|
||||
|
||||
for menu_item in self._menu_array:
|
||||
menu_bar.remove(menu_item)
|
||||
self._actiongroup.remove_actions()
|
||||
self.menu.remove_menu_items(self.menu_name, self.section_name)
|
||||
|
||||
self._menu_array = []
|
||||
items_added = False
|
||||
|
||||
for plugin in self.supported_plugins:
|
||||
menu_item = plugin.create_menu_item(self.menu_name,
|
||||
self.shell, self._actiongroup, for_album)
|
||||
new_menu_item = plugin.create_menu_item(self.menu_name, self.section_name,
|
||||
self.at_position, self._actiongroup, self.menu, for_album)
|
||||
|
||||
if menu_item:
|
||||
self._menu_array.append(menu_item)
|
||||
if (not items_added) and new_menu_item:
|
||||
items_added = True
|
||||
|
||||
if len(self._menu_array) > 0:
|
||||
menu_item = Gtk.SeparatorMenuItem().new()
|
||||
menu_item.set_visible(True)
|
||||
self._menu_array.append(menu_item)
|
||||
|
||||
for menu_item in self._menu_array:
|
||||
menu_bar.insert(menu_item, at_position)
|
||||
|
||||
uim = self.shell.props.ui_manager
|
||||
menu_bar.show_all()
|
||||
uim.ensure_update()
|
||||
if items_added:
|
||||
self.menu.insert_separator(self.menu_name, self.at_position)
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import GLib
|
||||
|
||||
from coverart_widgets import AbstractView
|
||||
|
||||
|
||||
class ListShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
the view that makes use of the `AlbumsModel`.
|
||||
'''
|
||||
|
||||
def __init__(self, list_view):
|
||||
super(ListShowingPolicy, self).__init__()
|
||||
|
||||
self.counter = 0
|
||||
self._has_initialised = False
|
||||
|
||||
def initialise(self, album_manager):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
|
||||
class ListView(AbstractView):
|
||||
__gtype_name__ = "ListView"
|
||||
|
||||
name = 'listview'
|
||||
use_plugin_window = False
|
||||
|
||||
def __init__(self):
|
||||
super(ListView, self).__init__()
|
||||
self.view = self
|
||||
self._has_initialised = False
|
||||
self.show_policy = ListShowingPolicy(self)
|
||||
|
||||
def initialise(self, source):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
self.view_name = "list_view"
|
||||
super(ListView, self).initialise(source)
|
||||
#self.album_manager = source.album_manager
|
||||
self.shell = source.shell
|
||||
|
||||
def switch_to_view(self, source, album):
|
||||
self.initialise(source)
|
||||
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.shell.props.library_source)
|
||||
|
||||
def get_selected_objects(self):
|
||||
'''
|
||||
finds what has been selected
|
||||
|
||||
returns an array of `Album`
|
||||
'''
|
||||
return []
|
||||
@@ -0,0 +1,184 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
# define plugin
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import RB
|
||||
from gi.repository import GObject
|
||||
from coverart_rb3compat import Menu
|
||||
from coverart_external_plugins import CreateExternalPluginMenu
|
||||
from coverart_entryview import CoverArtEntryView
|
||||
from coverart_rb3compat import ActionGroup
|
||||
from coverart_rb3compat import ApplicationShell
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
import rb
|
||||
|
||||
class CoverArtPlayEntryView(CoverArtEntryView):
|
||||
__hash__ = GObject.__hash__
|
||||
|
||||
def __init__(self, shell, source):
|
||||
'''
|
||||
Initializes the entryview.
|
||||
'''
|
||||
super(CoverArtPlayEntryView, self).__init__(shell, source)
|
||||
|
||||
def define_menu(self):
|
||||
popup = Menu(self.plugin, self.shell)
|
||||
popup.load_from_file('N/A',
|
||||
'ui/coverart_play_pop_rb3.ui')
|
||||
signals = {
|
||||
'remove_from_playlist_menu_item': self.remove_from_playlist_menu_item_callback
|
||||
}
|
||||
|
||||
popup.connect_signals(signals)
|
||||
popup.connect('pre-popup', self.pre_popup_menu_callback)
|
||||
self.popup = popup
|
||||
|
||||
def pre_popup_menu_callback(self, *args):
|
||||
'''
|
||||
Callback when the popup menu is about to be displayed
|
||||
'''
|
||||
|
||||
if not self.external_plugins:
|
||||
self.external_plugins = \
|
||||
CreateExternalPluginMenu("playlist_entry_view", 1, self.popup)
|
||||
self.external_plugins.create_menu('play_popup_menu')
|
||||
|
||||
def remove_from_playlist_menu_item_callback(self, *args):
|
||||
print ("remove_from_playlist_menu_item_callback")
|
||||
entries = self.get_selected_entries()
|
||||
for entry in entries:
|
||||
print (entry)
|
||||
self.source.source_query_model.remove_entry(entry)
|
||||
|
||||
def do_show_popup(self, over_entry):
|
||||
if over_entry:
|
||||
print("CoverArtBrowser DEBUG - do_show_popup()")
|
||||
|
||||
self.popup.popup(self.source,
|
||||
'play_popup_menu', 0, Gtk.get_current_event_time())
|
||||
|
||||
return over_entry
|
||||
|
||||
def play_track_menu_item_callback(self, *args):
|
||||
print("CoverArtBrowser DEBUG - play_track_menu_item_callback()")
|
||||
|
||||
selected = self.get_selected_entries()
|
||||
entry = selected[0]
|
||||
|
||||
# Start the music
|
||||
player = self.shell.props.shell_player
|
||||
player.play_entry(entry, self.source)
|
||||
|
||||
print("CoverArtBrowser DEBUG - play_track_menu_item_callback()")
|
||||
|
||||
|
||||
class CoverArtPlaySource(RB.Source):
|
||||
'''
|
||||
Source utilized by the plugin to show all it's ui.
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
'''
|
||||
Initializes the source.
|
||||
'''
|
||||
super(CoverArtPlaySource, self).__init__()
|
||||
self.external_plugins = None
|
||||
self.hasActivated = False
|
||||
|
||||
def initialise(self, plugin, shell, source):
|
||||
self.plugin = plugin
|
||||
self.shell = shell
|
||||
self.source = source
|
||||
|
||||
def do_selected(self):
|
||||
'''
|
||||
Called by Rhythmbox when the source is selected. It makes sure to
|
||||
create the ui the first time the source is shown.
|
||||
'''
|
||||
print("CoverArtBrowser DEBUG - do_selected")
|
||||
|
||||
# first time of activation -> add graphical stuff
|
||||
if not self.hasActivated:
|
||||
self.do_impl_activate()
|
||||
|
||||
# indicate that the source was activated before
|
||||
self.hasActivated = True
|
||||
|
||||
print("CoverArtBrowser DEBUG - end do_selected")
|
||||
|
||||
def connect_library_signals(self):
|
||||
pass
|
||||
|
||||
def do_impl_activate(self):
|
||||
'''
|
||||
Called by do_selected the first time the source is activated.
|
||||
It creates all the source ui and connects the necessary signals for it
|
||||
correct behavior.
|
||||
'''
|
||||
print ('do_impl_activate')
|
||||
self.hasActivated = True
|
||||
|
||||
self.entryview = CoverArtPlayEntryView(self.shell, self.source)
|
||||
self.entryview.props.hexpand = True
|
||||
self.entryview.props.vexpand = True
|
||||
grid = Gtk.Grid()
|
||||
grid.attach(self.entryview, 0, 1, 1, 1)
|
||||
|
||||
self.entryview.set_model(self.source.source_query_model)
|
||||
|
||||
# enable sorting on the entryview
|
||||
#entryview.set_columns_clickable(True)
|
||||
self.shell.props.library_source.get_entry_view().set_columns_clickable(
|
||||
True)
|
||||
|
||||
cl = CoverLocale()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
location = rb.find_plugin_file(self.plugin, 'ui/playsource-toolbar.ui')
|
||||
ui = Gtk.Builder()
|
||||
ui.set_translation_domain(cl.Locale.RB)
|
||||
ui.add_from_file(location)
|
||||
toolbar_menu = ui.get_object('playsource-toolbar')
|
||||
app = self.shell.props.application
|
||||
app.link_shared_menus(toolbar_menu)
|
||||
bar = RB.ButtonBar.new(toolbar_menu, toolbar_menu)
|
||||
grid.attach(bar, 0, 0, 1, 1)
|
||||
|
||||
grid.show_all()
|
||||
self.pack_start(grid, True, True, 0)
|
||||
|
||||
appshell = ApplicationShell(self.shell)
|
||||
action_group = ActionGroup(self.shell, 'PlaySourceActions')
|
||||
action_group.add_action(func=self.clear_playsource,
|
||||
action_name='playsource-clear', action_state=ActionGroup.STANDARD,
|
||||
action_type='app')
|
||||
action_group.add_action(func=self.shuffle_playsource,
|
||||
action_name='playsource-shuffle', action_state=ActionGroup.STANDARD,
|
||||
action_type='app')
|
||||
appshell.insert_action_group(action_group)
|
||||
|
||||
def clear_playsource(self, *args):
|
||||
for row in self.entryview.props.model:
|
||||
self.entryview.props.model.remove_entry(row[0])
|
||||
|
||||
def shuffle_playsource(self, *args):
|
||||
self.entryview.props.model.shuffle_entries()
|
||||
|
||||
|
||||
GObject.type_register(CoverArtPlayEntryView)
|
||||
@@ -0,0 +1,377 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import urllib.parse
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
|
||||
from gi.repository import RB
|
||||
from gi.repository import Gtk
|
||||
|
||||
from coverart_utils import idle_iterator
|
||||
import rb
|
||||
|
||||
|
||||
LOAD_CHUNK = 50
|
||||
|
||||
|
||||
class WebPlaylist(object):
|
||||
MAX_TRACKS_TO_ADD = 3 # number of tracks to add to a source for each fetch
|
||||
MIN_TRACKS_TO_FETCH = 5 # number of tracks in source before a fetch will be required
|
||||
TOTAL_TRACKS_REMEMBERED = 25 # total number of tracks for all artists before a fetch is allowed
|
||||
MAX_TRACKS_PER_ARTIST = 3 # number of tracks allowed to be remembered per artist
|
||||
|
||||
def __init__(self, shell, source, playlist_name):
|
||||
|
||||
self.shell = shell
|
||||
#lets fill up the queue with artists
|
||||
self.candidate_artist = {}
|
||||
self.shell.props.shell_player.connect('playing-song-changed', self.playing_song_changed)
|
||||
self.source = source
|
||||
self.search_entry = None
|
||||
self.playlist_started = False
|
||||
self.played_artist = {}
|
||||
self.tracks_not_played = 0
|
||||
# cache for artist information: valid for a month, can be used indefinitely
|
||||
# if offline, discarded if unused for six months
|
||||
self.info_cache = rb.URLCache(name=playlist_name,
|
||||
path=os.path.join('coverart_browser', playlist_name),
|
||||
refresh=30,
|
||||
discard=180)
|
||||
self.info_cache.clean()
|
||||
|
||||
def playing_song_changed(self, player, entry):
|
||||
if not entry:
|
||||
return
|
||||
|
||||
if player.get_playing_source() != self.source:
|
||||
self.playlist_started = False
|
||||
self.played_artist.clear()
|
||||
self.tracks_not_played = 0
|
||||
|
||||
if self.playlist_started and len(self.source.props.query_model) < self.MIN_TRACKS_TO_FETCH:
|
||||
self.start(entry)
|
||||
|
||||
def start(self, seed_entry, reinitialise=False):
|
||||
artist = seed_entry.get_string(RB.RhythmDBPropType.ARTIST)
|
||||
|
||||
if reinitialise:
|
||||
self.played_artist.clear()
|
||||
self.tracks_not_played = 0
|
||||
self.playlist_started = False
|
||||
|
||||
player = self.shell.props.shell_player
|
||||
_, is_playing = player.get_playing()
|
||||
|
||||
if is_playing:
|
||||
player.stop()
|
||||
|
||||
for row in self.source.props.query_model:
|
||||
self.source.props.query_model.remove_entry(row[0])
|
||||
|
||||
if self.tracks_not_played > self.TOTAL_TRACKS_REMEMBERED:
|
||||
print(("we have plenty of tracks to play yet - no need to fetch more %d", self.tracks_not_played))
|
||||
self.add_tracks_to_source()
|
||||
return
|
||||
|
||||
search_artist = urllib.parse.quote(artist.encode("utf8"))
|
||||
if search_artist in self.played_artist:
|
||||
print("we have already searched for that artist")
|
||||
return
|
||||
|
||||
self.search_entry = seed_entry
|
||||
self.played_artist[search_artist] = True
|
||||
|
||||
self.playlist_started = True
|
||||
self._running = False
|
||||
self._start_process()
|
||||
|
||||
def _start_process(self):
|
||||
if not self._running:
|
||||
self._running = True
|
||||
self.search_website()
|
||||
|
||||
def search_website(self):
|
||||
pass
|
||||
|
||||
def _clear_next(self):
|
||||
self.search_artists = ""
|
||||
self._running = False
|
||||
|
||||
@idle_iterator
|
||||
def _load_albums(self):
|
||||
def process(row, data):
|
||||
entry = data['model'][row.path][0]
|
||||
|
||||
lookup = entry.get_string(RB.RhythmDBPropType.ARTIST_FOLDED)
|
||||
lookup_title = entry.get_string(RB.RhythmDBPropType.TITLE_FOLDED)
|
||||
|
||||
if lookup in self.artist and \
|
||||
lookup_title in \
|
||||
self.artist[lookup]:
|
||||
|
||||
if lookup not in self.candidate_artist:
|
||||
self.candidate_artist[lookup] = []
|
||||
|
||||
# N.B. every artist has an array of dicts with a known format of track & add-to-source elements
|
||||
# the following extracts the track-title and add-to-source to form a dict of track-title and a value
|
||||
# of the add-to-source
|
||||
d = dict((i['track-title'], i['add-to-source']) for i in self.candidate_artist[lookup])
|
||||
if len(d) < self.MAX_TRACKS_PER_ARTIST and lookup_title not in d:
|
||||
# we only append a max of three tracks to each artist
|
||||
self.candidate_artist[lookup].append({
|
||||
'track': entry,
|
||||
'add-to-source': False,
|
||||
'track-title': lookup_title})
|
||||
self.tracks_not_played = self.tracks_not_played + 1
|
||||
|
||||
|
||||
def after(data):
|
||||
# update the progress
|
||||
pass
|
||||
|
||||
def error(exception):
|
||||
print(('Error processing entries: ' + str(exception)))
|
||||
|
||||
def finish(data):
|
||||
|
||||
self.add_tracks_to_source()
|
||||
self._clear_next()
|
||||
|
||||
return LOAD_CHUNK, process, after, error, finish
|
||||
|
||||
def display_error_message(self):
|
||||
dialog = Gtk.MessageDialog(None,
|
||||
Gtk.DialogFlags.MODAL,
|
||||
Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK,
|
||||
_("No matching tracks have been found"))
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def add_tracks_to_source(self):
|
||||
entries = []
|
||||
for artist in self.candidate_artist:
|
||||
|
||||
d = dict((i['track'], (self.candidate_artist[artist].index(i),
|
||||
i['add-to-source'],
|
||||
artist)) for i in self.candidate_artist[artist])
|
||||
|
||||
for entry, elements in d.items():
|
||||
element_pos, add_to_source, artist = elements
|
||||
if not add_to_source:
|
||||
entries.append({entry: elements})
|
||||
|
||||
random.shuffle(entries)
|
||||
|
||||
count = 0
|
||||
for row in entries:
|
||||
print(row)
|
||||
entry, elements = list(row.items())[0]
|
||||
element_pos, add_to_source, artist = elements
|
||||
self.source.add_entry(entry, -1)
|
||||
self.candidate_artist[artist][element_pos]['add-to-source'] = True
|
||||
|
||||
count = count + 1
|
||||
self.tracks_not_played = self.tracks_not_played - 1
|
||||
if count == self.MAX_TRACKS_TO_ADD:
|
||||
break
|
||||
|
||||
player = self.shell.props.shell_player
|
||||
|
||||
_, is_playing = player.get_playing()
|
||||
|
||||
if len(self.source.props.query_model) > 0 and not is_playing:
|
||||
player.play_entry(self.source.props.query_model[0][0], self.source)
|
||||
|
||||
|
||||
class LastFMTrackPlaylist(WebPlaylist):
|
||||
def __init__(self, shell, source):
|
||||
WebPlaylist.__init__(self, shell, source, "lastfm_trackplaylist")
|
||||
|
||||
def search_website(self):
|
||||
# unless already cached - directly fetch from lastfm similar track information
|
||||
apikey = "844353bce568b93accd9ca47674d6c3e"
|
||||
url = "http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&api_key={0}&artist={1}&track={2}&format=json"
|
||||
|
||||
artist = self.search_entry.get_string(RB.RhythmDBPropType.ARTIST)
|
||||
title = self.search_entry.get_string(RB.RhythmDBPropType.TITLE)
|
||||
artist = urllib.parse.quote(artist.encode("utf8"))
|
||||
title = urllib.parse.quote(title.encode("utf8"))
|
||||
formatted_url = url.format(urllib.parse.quote(apikey),
|
||||
artist,
|
||||
title)
|
||||
|
||||
print(formatted_url)
|
||||
cachekey = "artist:%s:title:%s" % (artist, title)
|
||||
self.info_cache.fetch(cachekey, formatted_url, self.similar_info_cb, None)
|
||||
|
||||
def similar_info_cb(self, data, _):
|
||||
|
||||
if not data:
|
||||
print("nothing to do")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
similar = json.loads(data.decode('utf-8'))
|
||||
|
||||
# loop through the response and find all titles for the artists returned
|
||||
self.artist = {}
|
||||
|
||||
if 'similartracks' not in similar:
|
||||
print("No matching data returned from LastFM")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
for song in similar['similartracks']['track']:
|
||||
name = RB.search_fold(song['artist']['name'])
|
||||
if name not in self.artist:
|
||||
self.artist[name] = []
|
||||
|
||||
self.artist[name].append(RB.search_fold(song['name']))
|
||||
|
||||
if len(self.artist) == 0:
|
||||
print("no artists returned")
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
# loop through every track - see if the track contains the artist & title
|
||||
# if yes then this is a candidate similar track to remember
|
||||
|
||||
query_model = self.shell.props.library_source.props.base_query_model
|
||||
|
||||
self._load_albums(iter(query_model), albums={}, model=query_model,
|
||||
total=len(query_model), progress=0.)
|
||||
|
||||
|
||||
class EchoNestPlaylist(WebPlaylist):
|
||||
def __init__(self, shell, source):
|
||||
WebPlaylist.__init__(self, shell, source, "echonest_playlist")
|
||||
|
||||
def search_website(self):
|
||||
# unless already cached - directly fetch from echonest similar artist information
|
||||
apikey = "N685TONJGZSHBDZMP"
|
||||
url = "http://developer.echonest.com/api/v4/playlist/basic?api_key={0}&artist={1}&format=json&results=100&type=artist-radio&limited_interactivity=true"
|
||||
|
||||
artist = self.search_entry.get_string(RB.RhythmDBPropType.ARTIST)
|
||||
artist = urllib.parse.quote(artist.encode("utf8"))
|
||||
formatted_url = url.format(urllib.parse.quote(apikey),
|
||||
artist)
|
||||
|
||||
print(formatted_url)
|
||||
cachekey = "artist:%s" % artist
|
||||
self.info_cache.fetch(cachekey, formatted_url, self.similar_info_cb, None)
|
||||
|
||||
def similar_info_cb(self, data, _):
|
||||
|
||||
if not data:
|
||||
print("nothing to do")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
similar = json.loads(data.decode('utf-8'))
|
||||
|
||||
# loop through the response and find all titles for the artists returned
|
||||
self.artist = {}
|
||||
|
||||
if 'songs' not in similar['response']:
|
||||
print("No matching data returned from EchoNest")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
for song in similar['response']['songs']:
|
||||
name = RB.search_fold(song['artist_name'])
|
||||
if name not in self.artist:
|
||||
self.artist[name] = []
|
||||
|
||||
self.artist[name].append(RB.search_fold(song['title']))
|
||||
|
||||
if len(self.artist) == 0:
|
||||
print("no artists returned")
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
# loop through every track - see if the track contains the artist & title
|
||||
# if yes then this is a candidate similar track to remember
|
||||
|
||||
query_model = self.shell.props.library_source.props.base_query_model
|
||||
|
||||
self._load_albums(iter(query_model), albums={}, model=query_model,
|
||||
total=len(query_model), progress=0.)
|
||||
|
||||
|
||||
class EchoNestGenrePlaylist(WebPlaylist):
|
||||
def __init__(self, shell, source):
|
||||
WebPlaylist.__init__(self, shell, source, "echonest_genre_playlist")
|
||||
|
||||
def search_website(self):
|
||||
# unless already cached - directly fetch from echonest similar artist information
|
||||
apikey = "N685TONJGZSHBDZMP"
|
||||
url = "http://developer.echonest.com/api/v4/playlist/basic?api_key={0}&genre={1}&format=json&results=100&type=genre-radio&limited_interactivity=true"
|
||||
|
||||
genre = self.search_entry.get_string(RB.RhythmDBPropType.GENRE).lower()
|
||||
genre = urllib.parse.quote(genre.encode("utf8"))
|
||||
formatted_url = url.format(urllib.parse.quote(apikey),
|
||||
genre)
|
||||
|
||||
print(formatted_url)
|
||||
cachekey = "genre:%s" % genre
|
||||
self.info_cache.fetch(cachekey, formatted_url, self.similar_info_cb, None)
|
||||
|
||||
def similar_info_cb(self, data, _):
|
||||
|
||||
if not data:
|
||||
print("nothing to do")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
similar = json.loads(data.decode('utf-8'))
|
||||
|
||||
# loop through the response and find all titles for the artists returned
|
||||
self.artist = {}
|
||||
|
||||
if 'songs' not in similar['response']:
|
||||
print("No matching data returned from EchoNest")
|
||||
self.display_error_message()
|
||||
self._clear_next()
|
||||
return
|
||||
for song in similar['response']['songs']:
|
||||
name = RB.search_fold(song['artist_name'])
|
||||
if name not in self.artist:
|
||||
self.artist[name] = []
|
||||
|
||||
self.artist[name].append(RB.search_fold(song['title']))
|
||||
|
||||
if len(self.artist) == 0:
|
||||
print("no artists returned")
|
||||
self._clear_next()
|
||||
return
|
||||
|
||||
# loop through every track - see if the track contains the artist & title
|
||||
# if yes then this is a candidate similar track to remember
|
||||
|
||||
query_model = self.shell.props.library_source.props.base_query_model
|
||||
|
||||
self._load_albums(iter(query_model), albums={}, model=query_model,
|
||||
total=len(query_model), progress=0.)
|
||||
@@ -0,0 +1,80 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import GLib
|
||||
|
||||
from coverart_widgets import AbstractView
|
||||
|
||||
|
||||
class PlaySourceShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
the view that makes use of the `AlbumsModel`.
|
||||
'''
|
||||
|
||||
def __init__(self, list_view):
|
||||
super(PlaySourceShowingPolicy, self).__init__()
|
||||
|
||||
self.counter = 0
|
||||
self._has_initialised = False
|
||||
|
||||
def initialise(self, album_manager):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
|
||||
class PlaySourceView(AbstractView):
|
||||
__gtype_name__ = "PlaySourceView"
|
||||
|
||||
name = 'playsourceview'
|
||||
use_plugin_window = False
|
||||
|
||||
def __init__(self):
|
||||
super(PlaySourceView, self).__init__()
|
||||
self.view = self
|
||||
self._has_initialised = False
|
||||
self.show_policy = PlaySourceShowingPolicy(self)
|
||||
|
||||
def initialise(self, source):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
self.view_name = "playsource_view"
|
||||
super(PlaySourceView, self).initialise(source)
|
||||
#self.album_manager = source.album_manager
|
||||
self.shell = source.shell
|
||||
|
||||
def switch_to_view(self, source, album):
|
||||
self.initialise(source)
|
||||
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
source.playlist_source)
|
||||
|
||||
def get_selected_objects(self):
|
||||
'''
|
||||
finds what has been selected
|
||||
|
||||
returns an array of `Album`
|
||||
'''
|
||||
return []
|
||||
@@ -0,0 +1,80 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import GLib
|
||||
|
||||
from coverart_widgets import AbstractView
|
||||
|
||||
|
||||
class QueueShowingPolicy(GObject.Object):
|
||||
'''
|
||||
Policy that mostly takes care of how and when things should be showed on
|
||||
the view that makes use of the `AlbumsModel`.
|
||||
'''
|
||||
|
||||
def __init__(self, list_view):
|
||||
super(QueueShowingPolicy, self).__init__()
|
||||
|
||||
self.counter = 0
|
||||
self._has_initialised = False
|
||||
|
||||
def initialise(self, album_manager):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
|
||||
class QueueView(AbstractView):
|
||||
__gtype_name__ = "QueueView"
|
||||
|
||||
name = 'queueview'
|
||||
use_plugin_window = False
|
||||
|
||||
def __init__(self):
|
||||
super(QueueView, self).__init__()
|
||||
self.view = self
|
||||
self._has_initialised = False
|
||||
self.show_policy = QueueShowingPolicy(self)
|
||||
|
||||
def initialise(self, source):
|
||||
if self._has_initialised:
|
||||
return
|
||||
|
||||
self._has_initialised = True
|
||||
|
||||
self.view_name = "queue_view"
|
||||
super(QueueView, self).initialise(source)
|
||||
#self.album_manager = source.album_manager
|
||||
self.shell = source.shell
|
||||
|
||||
def switch_to_view(self, source, album):
|
||||
self.initialise(source)
|
||||
|
||||
GLib.idle_add(self.shell.props.display_page_tree.select,
|
||||
self.shell.props.queue_source)
|
||||
|
||||
def get_selected_objects(self):
|
||||
'''
|
||||
finds what has been selected
|
||||
|
||||
returns an array of `Album`
|
||||
'''
|
||||
return []
|
||||
@@ -0,0 +1,880 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# IMPORTANT - WHILST THIS MODULE IS USED BY SEVERAL OTHER PLUGINS
|
||||
# THE MASTER AND MOST UP-TO-DATE IS FOUND IN THE COVERART BROWSER
|
||||
# PLUGIN - https://github.com/fossfreedom/coverart-browser
|
||||
# PLEASE SUBMIT CHANGES BACK TO HELP EXPAND THIS API
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gio
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject
|
||||
from gi.repository import RB
|
||||
|
||||
import rb
|
||||
|
||||
|
||||
def pygobject_version():
|
||||
'''
|
||||
returns float of the major and minor parts of a pygobject version
|
||||
e.g. version (3, 9, 5) return float(3.9)
|
||||
'''
|
||||
to_number = lambda t: ".".join(str(v) for v in t)
|
||||
|
||||
str_version = to_number(GObject.pygobject_version)
|
||||
|
||||
return float(str_version.rsplit('.', 1)[0])
|
||||
|
||||
|
||||
def compare_pygobject_version(version):
|
||||
'''
|
||||
return True if version is less than pygobject_version
|
||||
i.e. 3.9 < 3.11
|
||||
'''
|
||||
to_number = lambda t: ".".join(str(v) for v in t)
|
||||
|
||||
str_version = to_number(GObject.pygobject_version)
|
||||
|
||||
split = str_version.rsplit('.', 2)
|
||||
split_compare = version.rsplit('.', 2)
|
||||
|
||||
if int(split_compare[0]) < int(split[0]):
|
||||
return True
|
||||
|
||||
if int(split_compare[1]) < int(split[1]):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
PYVER = sys.version_info[0]
|
||||
|
||||
if PYVER >= 3:
|
||||
import urllib.request, urllib.parse, urllib.error
|
||||
else:
|
||||
import urllib
|
||||
from urlparse import urlparse as rb2urlparse
|
||||
|
||||
if PYVER >= 3:
|
||||
import http.client
|
||||
else:
|
||||
import httplib
|
||||
|
||||
|
||||
def responses():
|
||||
if PYVER >= 3:
|
||||
return http.client.responses
|
||||
else:
|
||||
return httplib.responses
|
||||
|
||||
|
||||
def unicodestr(param, charset):
|
||||
if PYVER >= 3:
|
||||
return param #str(param, charset)
|
||||
else:
|
||||
return unicode(param, charset)
|
||||
|
||||
|
||||
def unicodeencode(param, charset):
|
||||
if PYVER >= 3:
|
||||
return param #str(param).encode(charset)
|
||||
else:
|
||||
return unicode(param).encode(charset)
|
||||
|
||||
|
||||
def unicodedecode(param, charset):
|
||||
if PYVER >= 3:
|
||||
return param
|
||||
else:
|
||||
return param.decode(charset)
|
||||
|
||||
|
||||
def urlparse(uri):
|
||||
if PYVER >= 3:
|
||||
return urllib.parse.urlparse(uri)
|
||||
else:
|
||||
return rb2urlparse(uri)
|
||||
|
||||
|
||||
def url2pathname(url):
|
||||
if PYVER >= 3:
|
||||
return urllib.request.url2pathname(url)
|
||||
else:
|
||||
return urllib.url2pathname(url)
|
||||
|
||||
|
||||
def urlopen(filename):
|
||||
if PYVER >= 3:
|
||||
return urllib.request.urlopen(filename)
|
||||
else:
|
||||
return urllib.urlopen(filename)
|
||||
|
||||
|
||||
def pathname2url(filename):
|
||||
if PYVER >= 3:
|
||||
return urllib.request.pathname2url(filename)
|
||||
else:
|
||||
return urllib.pathname2url(filename)
|
||||
|
||||
|
||||
def unquote(uri):
|
||||
if PYVER >= 3:
|
||||
return urllib.parse.unquote(uri)
|
||||
else:
|
||||
return urllib.unquote(uri)
|
||||
|
||||
|
||||
def quote(uri, safe=None):
|
||||
if PYVER >= 3:
|
||||
if safe:
|
||||
return urllib.parse.quote(uri, safe=safe)
|
||||
else:
|
||||
return urllib.parse.quote(uri)
|
||||
else:
|
||||
if safe:
|
||||
return urllib.quote(uri, safe=safe)
|
||||
else:
|
||||
return urllib.quote(uri)
|
||||
|
||||
|
||||
def quote_plus(uri):
|
||||
if PYVER >= 3:
|
||||
return urllib.parse.quote_plus(uri)
|
||||
else:
|
||||
return urllib.quote_plus(uri)
|
||||
|
||||
|
||||
def is_rb3(*args):
|
||||
if hasattr(RB.Shell.props, 'ui_manager'):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class Menu(GObject.Object):
|
||||
'''
|
||||
Menu object used to create window popup menus
|
||||
'''
|
||||
__gsignals__ = {
|
||||
'pre-popup': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
|
||||
def __init__(self, plugin, shell):
|
||||
'''
|
||||
Initializes the menu.
|
||||
'''
|
||||
super(Menu, self).__init__()
|
||||
self.plugin = plugin
|
||||
self.shell = shell
|
||||
self._unique_num = 0
|
||||
|
||||
self._rbmenu_items = {}
|
||||
self._rbmenu_objects = {}
|
||||
|
||||
def add_menu_item(self, menubar, section_name, action):
|
||||
'''
|
||||
add a new menu item to the popup
|
||||
:param menubar: `str` is the name GtkMenu (or ignored for RB2.99+)
|
||||
:param section_name: `str` is the name of the section to add the item to (RB2.99+)
|
||||
:param action: `Action` to associate with the menu item
|
||||
'''
|
||||
return self.insert_menu_item(menubar, section_name, -1, action)
|
||||
|
||||
def insert_menu_item(self, menubar, section_name, position, action):
|
||||
'''
|
||||
add a new menu item to the popup
|
||||
:param menubar: `str` is the name GtkMenu (or ignored for RB2.99+)
|
||||
:param section_name: `str` is the name of the section to add the item to (RB2.99+)
|
||||
:param position: `int` position to add to GtkMenu (ignored for RB2.99+)
|
||||
:param action: `Action` to associate with the menu item
|
||||
'''
|
||||
label = action.label
|
||||
|
||||
if is_rb3(self.shell):
|
||||
app = self.shell.props.application
|
||||
item = Gio.MenuItem()
|
||||
action.associate_menuitem(item)
|
||||
item.set_label(label)
|
||||
|
||||
if not section_name in self._rbmenu_items:
|
||||
self._rbmenu_items[section_name] = []
|
||||
self._rbmenu_items[section_name].append(label)
|
||||
|
||||
app.add_plugin_menu_item(section_name, label, item)
|
||||
else:
|
||||
item = Gtk.MenuItem(label=label)
|
||||
action.associate_menuitem(item)
|
||||
self._rbmenu_items[label] = item
|
||||
bar = self.get_menu_object(menubar)
|
||||
|
||||
if position == -1:
|
||||
bar.append(item)
|
||||
else:
|
||||
bar.insert(item, position)
|
||||
bar.show_all()
|
||||
uim = self.shell.props.ui_manager
|
||||
uim.ensure_update()
|
||||
|
||||
return item
|
||||
|
||||
def insert_separator(self, menubar, at_position):
|
||||
'''
|
||||
add a separator to the popup (only required for RB2.98 and earlier)
|
||||
:param menubar: `str` is the name GtkMenu (or ignored for RB2.99+)
|
||||
:param position: `int` position to add to GtkMenu (ignored for RB2.99+)
|
||||
'''
|
||||
if not is_rb3(self.shell):
|
||||
menu_item = Gtk.SeparatorMenuItem().new()
|
||||
menu_item.set_visible(True)
|
||||
self._rbmenu_items['separator' + str(self._unique_num)] = menu_item
|
||||
self._unique_num = self._unique_num + 1
|
||||
bar = self.get_menu_object(menubar)
|
||||
bar.insert(menu_item, at_position)
|
||||
bar.show_all()
|
||||
uim = self.shell.props.ui_manager
|
||||
uim.ensure_update()
|
||||
|
||||
def remove_menu_items(self, menubar, section_name):
|
||||
'''
|
||||
utility function to remove all menuitems associated with the menu section
|
||||
:param menubar: `str` is the name of the GtkMenu containing the menu items (ignored for RB2.99+)
|
||||
:param section_name: `str` is the name of the section containing the menu items (for RB2.99+ only)
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
if not section_name in self._rbmenu_items:
|
||||
return
|
||||
|
||||
app = self.shell.props.application
|
||||
|
||||
for menu_item in self._rbmenu_items[section_name]:
|
||||
app.remove_plugin_menu_item(section_name, menu_item)
|
||||
|
||||
if self._rbmenu_items[section_name]:
|
||||
del self._rbmenu_items[section_name][:]
|
||||
|
||||
else:
|
||||
|
||||
if not self._rbmenu_items:
|
||||
return
|
||||
|
||||
uim = self.shell.props.ui_manager
|
||||
bar = self.get_menu_object(menubar)
|
||||
|
||||
for menu_item in self._rbmenu_items:
|
||||
bar.remove(self._rbmenu_items[menu_item])
|
||||
|
||||
bar.show_all()
|
||||
uim.ensure_update()
|
||||
|
||||
def load_from_file(self, rb2_ui_filename, rb3_ui_filename):
|
||||
'''
|
||||
utility function to load the menu structure
|
||||
:param rb2_ui_filename: `str` RB2.98 and below UI file
|
||||
:param rb3_ui_filename: `str` RB2.99 and higher UI file
|
||||
'''
|
||||
self.builder = Gtk.Builder()
|
||||
try:
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
|
||||
cl = CoverLocale()
|
||||
|
||||
self.builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN)
|
||||
except:
|
||||
pass
|
||||
|
||||
if is_rb3(self.shell):
|
||||
ui_filename = rb3_ui_filename
|
||||
else:
|
||||
ui_filename = rb2_ui_filename
|
||||
|
||||
self.ui_filename = ui_filename
|
||||
|
||||
self.builder.add_from_file(rb.find_plugin_file(self.plugin,
|
||||
ui_filename))
|
||||
|
||||
def _connect_rb3_signals(self, signals):
|
||||
def _menu_connect(action_name, func):
|
||||
action = Gio.SimpleAction(name=action_name)
|
||||
action.connect('activate', func)
|
||||
action.set_enabled(True)
|
||||
self.shell.props.window.add_action(action)
|
||||
|
||||
for key, value in signals.items():
|
||||
_menu_connect(key, value)
|
||||
|
||||
def _connect_rb2_signals(self, signals):
|
||||
def _menu_connect(menu_item_name, func):
|
||||
menu_item = self.get_menu_object(menu_item_name)
|
||||
menu_item.connect('activate', func)
|
||||
|
||||
for key, value in signals.items():
|
||||
_menu_connect(key, value)
|
||||
|
||||
def connect_signals(self, signals):
|
||||
'''
|
||||
connect all signal handlers with their menuitem counterparts
|
||||
:param signals: `dict` key is the name of the menuitem
|
||||
and value is the function callback when the menu is activated
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
self._connect_rb3_signals(signals)
|
||||
else:
|
||||
self._connect_rb2_signals(signals)
|
||||
|
||||
def get_gtkmenu(self, source, popup_name):
|
||||
'''
|
||||
utility function to obtain the GtkMenu from the menu UI file
|
||||
:param popup_name: `str` is the name menu-id in the UI file
|
||||
'''
|
||||
if popup_name in self._rbmenu_objects:
|
||||
return self._rbmenu_objects[popup_name]
|
||||
item = self.builder.get_object(popup_name)
|
||||
|
||||
if is_rb3(self.shell):
|
||||
app = self.shell.props.application
|
||||
app.link_shared_menus(item)
|
||||
popup_menu = Gtk.Menu.new_from_model(item)
|
||||
popup_menu.attach_to_widget(source, None)
|
||||
else:
|
||||
popup_menu = item
|
||||
|
||||
self._rbmenu_objects[popup_name] = popup_menu
|
||||
|
||||
return popup_menu
|
||||
|
||||
def get_menu_object(self, menu_name_or_link):
|
||||
'''
|
||||
utility function returns the GtkMenuItem/Gio.MenuItem
|
||||
:param menu_name_or_link: `str` to search for in the UI file
|
||||
'''
|
||||
if menu_name_or_link in self._rbmenu_objects:
|
||||
return self._rbmenu_objects[menu_name_or_link]
|
||||
item = self.builder.get_object(menu_name_or_link)
|
||||
if is_rb3(self.shell):
|
||||
if item:
|
||||
popup_menu = item
|
||||
else:
|
||||
app = self.shell.props.application
|
||||
popup_menu = app.get_plugin_menu(menu_name_or_link)
|
||||
else:
|
||||
popup_menu = item
|
||||
print(menu_name_or_link)
|
||||
self._rbmenu_objects[menu_name_or_link] = popup_menu
|
||||
|
||||
return popup_menu
|
||||
|
||||
def set_sensitive(self, menu_or_action_item, enable):
|
||||
'''
|
||||
utility function to enable/disable a menu-item
|
||||
:param menu_or_action_item: `GtkMenuItem` or `Gio.SimpleAction`
|
||||
that is to be enabled/disabled
|
||||
:param enable: `bool` value to enable/disable
|
||||
'''
|
||||
|
||||
if is_rb3(self.shell):
|
||||
item = self.shell.props.window.lookup_action(menu_or_action_item)
|
||||
item.set_enabled(enable)
|
||||
else:
|
||||
item = self.get_menu_object(menu_or_action_item)
|
||||
item.set_sensitive(enable)
|
||||
|
||||
def popup(self, source, menu_name, button, time):
|
||||
'''
|
||||
utility function to show the popup menu
|
||||
'''
|
||||
self.emit('pre-popup')
|
||||
menu = self.get_gtkmenu(source, menu_name)
|
||||
menu.popup(None, None, None, None, button, time)
|
||||
|
||||
|
||||
class ActionGroup(object):
|
||||
'''
|
||||
container for all Actions used to associate with menu items
|
||||
'''
|
||||
|
||||
# action_state
|
||||
STANDARD = 0
|
||||
TOGGLE = 1
|
||||
|
||||
def __init__(self, shell, group_name):
|
||||
'''
|
||||
constructor
|
||||
:param shell: `RBShell`
|
||||
:param group_name: `str` unique name for the object to create
|
||||
'''
|
||||
self.group_name = group_name
|
||||
self.shell = shell
|
||||
|
||||
self._actions = {}
|
||||
|
||||
if is_rb3(self.shell):
|
||||
self.actiongroup = Gio.SimpleActionGroup()
|
||||
else:
|
||||
self.actiongroup = Gtk.ActionGroup(group_name)
|
||||
uim = self.shell.props.ui_manager
|
||||
uim.insert_action_group(self.actiongroup)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.group_name
|
||||
|
||||
def remove_actions(self):
|
||||
'''
|
||||
utility function to remove all actions associated with the ActionGroup
|
||||
'''
|
||||
for action in self.actiongroup.list_actions():
|
||||
self.actiongroup.remove_action(action)
|
||||
|
||||
def get_action(self, action_name):
|
||||
'''
|
||||
utility function to obtain the Action from the ActionGroup
|
||||
|
||||
:param action_name: `str` is the Action unique name
|
||||
'''
|
||||
return self._actions[action_name]
|
||||
|
||||
def add_action_with_accel(self, func, action_name, accel, **args):
|
||||
'''
|
||||
Creates an Action with an accelerator and adds it to the ActionGroup
|
||||
|
||||
:param func: function callback used when user activates the action
|
||||
:param action_name: `str` unique name to associate with an action
|
||||
:param accel: `str` accelerator
|
||||
:param args: dict of arguments - this is passed to the function callback
|
||||
|
||||
Notes:
|
||||
see notes for add_action
|
||||
'''
|
||||
args['accel'] = accel
|
||||
return self.add_action(func, action_name, **args)
|
||||
|
||||
def add_action(self, func, action_name, **args):
|
||||
'''
|
||||
Creates an Action and adds it to the ActionGroup
|
||||
|
||||
:param func: function callback used when user activates the action
|
||||
:param action_name: `str` unique name to associate with an action
|
||||
:param args: dict of arguments - this is passed to the function callback
|
||||
|
||||
Notes:
|
||||
key value of "label" is the visual menu label to display
|
||||
key value of "action_type" is the RB2.99 Gio.Action type ("win" or "app")
|
||||
by default it assumes all actions are "win" type
|
||||
key value of "action_state" determines what action state to create
|
||||
'''
|
||||
if 'label' in args:
|
||||
label = args['label']
|
||||
else:
|
||||
label = action_name
|
||||
|
||||
if 'accel' in args:
|
||||
accel = args['accel']
|
||||
else:
|
||||
accel = None
|
||||
|
||||
state = ActionGroup.STANDARD
|
||||
if 'action_state' in args:
|
||||
state = args['action_state']
|
||||
|
||||
if is_rb3(self.shell):
|
||||
if state == ActionGroup.TOGGLE:
|
||||
action = Gio.SimpleAction.new_stateful(action_name, None,
|
||||
GLib.Variant('b', False))
|
||||
else:
|
||||
action = Gio.SimpleAction.new(action_name, None)
|
||||
|
||||
action_type = 'win'
|
||||
if 'action_type' in args:
|
||||
if args['action_type'] == 'app':
|
||||
action_type = 'app'
|
||||
|
||||
app = Gio.Application.get_default()
|
||||
|
||||
if action_type == 'app':
|
||||
app.add_action(action)
|
||||
else:
|
||||
self.shell.props.window.add_action(action)
|
||||
self.actiongroup.add_action(action)
|
||||
|
||||
if accel:
|
||||
app.add_accelerator(accel, action_type + "." + action_name, None)
|
||||
else:
|
||||
if 'stock_id' in args:
|
||||
stock_id = args['stock_id']
|
||||
else:
|
||||
stock_id = Gtk.STOCK_CLEAR
|
||||
|
||||
if state == ActionGroup.TOGGLE:
|
||||
action = Gtk.ToggleAction(label=label,
|
||||
name=action_name,
|
||||
tooltip='', stock_id=stock_id)
|
||||
else:
|
||||
action = Gtk.Action(label=label,
|
||||
name=action_name,
|
||||
tooltip='', stock_id=stock_id)
|
||||
|
||||
if accel:
|
||||
self.actiongroup.add_action_with_accel(action, accel)
|
||||
else:
|
||||
self.actiongroup.add_action(action)
|
||||
|
||||
act = Action(self.shell, action)
|
||||
act.connect('activate', func, args)
|
||||
|
||||
act.label = label
|
||||
act.accel = accel
|
||||
|
||||
self._actions[action_name] = act
|
||||
|
||||
return act
|
||||
|
||||
|
||||
class ApplicationShell(object):
|
||||
'''
|
||||
Unique class that mirrors RB.Application & RB.Shell menu functionality
|
||||
'''
|
||||
# storage for the instance reference
|
||||
__instance = None
|
||||
|
||||
class __impl:
|
||||
""" Implementation of the singleton interface """
|
||||
|
||||
def __init__(self, shell):
|
||||
self.shell = shell
|
||||
|
||||
if is_rb3(self.shell):
|
||||
self._uids = {}
|
||||
else:
|
||||
self._uids = []
|
||||
|
||||
self._action_groups = {}
|
||||
|
||||
def insert_action_group(self, action_group):
|
||||
'''
|
||||
Adds an ActionGroup to the ApplicationShell
|
||||
|
||||
:param action_group: `ActionGroup` to add
|
||||
'''
|
||||
self._action_groups[action_group.name] = action_group
|
||||
|
||||
def lookup_action(self, action_group_name, action_name, action_type='app'):
|
||||
'''
|
||||
looks up (finds) an action created by another plugin. If found returns
|
||||
an Action or None if no matching Action.
|
||||
|
||||
:param action_group_name: `str` is the Gtk.ActionGroup name (ignored for RB2.99+)
|
||||
:param action_name: `str` unique name for the action to look for
|
||||
:param action_type: `str` RB2.99+ action type ("win" or "app")
|
||||
'''
|
||||
|
||||
if is_rb3(self.shell):
|
||||
if action_type == "app":
|
||||
action = self.shell.props.application.lookup_action(action_name)
|
||||
else:
|
||||
action = self.shell.props.window.lookup_action(action_name)
|
||||
else:
|
||||
uim = self.shell.props.ui_manager
|
||||
ui_actiongroups = uim.get_action_groups()
|
||||
|
||||
actiongroup = None
|
||||
for actiongroup in ui_actiongroups:
|
||||
if actiongroup.get_name() == action_group_name:
|
||||
break
|
||||
|
||||
action = None
|
||||
if actiongroup:
|
||||
action = actiongroup.get_action(action_name)
|
||||
|
||||
if action:
|
||||
return Action(self.shell, action)
|
||||
else:
|
||||
return None
|
||||
|
||||
def add_app_menuitems(self, ui_string, group_name, menu='tools'):
|
||||
'''
|
||||
utility function to add application menu items.
|
||||
|
||||
For RB2.99 all application menu items are added to the "tools" section of the
|
||||
application menu. All Actions are assumed to be of action_type "app".
|
||||
|
||||
For RB2.98 or less, it is added however the UI_MANAGER string
|
||||
is defined.
|
||||
|
||||
:param ui_string: `str` is the Gtk UI definition. There is not an
|
||||
equivalent UI definition in RB2.99 but we can parse out menu items since
|
||||
this string is in XML format
|
||||
|
||||
:param group_name: `str` unique name of the ActionGroup to add menu items to
|
||||
:param menu: `str` RB2.99 menu section to add to - nominally either
|
||||
'tools' or 'view'
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
root = ET.fromstring(ui_string)
|
||||
for elem in root.findall(".//menuitem"):
|
||||
action_name = elem.attrib['action']
|
||||
item_name = elem.attrib['name']
|
||||
|
||||
group = self._action_groups[group_name]
|
||||
act = group.get_action(action_name)
|
||||
|
||||
item = Gio.MenuItem()
|
||||
item.set_detailed_action('app.' + action_name)
|
||||
item.set_label(act.label)
|
||||
item.set_attribute_value("accel", GLib.Variant("s", act.accel))
|
||||
app = Gio.Application.get_default()
|
||||
index = menu + action_name
|
||||
app.add_plugin_menu_item(menu,
|
||||
index, item)
|
||||
self._uids[index] = menu
|
||||
else:
|
||||
uim = self.shell.props.ui_manager
|
||||
self._uids.append(uim.add_ui_from_string(ui_string))
|
||||
uim.ensure_update()
|
||||
|
||||
def add_browser_menuitems(self, ui_string, group_name):
|
||||
'''
|
||||
utility function to add popup menu items to existing browser popups
|
||||
|
||||
For RB2.99 all menu items are are assumed to be of action_type "win".
|
||||
|
||||
For RB2.98 or less, it is added however the UI_MANAGER string
|
||||
is defined.
|
||||
|
||||
:param ui_string: `str` is the Gtk UI definition. There is not an
|
||||
equivalent UI definition in RB2.99 but we can parse out menu items since
|
||||
this string is in XML format
|
||||
|
||||
:param group_name: `str` unique name of the ActionGroup to add menu items to
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
root = ET.fromstring(ui_string)
|
||||
for elem in root.findall("./popup"):
|
||||
popup_name = elem.attrib['name']
|
||||
|
||||
menuelem = elem.find('.//menuitem')
|
||||
action_name = menuelem.attrib['action']
|
||||
item_name = menuelem.attrib['name']
|
||||
|
||||
group = self._action_groups[group_name]
|
||||
act = group.get_action(action_name)
|
||||
|
||||
item = Gio.MenuItem()
|
||||
item.set_detailed_action('win.' + action_name)
|
||||
item.set_label(act.label)
|
||||
app = Gio.Application.get_default()
|
||||
|
||||
if popup_name == 'QueuePlaylistViewPopup':
|
||||
plugin_type = 'queue-popup'
|
||||
elif popup_name == 'BrowserSourceViewPopup':
|
||||
plugin_type = 'browser-popup'
|
||||
elif popup_name == 'PlaylistViewPopup':
|
||||
plugin_type = 'playlist-popup'
|
||||
elif popup_name == 'PodcastViewPopup':
|
||||
plugin_type = 'podcast-episode-popup'
|
||||
else:
|
||||
print("unknown type %s" % plugin_type)
|
||||
|
||||
index = plugin_type + action_name
|
||||
app.add_plugin_menu_item(plugin_type, index, item)
|
||||
self._uids[index] = plugin_type
|
||||
else:
|
||||
uim = self.shell.props.ui_manager
|
||||
self._uids.append(uim.add_ui_from_string(ui_string))
|
||||
uim.ensure_update()
|
||||
|
||||
def cleanup(self):
|
||||
'''
|
||||
utility remove any menuitems created.
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
for uid in self._uids:
|
||||
Gio.Application.get_default().remove_plugin_menu_item(self._uids[uid],
|
||||
uid)
|
||||
else:
|
||||
uim = self.shell.props.ui_manager
|
||||
for uid in self._uids:
|
||||
uim.remove_ui(uid)
|
||||
uim.ensure_update();
|
||||
|
||||
def __init__(self, shell):
|
||||
""" Create singleton instance """
|
||||
# Check whether we already have an instance
|
||||
if ApplicationShell.__instance is None:
|
||||
# Create and remember instance
|
||||
ApplicationShell.__instance = ApplicationShell.__impl(shell)
|
||||
|
||||
# Store instance reference as the only member in the handle
|
||||
self.__dict__['_ApplicationShell__instance'] = ApplicationShell.__instance
|
||||
|
||||
def __getattr__(self, attr):
|
||||
""" Delegate access to implementation """
|
||||
return getattr(self.__instance, attr)
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
""" Delegate access to implementation """
|
||||
return setattr(self.__instance, attr, value)
|
||||
|
||||
|
||||
class Action(object):
|
||||
'''
|
||||
class that wraps around either a Gio.Action or a Gtk.Action
|
||||
'''
|
||||
|
||||
def __init__(self, shell, action):
|
||||
'''
|
||||
constructor.
|
||||
|
||||
:param shell: `RBShell`
|
||||
:param action: `Gio.Action` or `Gtk.Action`
|
||||
'''
|
||||
self.shell = shell
|
||||
self.action = action
|
||||
|
||||
self._label = ''
|
||||
self._accel = ''
|
||||
self._current_state = False
|
||||
self._do_update_state = True
|
||||
|
||||
def connect(self, address, func, args):
|
||||
self._connect_func = func
|
||||
self._connect_args = args
|
||||
|
||||
if address == 'activate':
|
||||
func = self._activate
|
||||
|
||||
if is_rb3(self.shell):
|
||||
self.action.connect(address, func, args)
|
||||
else:
|
||||
self.action.connect(address, func, None, args)
|
||||
|
||||
def _activate(self, action, *args):
|
||||
if self._do_update_state:
|
||||
self._current_state = not self._current_state
|
||||
self.set_state(self._current_state)
|
||||
|
||||
self._connect_func(action, None, self._connect_args)
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
'''
|
||||
get the menu label associated with the Action
|
||||
|
||||
for RB2.99+ actions dont have menu labels so this is managed
|
||||
manually
|
||||
'''
|
||||
if not is_rb3(self.shell):
|
||||
return self.action.get_label()
|
||||
else:
|
||||
return self._label
|
||||
|
||||
@label.setter
|
||||
def label(self, new_label):
|
||||
if not is_rb3(self.shell):
|
||||
self.action.set_label(new_label)
|
||||
|
||||
self._label = new_label
|
||||
|
||||
@property
|
||||
def accel(self):
|
||||
'''
|
||||
get the accelerator associated with the Action
|
||||
'''
|
||||
return self._accel
|
||||
|
||||
@accel.setter
|
||||
def accel(self, new_accelerator):
|
||||
if new_accelerator:
|
||||
self._accel = new_accelerator
|
||||
else:
|
||||
self._accel = ''
|
||||
|
||||
def get_sensitive(self):
|
||||
'''
|
||||
get the sensitivity (enabled/disabled) state of the Action
|
||||
|
||||
returns boolean
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
return self.action.get_enabled()
|
||||
else:
|
||||
return self.action.get_sensitive()
|
||||
|
||||
def set_state(self, value):
|
||||
'''
|
||||
set the state of a stateful action - this is applicable only
|
||||
to RB2.99+
|
||||
'''
|
||||
if is_rb3(self.shell) and self.action.props.state_type:
|
||||
self.action.change_state(GLib.Variant('b', value))
|
||||
|
||||
def activate(self):
|
||||
'''
|
||||
invokes the activate signal for the action
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
self.action.activate(None)
|
||||
else:
|
||||
self.action.activate()
|
||||
|
||||
def set_active(self, value):
|
||||
'''
|
||||
activate or deactivate a stateful action signal
|
||||
For consistency with earlier RB versions, this will fire the
|
||||
activate signal for the action
|
||||
|
||||
:param value: `boolean` state value
|
||||
'''
|
||||
|
||||
if is_rb3(self.shell):
|
||||
self.action.change_state(GLib.Variant('b', value))
|
||||
self._current_state = value
|
||||
self._do_update_state = False
|
||||
self.activate()
|
||||
self._do_update_state = True
|
||||
else:
|
||||
self.action.set_active(value)
|
||||
|
||||
def get_active(self):
|
||||
'''
|
||||
get the state of the action
|
||||
|
||||
returns `boolean` state value
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
returnval = self._current_state
|
||||
else:
|
||||
returnval = self.action.get_active()
|
||||
|
||||
return returnval
|
||||
|
||||
def associate_menuitem(self, menuitem):
|
||||
'''
|
||||
links a menu with the action
|
||||
|
||||
'''
|
||||
if is_rb3(self.shell):
|
||||
menuitem.set_detailed_action('win.' + self.action.get_name())
|
||||
else:
|
||||
menuitem.set_related_action(self.action)
|
||||
|
||||
|
||||
@@ -18,60 +18,65 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import rb
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import WebKit
|
||||
from mako.template import Template
|
||||
|
||||
from coverart_album import AlbumManager
|
||||
import rb
|
||||
import coverart_rb3compat as rb3compat
|
||||
from coverart_album import Album
|
||||
from coverart_browser_prefs import webkit_support
|
||||
|
||||
|
||||
class CoverSearchPane(Gtk.Box):
|
||||
'''
|
||||
This UI represents a pane where different album's covers can be presented
|
||||
given an album to look for. It also allows to make custom image searchs,
|
||||
This UI represents a pane where different covers can be presented
|
||||
given an album or artist to look for. It also allows to make custom image searchs,
|
||||
customize the default search and select covers from the pane and use them
|
||||
as the album covers (either with a double click or draging them).
|
||||
as the covers (either with a double click or dragging them).
|
||||
'''
|
||||
def __init__(self, plugin, album_manager, selection_color):
|
||||
|
||||
def __init__(self, plugin, selection_color):
|
||||
'''
|
||||
Initializes the pane, loading it's html templates and it's ui.
|
||||
'''
|
||||
super(CoverSearchPane, self).__init__()
|
||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
self.album_manager = album_manager
|
||||
self.selection_color = selection_color
|
||||
|
||||
self.file = ""
|
||||
self.basepath = 'file://' + plugin.plugin_info.get_data_dir()
|
||||
|
||||
self.load_templates(plugin)
|
||||
self.init_gui()
|
||||
if webkit_support():
|
||||
self.init_gui()
|
||||
|
||||
# init the pane with the empty template
|
||||
self.clear()
|
||||
# init the pane with the empty template
|
||||
self.clear()
|
||||
|
||||
def load_templates(self, plugin):
|
||||
'''
|
||||
Loads the templates and stylesheets to be used by the pane.
|
||||
'''
|
||||
# input_encoding='utf-8',
|
||||
# input_encoding='utf-8',
|
||||
|
||||
path = rb.find_plugin_file(plugin,
|
||||
'tmpl/albumartsearch-tmpl.html')
|
||||
'tmpl/albumartsearch-tmpl.html')
|
||||
self.template = Template(filename=path,
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
output_encoding='utf-8',
|
||||
encoding_errors='replace')
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
path = rb.find_plugin_file(plugin,
|
||||
'tmpl/albumartsearchempty-tmpl.html')
|
||||
'tmpl/albumartsearchempty-tmpl.html')
|
||||
self.empty_template = Template(filename=path,
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
output_encoding='utf-8',
|
||||
encoding_errors='replace')
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
path = rb.find_plugin_file(plugin,
|
||||
'tmpl/artistartsearch-tmpl.html')
|
||||
self.artist_template = Template(filename=path,
|
||||
default_filters=['decode.utf8'],
|
||||
module_directory='/tmp/',
|
||||
encoding_errors='replace')
|
||||
self.styles = rb.find_plugin_file(plugin, 'tmpl/main.css')
|
||||
|
||||
def init_gui(self):
|
||||
@@ -79,6 +84,8 @@ class CoverSearchPane(Gtk.Box):
|
||||
Initializes the pane ui.
|
||||
'''
|
||||
#---- set up webkit pane -----#
|
||||
from gi.repository import WebKit
|
||||
|
||||
self.webview = WebKit.WebView()
|
||||
settings = self.webview.get_settings()
|
||||
settings.set_property('enable-default-context-menu', False)
|
||||
@@ -91,64 +98,91 @@ class CoverSearchPane(Gtk.Box):
|
||||
self.show_all()
|
||||
|
||||
# connect the title changed signal
|
||||
#self.webview.connect('title-changed', self.set_cover)
|
||||
self.webview.connect('notify::title', self.set_cover)
|
||||
|
||||
def do_search(self, album):
|
||||
def do_search(self, coverobject, callback):
|
||||
'''
|
||||
When this method is called, the webview gets refreshed with the info
|
||||
of the album passed.
|
||||
of the album or artist passed.
|
||||
|
||||
'''
|
||||
if album is self.current_album:
|
||||
print("coverart-search do_search")
|
||||
if coverobject is self.current_searchobject:
|
||||
return
|
||||
|
||||
self.current_album = album
|
||||
self.current_searchobject = coverobject
|
||||
self.callback = callback
|
||||
|
||||
artist = album.artist
|
||||
album_name = album.name
|
||||
if isinstance(coverobject, Album):
|
||||
artist = coverobject.artist
|
||||
album_name = coverobject.name
|
||||
|
||||
if album_name.upper() == "UNKNOWN":
|
||||
album_name = ""
|
||||
if album_name.upper() == "UNKNOWN":
|
||||
album_name = ""
|
||||
|
||||
if artist.upper() == "UNKNOWN":
|
||||
artist = ""
|
||||
if artist.upper() == "UNKNOWN":
|
||||
artist = ""
|
||||
|
||||
if not (album_name == "" and artist == ""):
|
||||
artist = rb3compat.unicodestr(artist.replace('&', '&'),
|
||||
'utf-8')
|
||||
album_name = rb3compat.unicodestr(album_name.replace('&', '&'), 'utf-8')
|
||||
self.render_album_art_search(artist, album_name)
|
||||
else:
|
||||
artist_name = coverobject.name
|
||||
|
||||
if artist_name.upper() == "UNKNOWN":
|
||||
artist_name = ""
|
||||
|
||||
if not (artist_name == ""):
|
||||
artist = rb3compat.unicodestr(artist_name.replace('&', '&'),
|
||||
'utf-8')
|
||||
self.render_artist_art_search(artist)
|
||||
|
||||
if not(album_name == "" and artist == ""):
|
||||
artist = unicode(artist.replace('&', '&'),
|
||||
'utf-8')
|
||||
album_name = unicode(album_name.replace('&', '&'), 'utf-8')
|
||||
self.render_album_art_search(artist, album_name)
|
||||
|
||||
def render_album_art_search(self, artist, album_name):
|
||||
'''
|
||||
Renders the template on the webview.
|
||||
'''
|
||||
temp_file = self.template.render(artist=artist, album=album_name,
|
||||
stylesheet=self.styles, selection_color=self.selection_color)
|
||||
stylesheet=self.styles, selection_color=self.selection_color)
|
||||
|
||||
print("here")
|
||||
self.webview.load_string(temp_file, 'text/html', 'utf-8',
|
||||
self.basepath)
|
||||
self.basepath)
|
||||
|
||||
def render_artist_art_search(self, artist):
|
||||
'''
|
||||
Renders the template on the webview.
|
||||
'''
|
||||
temp_file = self.artist_template.render(artist=artist,
|
||||
stylesheet=self.styles, selection_color=self.selection_color)
|
||||
|
||||
print("here")
|
||||
self.webview.load_string(temp_file, 'text/html', 'utf-8',
|
||||
self.basepath)
|
||||
|
||||
def clear(self):
|
||||
'''
|
||||
Clears the webview of any album's specific info/covers.
|
||||
Clears the webview of any specific info/covers.
|
||||
'''
|
||||
self.current_album = None
|
||||
self.current_searchobject = None
|
||||
temp_file = self.empty_template.render(stylesheet=self.styles)
|
||||
|
||||
self.webview.load_string(temp_file, 'text/html', 'utf-8',
|
||||
self.basepath)
|
||||
self.basepath)
|
||||
|
||||
def set_cover(self, webview, arg):
|
||||
'''
|
||||
Callback called when a image in the pane is double-clicked. It takes
|
||||
care of asking the AlbumLoader to update the album's cover.
|
||||
care of updating the searched object cover.
|
||||
Some titles have spurious characters beginning with % - remove these
|
||||
'''
|
||||
# update the cover
|
||||
title = webview.get_title()
|
||||
|
||||
print title
|
||||
print(title)
|
||||
if title:
|
||||
self.album_manager.cover_man.update_cover(self.current_album,
|
||||
uri=title)
|
||||
#self.album_manager.cover_man.update_cover(self.current_searchobject,
|
||||
# uri=title)
|
||||
self.callback(self.current_searchobject, uri=title)
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
#
|
||||
# Copyright (C) 2012 - fossfreedom
|
||||
# Copyright (C) 2012 - Agustin Carrasco
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import RB
|
||||
from gi.repository import Gio
|
||||
|
||||
from coverart_browser_prefs import GSetting
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
from coverart_utils import Theme
|
||||
from coverart_controllers import PlaylistPopupController
|
||||
from coverart_controllers import GenrePopupController
|
||||
from coverart_controllers import SortPopupController
|
||||
from coverart_controllers import ArtistSortPopupController
|
||||
from coverart_controllers import PropertiesMenuController
|
||||
from coverart_controllers import DecadePopupController
|
||||
from coverart_controllers import SortOrderToggleController
|
||||
from coverart_controllers import ArtistSortOrderToggleController
|
||||
from coverart_controllers import AlbumSearchEntryController
|
||||
from coverart_widgets import SearchEntry
|
||||
from coverart_browser_prefs import webkit_support
|
||||
import rb
|
||||
|
||||
|
||||
class Toolbar(GObject.Object):
|
||||
def __init__(self, plugin, mainbox, controllers):
|
||||
super(Toolbar, self).__init__()
|
||||
|
||||
self.plugin = plugin
|
||||
self.mainbox = mainbox
|
||||
cl = CoverLocale()
|
||||
|
||||
ui_file = rb.find_plugin_file(plugin, self.ui)
|
||||
|
||||
# create the toolbar
|
||||
builder = Gtk.Builder()
|
||||
builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
builder.add_from_file(ui_file)
|
||||
|
||||
# assign the controllers to the buttons
|
||||
for button, controller in controllers.items():
|
||||
if button != 'search':
|
||||
builder.get_object(button).controller = controller
|
||||
|
||||
if not webkit_support():
|
||||
#button = builder.get_object('flowview_button')
|
||||
#button.set_visible(False)
|
||||
separator = builder.get_object('properties_separator')
|
||||
if separator:
|
||||
separator.set_visible(False)
|
||||
|
||||
# workaround to translate the search entry tooltips
|
||||
cl.switch_locale(cl.Locale.RB)
|
||||
search_entry = SearchEntry(has_popup=True)
|
||||
search_entry.show_all()
|
||||
cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
|
||||
|
||||
# add it to the ui
|
||||
align = builder.get_object('entry_search_alignment')
|
||||
align.add(search_entry)
|
||||
|
||||
# assign the controller
|
||||
search_entry.controller = controllers['search']
|
||||
|
||||
Theme(self.plugin).connect('theme_changed', self._theme_changed,
|
||||
controllers)
|
||||
|
||||
self.builder = builder.get_object('toolbar')
|
||||
|
||||
#now theme the toolbar including child objects such as the button popups
|
||||
style_context = self.builder.get_style_context()
|
||||
style_context.add_class(Gtk.STYLE_CLASS_TOOLBAR)
|
||||
|
||||
def _theme_changed(self, toolbar, controllers):
|
||||
for controller in list(controllers.values()):
|
||||
controller.update_images(True)
|
||||
|
||||
|
||||
class TopToolbar(Toolbar):
|
||||
ui = 'ui/coverart_topbar.ui'
|
||||
name = 'main'
|
||||
|
||||
def hide(self):
|
||||
if self.builder.get_visible():
|
||||
self.builder.hide()
|
||||
|
||||
def show(self):
|
||||
self.mainbox.pack_start(self.builder, False, True, 0)
|
||||
self.mainbox.reorder_child(self.builder, 0)
|
||||
self.builder.show()
|
||||
|
||||
|
||||
class LeftToolbar(Toolbar):
|
||||
ui = 'ui/coverart_leftsidebar.ui'
|
||||
name = 'left'
|
||||
|
||||
def hide(self):
|
||||
if self.builder.get_visible():
|
||||
self.builder.hide()
|
||||
self.plugin.shell.remove_widget(self.builder,
|
||||
RB.ShellUILocation.SIDEBAR)
|
||||
|
||||
def show(self):
|
||||
self.plugin.shell.add_widget(self.builder,
|
||||
RB.ShellUILocation.SIDEBAR, expand=False, fill=False)
|
||||
self.builder.show()
|
||||
|
||||
|
||||
class RightToolbar(Toolbar):
|
||||
ui = 'ui/coverart_rightsidebar.ui'
|
||||
name = 'right'
|
||||
|
||||
def hide(self):
|
||||
if self.builder.get_visible():
|
||||
self.builder.hide()
|
||||
self.plugin.shell.remove_widget(self.builder,
|
||||
RB.ShellUILocation.RIGHT_SIDEBAR)
|
||||
|
||||
def show(self):
|
||||
self.plugin.shell.add_widget(self.builder,
|
||||
RB.ShellUILocation.RIGHT_SIDEBAR, expand=False, fill=False)
|
||||
self.builder.show()
|
||||
|
||||
|
||||
class ToolbarObject(object):
|
||||
#properties
|
||||
|
||||
PROPERTIES = 'properties_button'
|
||||
SORT_BY = 'sort_by'
|
||||
SORT_ORDER = 'sort_order'
|
||||
SORT_BY_ARTIST = 'sort_by_artist'
|
||||
SORT_ORDER_ARTIST = 'sort_order_artist'
|
||||
GENRE = 'genre_button'
|
||||
PLAYLIST = 'playlist_button'
|
||||
DECADE = 'decade_button'
|
||||
SEARCH = 'search'
|
||||
VIEW = 'view_button'
|
||||
|
||||
|
||||
class ToolbarManager(GObject.Object):
|
||||
# properties
|
||||
toolbar_pos = GObject.property(type=str, default=TopToolbar.name)
|
||||
|
||||
def __init__(self, plugin, main_box, viewmgr):
|
||||
super(ToolbarManager, self).__init__()
|
||||
self.plugin = plugin
|
||||
# create the buttons controllers
|
||||
controllers = self._create_controllers(plugin, viewmgr)
|
||||
|
||||
# initialize toolbars
|
||||
self._bars = {}
|
||||
self._bars[TopToolbar.name] = TopToolbar(plugin, main_box,
|
||||
controllers)
|
||||
self._bars[LeftToolbar.name] = LeftToolbar(plugin, main_box,
|
||||
controllers)
|
||||
self._bars[RightToolbar.name] = RightToolbar(plugin, main_box,
|
||||
controllers)
|
||||
|
||||
self.last_toolbar_pos = None
|
||||
# connect signal and properties
|
||||
self._connect_signals()
|
||||
self._connect_properties()
|
||||
|
||||
self._controllers = controllers
|
||||
|
||||
def set_enabled(self, enabled, toolbar_object=None):
|
||||
'''
|
||||
enable or disable the toolbar object.
|
||||
|
||||
:param enabled: `bool` value.
|
||||
:param toolbar_object: `ToolbarObject`
|
||||
None if enabled is to apply to all objects in the toolbar
|
||||
|
||||
'''
|
||||
if toolbar_object:
|
||||
self._controllers[toolbar_object].enabled = enabled
|
||||
else:
|
||||
for controller in self._controllers:
|
||||
self._controllers[controller].enabled = enabled
|
||||
|
||||
def _connect_signals(self):
|
||||
self.connect('notify::toolbar-pos', self._on_notify_toolbar_pos)
|
||||
|
||||
def _connect_properties(self):
|
||||
gs = GSetting()
|
||||
setting = gs.get_setting(gs.Path.PLUGIN)
|
||||
setting.bind(gs.PluginKey.TOOLBAR_POS, self, 'toolbar_pos',
|
||||
Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _create_controllers(self, plugin, viewmgr):
|
||||
controllers = {}
|
||||
|
||||
album_model = viewmgr.source.album_manager.model
|
||||
controllers[ToolbarObject.PROPERTIES] = \
|
||||
PropertiesMenuController(plugin, viewmgr.source)
|
||||
controllers[ToolbarObject.SORT_BY] = \
|
||||
SortPopupController(plugin, viewmgr)
|
||||
controllers[ToolbarObject.SORT_ORDER] = \
|
||||
SortOrderToggleController(plugin, viewmgr)
|
||||
controllers[ToolbarObject.SORT_BY_ARTIST] = \
|
||||
ArtistSortPopupController(plugin, viewmgr)
|
||||
controllers[ToolbarObject.SORT_ORDER_ARTIST] = \
|
||||
ArtistSortOrderToggleController(plugin, viewmgr)
|
||||
controllers[ToolbarObject.GENRE] = \
|
||||
GenrePopupController(plugin, album_model)
|
||||
controllers[ToolbarObject.PLAYLIST] = \
|
||||
PlaylistPopupController(plugin, album_model)
|
||||
controllers[ToolbarObject.DECADE] = \
|
||||
DecadePopupController(plugin, album_model)
|
||||
controllers[ToolbarObject.SEARCH] = \
|
||||
AlbumSearchEntryController(album_model)
|
||||
|
||||
controllers[ToolbarObject.VIEW] = viewmgr.controller
|
||||
|
||||
return controllers
|
||||
|
||||
def _on_notify_toolbar_pos(self, *args):
|
||||
if self.last_toolbar_pos:
|
||||
self._bars[self.last_toolbar_pos].hide()
|
||||
|
||||
self._bars[self.toolbar_pos].show()
|
||||
|
||||
self.last_toolbar_pos = self.toolbar_pos
|
||||
@@ -15,6 +15,12 @@
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from bisect import bisect_left, bisect_right
|
||||
import collections
|
||||
import re
|
||||
import logging
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
|
||||
from gi.repository import GdkPixbuf
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import Gtk
|
||||
@@ -23,17 +29,73 @@ from gi.repository import RB
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gio
|
||||
import lxml.etree as ET
|
||||
|
||||
import rb
|
||||
from coverart_browser_prefs import CoverLocale
|
||||
from coverart_browser_prefs import GSetting
|
||||
import collections
|
||||
import re
|
||||
import urllib
|
||||
import coverart_rb3compat as rb3compat
|
||||
from coverart_search_providers import lastfm_connected
|
||||
from coverart_search_providers import get_search_providers
|
||||
|
||||
|
||||
class FauxTb(object):
|
||||
def __init__(self, tb_frame, tb_lineno, tb_next):
|
||||
self.tb_frame = tb_frame
|
||||
self.tb_lineno = tb_lineno
|
||||
self.tb_next = tb_next
|
||||
|
||||
|
||||
def current_stack(skip=0):
|
||||
try:
|
||||
1 / 0
|
||||
except ZeroDivisionError:
|
||||
f = sys.exc_info()[2].tb_frame
|
||||
for i in range(skip + 2):
|
||||
f = f.f_back
|
||||
lst = []
|
||||
while f is not None:
|
||||
lst.append((f, f.f_lineno))
|
||||
f = f.f_back
|
||||
return lst
|
||||
|
||||
|
||||
def extend_traceback(tb, stack):
|
||||
"""Extend traceback with stack info."""
|
||||
head = tb
|
||||
for tb_frame, tb_lineno in stack:
|
||||
head = FauxTb(tb_frame, tb_lineno, head)
|
||||
return head
|
||||
|
||||
|
||||
def full_exc_info():
|
||||
"""Like sys.exc_info, but includes the full traceback."""
|
||||
t, v, tb = sys.exc_info()
|
||||
full_tb = extend_traceback(tb, current_stack(1))
|
||||
return t, v, full_tb
|
||||
|
||||
|
||||
def dumpstack(message):
|
||||
''' dumps the current stack - useful of debugging
|
||||
'''
|
||||
logging.error(message, exc_info=full_exc_info())
|
||||
|
||||
|
||||
def uniquify_and_sort(iterable):
|
||||
''' Removes duplicates of an iterables and returns a list of unique
|
||||
elements.
|
||||
'''
|
||||
uniques = []
|
||||
|
||||
for element in iterable:
|
||||
if element not in uniques:
|
||||
uniques.append(element)
|
||||
|
||||
return sorted(uniques)
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
GenreType = namedtuple("GenreType", ["name", "genre_type"])
|
||||
|
||||
|
||||
class NaturalString(str):
|
||||
'''
|
||||
this class implements an object that can naturally compare
|
||||
@@ -42,10 +104,10 @@ class NaturalString(str):
|
||||
'''
|
||||
|
||||
def __init__(self, string):
|
||||
super(NaturalString, self).__init__(string)
|
||||
super(NaturalString, self).__init__()
|
||||
convert = lambda text: int(text) if text.isdigit() else text.lower()
|
||||
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)',
|
||||
key)]
|
||||
key)]
|
||||
|
||||
self._string_elements = alphanum_key(string)
|
||||
|
||||
@@ -246,7 +308,6 @@ class SortedCollection(object):
|
||||
|
||||
|
||||
class ReversedSortedCollection(object):
|
||||
|
||||
def __init__(self, sorted_collection):
|
||||
self._sorted_collection = sorted_collection
|
||||
|
||||
@@ -302,7 +363,6 @@ class ReversedSortedCollection(object):
|
||||
|
||||
|
||||
class IdleCallIterator(object):
|
||||
|
||||
def __init__(self, chunk, process, after=None, error=None, finish=None):
|
||||
default = lambda *_: None
|
||||
|
||||
@@ -324,7 +384,7 @@ class IdleCallIterator(object):
|
||||
|
||||
for i in range(self._chunk):
|
||||
try:
|
||||
next_elem = self._iter.next()
|
||||
next_elem = next(self._iter)
|
||||
|
||||
self._process(next_elem, data)
|
||||
except StopIteration:
|
||||
@@ -351,25 +411,26 @@ def idle_iterator(func):
|
||||
|
||||
return iter_function
|
||||
|
||||
|
||||
class Theme:
|
||||
'''
|
||||
This class manages the theme details
|
||||
'''
|
||||
# storage for the instance reference
|
||||
__instance = None
|
||||
|
||||
|
||||
class _impl(GObject.Object):
|
||||
""" Implementation of the singleton interface """
|
||||
#properties
|
||||
# properties
|
||||
theme = GObject.property(type=str, default="standard")
|
||||
|
||||
|
||||
# signals
|
||||
'''
|
||||
changed = signal emitted when a theme has changed
|
||||
'''
|
||||
__gsignals__ = {
|
||||
'theme_changed': (GObject.SIGNAL_RUN_LAST, None, ())
|
||||
}
|
||||
}
|
||||
# below public variables and methods that can be called for Theme
|
||||
def __init__(self, plugin):
|
||||
'''
|
||||
@@ -377,35 +438,35 @@ class Theme:
|
||||
used to access the plugin's settings.
|
||||
'''
|
||||
super(Theme._impl, self).__init__()
|
||||
|
||||
|
||||
self.plugin = plugin
|
||||
popups = rb.find_plugin_file(plugin, 'img/popups.xml')
|
||||
root = ET.parse(open(popups)).getroot()
|
||||
|
||||
base = 'theme/theme'
|
||||
self.themes = []
|
||||
|
||||
|
||||
for elem in root.xpath(base):
|
||||
self.themes.append(elem.attrib['folder_name'])
|
||||
|
||||
self.gs=GSetting()
|
||||
self.setting=self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
self.gs = GSetting()
|
||||
self.setting = self.gs.get_setting(self.gs.Path.PLUGIN)
|
||||
|
||||
# connect properties and signals
|
||||
self._connect_properties()
|
||||
self._connect_signals()
|
||||
|
||||
|
||||
@property
|
||||
def current(self):
|
||||
return self.setting[self.gs.PluginKey.THEME]
|
||||
|
||||
def _connect_properties(self):
|
||||
self.setting.bind(self.gs.PluginKey.THEME, self,
|
||||
'theme', Gio.SettingsBindFlags.GET)
|
||||
'theme', Gio.SettingsBindFlags.GET)
|
||||
|
||||
def _connect_signals(self):
|
||||
self.connect('notify::theme', self._on_theme_changed,
|
||||
None)
|
||||
None)
|
||||
|
||||
def _on_theme_changed(self, *args):
|
||||
self.emit('theme_changed')
|
||||
@@ -427,12 +488,12 @@ class Theme:
|
||||
def __setattr__(self, attr, value):
|
||||
""" Delegate access to implementation """
|
||||
return setattr(self.__instance, attr, value)
|
||||
|
||||
class SpriteSheet(object):
|
||||
|
||||
|
||||
class SpriteSheet(object):
|
||||
def __init__(self, image, icon_width, icon_height, x_spacing, y_spacing,
|
||||
x_start, y_start, across_dimension, down_dimension,
|
||||
alpha_color=None, size=None):
|
||||
x_start, y_start, across_dimension, down_dimension,
|
||||
alpha_color=None, size=None):
|
||||
# load the image
|
||||
base_image = GdkPixbuf.Pixbuf.new_from_file(image)
|
||||
|
||||
@@ -447,15 +508,15 @@ class SpriteSheet(object):
|
||||
for y in range(0, down_dimension):
|
||||
for x in range(0, across_dimension):
|
||||
sprite = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True,
|
||||
8, icon_width, icon_height)
|
||||
8, icon_width, icon_height)
|
||||
|
||||
base_image.copy_area(x_start + (x * delta_x),
|
||||
y_start + (y * delta_y), icon_width, icon_height,
|
||||
sprite, 0, 0)
|
||||
y_start + (y * delta_y), icon_width, icon_height,
|
||||
sprite, 0, 0)
|
||||
|
||||
if size:
|
||||
sprite = sprite.scale_simple(size[0], size[1],
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
self._sprites.append(sprite)
|
||||
|
||||
@@ -465,14 +526,15 @@ class SpriteSheet(object):
|
||||
def __getitem__(self, index):
|
||||
return self._sprites[index]
|
||||
|
||||
|
||||
class ConfiguredSpriteSheet(object):
|
||||
def __init__(self, plugin, sprite_name, size=None):
|
||||
popups = rb.find_plugin_file(plugin, 'img/popups.xml')
|
||||
root = ET.parse(open(popups)).getroot()
|
||||
base = 'theme/theme[@folder_name="' + Theme(plugin).current\
|
||||
+ '"]/spritesheet[@name="' + sprite_name + '"]/'
|
||||
image = rb.find_plugin_file(plugin, 'img/' + Theme(plugin).current\
|
||||
+'/' + root.xpath(base + 'image')[0].text)
|
||||
base = 'theme/theme[@folder_name="' + Theme(plugin).current \
|
||||
+ '"]/spritesheet[@name="' + sprite_name + '"]/'
|
||||
image = rb.find_plugin_file(plugin, 'img/' + Theme(plugin).current \
|
||||
+ '/' + root.xpath(base + 'image')[0].text)
|
||||
icon_width = int(root.xpath(base + 'icon')[0].attrib['width'])
|
||||
icon_height = int(root.xpath(base + 'icon')[0].attrib['height'])
|
||||
x_spacing = int(root.xpath(base + 'spacing')[0].attrib['x'])
|
||||
@@ -483,34 +545,34 @@ class ConfiguredSpriteSheet(object):
|
||||
down_dimension = int(root.xpath(base + 'dimension')[0].attrib['down'])
|
||||
|
||||
try:
|
||||
alpha_color = map(int,
|
||||
root.xpath(base + 'alpha')[0].text.split(' '))
|
||||
alpha_color = list(map(int,
|
||||
root.xpath(base + 'alpha')[0].text.split(' ')))
|
||||
except:
|
||||
alpha_color = None
|
||||
|
||||
self.names = []
|
||||
self.locale_names = {}
|
||||
|
||||
cl = CoverLocale()
|
||||
lang=cl.get_locale()
|
||||
|
||||
base = sprite_name + '/' + sprite_name +\
|
||||
'[@spritesheet="' + sprite_name + '"]'
|
||||
cl = CoverLocale()
|
||||
lang = cl.get_locale()
|
||||
|
||||
base = sprite_name + '/' + sprite_name + \
|
||||
'[@spritesheet="' + sprite_name + '"]'
|
||||
|
||||
for elem in root.xpath(base + '[not(@xml:lang)]'):
|
||||
self.names.append(elem.text)
|
||||
|
||||
|
||||
for elem in root.xpath(base + '[@xml:lang="' + lang + '"]'):
|
||||
self.locale_names[elem.text]=elem.attrib['name']
|
||||
self.locale_names[elem.text] = elem.attrib['name']
|
||||
|
||||
if (not self.locale_names) and len(lang) > 2:
|
||||
for elem in root.xpath(base + '[@xml:lang="' +\
|
||||
lang[0:2] + '"]'):
|
||||
self.locale_names[elem.text]=elem.attrib['name']
|
||||
for elem in root.xpath(base + '[@xml:lang="' + \
|
||||
lang[0:2] + '"]'):
|
||||
self.locale_names[elem.text] = elem.attrib['name']
|
||||
|
||||
self._sheet = SpriteSheet(image, icon_width, icon_height, x_spacing,
|
||||
y_spacing, x_start, y_start, across_dimension, down_dimension,
|
||||
alpha_color, size)
|
||||
y_spacing, x_start, y_start, across_dimension, down_dimension,
|
||||
alpha_color, size)
|
||||
|
||||
self._genre_db = RB.ExtDB(name='cb_genre')
|
||||
|
||||
@@ -528,7 +590,8 @@ class ConfiguredSpriteSheet(object):
|
||||
|
||||
def keys(self):
|
||||
return self.names
|
||||
|
||||
|
||||
|
||||
class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
'''
|
||||
A sprite-sheet of genres. Creates a pixbuf representation of a picture
|
||||
@@ -547,11 +610,11 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
GENRE_USER = 1
|
||||
GENRE_SYSTEM = 2
|
||||
GENRE_LOCALE = 3
|
||||
|
||||
|
||||
def __init__(self, plugin, sprite_name, size=None):
|
||||
super(GenreConfiguredSpriteSheet, self).__init__(plugin, sprite_name,
|
||||
size)
|
||||
self.genre_alternate = {} # contains GenreType tuples
|
||||
size)
|
||||
self.genre_alternate = {} # contains GenreType tuples
|
||||
self._alt_icons = {}
|
||||
self._sprite_name = sprite_name
|
||||
self._size = size
|
||||
@@ -561,20 +624,21 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
self._parse_popups(plugin, root, self.GENRE_SYSTEM)
|
||||
|
||||
try:
|
||||
self._user_popups = RB.find_user_data_file('plugins/coverart_browser/img/usericons/popups.xml')
|
||||
#self._user_popups = RB.find_user_data_file('plugins/coverart_browser/img/usericons/popups.xml')
|
||||
self._user_popups = RB.user_cache_dir() + "/coverart_browser/usericons/popups.xml"
|
||||
root = ET.parse(open(self._user_popups)).getroot()
|
||||
self._parse_popups(plugin, root, self.GENRE_USER)
|
||||
elem = root.xpath(self._sprite_name + '/index')
|
||||
curr_index = long(elem[0].text)
|
||||
curr_index = int(elem[0].text)
|
||||
|
||||
for index in range(0,curr_index+1):
|
||||
for index in range(0, curr_index + 1):
|
||||
key = RB.ExtDBKey.create_lookup('icon', str(index))
|
||||
icon_location = self._genre_db.lookup(key)
|
||||
sprite = GdkPixbuf.Pixbuf.new_from_file(icon_location)
|
||||
if self._size:
|
||||
sprite = sprite.scale_simple(self._size[0], self._size[1],
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
self._alt_icons[str(index)] = sprite
|
||||
self.names.append(str(index))
|
||||
except:
|
||||
@@ -589,7 +653,7 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
def _parse_popups(self, plugin, root, genre_type):
|
||||
icon_names = {}
|
||||
cl = CoverLocale()
|
||||
lang=cl.get_locale()
|
||||
lang = cl.get_locale()
|
||||
|
||||
base = self._sprite_name + '/alt'
|
||||
for elem in root.xpath(base + '[not(@xml:lang)]/alt'):
|
||||
@@ -597,32 +661,33 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
|
||||
for elem in root.xpath(base + '[@xml:lang="' + lang + '"]/alt'):
|
||||
self.genre_alternate[GenreType(name=elem.text, genre_type=self.GENRE_LOCALE)] = elem.attrib['genre']
|
||||
|
||||
#if (not self.locale_alternate) and len(lang) > 2:
|
||||
|
||||
# if (not self.locale_alternate) and len(lang) > 2:
|
||||
if len(lang) > 2:
|
||||
for elem in root.xpath(base + '[@xml:lang="' +\
|
||||
lang[0:2] + '"]/alt'):
|
||||
for elem in root.xpath(base + '[@xml:lang="' + \
|
||||
lang[0:2] + '"]/alt'):
|
||||
self.genre_alternate[GenreType(name=elem.text, genre_type=self.GENRE_LOCALE)] = elem.attrib['genre']
|
||||
|
||||
def add_genre_icon( self, filename ):
|
||||
def add_genre_icon(self, filename):
|
||||
root = ET.parse(open(self._user_popups)).getroot()
|
||||
elem = root.xpath(self._sprite_name + '/index')
|
||||
next_index = long(elem[0].text)
|
||||
elem[0].text = str(next_index+1)
|
||||
next_index = int(elem[0].text)
|
||||
elem[0].text = str(next_index + 1)
|
||||
tree = ET.ElementTree(root)
|
||||
tree.write(self._user_popups, pretty_print=True, xml_declaration=True)
|
||||
|
||||
key = RB.ExtDBKey.create_storage('icon', str(next_index))
|
||||
uri = "file://" + urllib.pathname2url(filename)
|
||||
self._genre_db.store_uri(key, RB.ExtDBSourceType.USER_EXPLICIT, uri)
|
||||
|
||||
uri = "file://" + rb3compat.pathname2url(filename)
|
||||
|
||||
self._genre_db.store_uri(key, RB.ExtDBSourceType.USER_EXPLICIT, uri)
|
||||
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
|
||||
new_genre = GenreType(name=str(next_index), genre_type=self.GENRE_USER)
|
||||
|
||||
if self._size:
|
||||
pixbuf = pixbuf.scale_simple(self._size[0], self._size[1],
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
self._alt_icons[new_genre.name] = pixbuf
|
||||
self.names.append(new_genre.name)
|
||||
|
||||
@@ -633,7 +698,7 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
base = self._sprite_name + '/alt/alt'
|
||||
|
||||
found = False
|
||||
|
||||
|
||||
for elem in root.xpath(base):
|
||||
if RB.search_fold(elem.text) == RB.search_fold(current_genre):
|
||||
found = True
|
||||
@@ -644,15 +709,15 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
tree = ET.ElementTree(root)
|
||||
tree.write(self._user_popups, pretty_print=True, xml_declaration=True)
|
||||
else:
|
||||
print "not found to delete"
|
||||
|
||||
print("not found to delete")
|
||||
|
||||
def amend_genre_info( self, current_genre, new_genre, icon_name):
|
||||
|
||||
def amend_genre_info(self, current_genre, new_genre, icon_name):
|
||||
root = ET.parse(open(self._user_popups)).getroot()
|
||||
base = self._sprite_name + '/alt/alt'
|
||||
|
||||
found = False
|
||||
|
||||
|
||||
if current_genre != "":
|
||||
for elem in root.xpath(base):
|
||||
if RB.search_fold(elem.text) == RB.search_fold(current_genre):
|
||||
@@ -666,7 +731,7 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
found = True
|
||||
|
||||
if found:
|
||||
elem.text = unicode(new_genre, 'utf-8')
|
||||
elem.text = rb3compat.unicodestr(new_genre, 'utf-8')
|
||||
elem.attrib['genre'] = icon_name
|
||||
|
||||
tree = ET.ElementTree(root)
|
||||
@@ -674,9 +739,10 @@ class GenreConfiguredSpriteSheet(ConfiguredSpriteSheet):
|
||||
self.genre_alternate[GenreType(name=elem.text, genre_type=self.GENRE_USER)] = icon_name
|
||||
return GenreType(name=elem.text, genre_type=self.GENRE_USER)
|
||||
else:
|
||||
print "nothing found to amend"
|
||||
print("nothing found to amend")
|
||||
return None
|
||||
|
||||
|
||||
|
||||
def get_stock_size():
|
||||
what, width, height = Gtk.icon_size_lookup(Gtk.IconSize.BUTTON)
|
||||
|
||||
@@ -688,26 +754,67 @@ def create_pixbuf_from_file_at_size(filename, width, height):
|
||||
|
||||
if pixbuf.get_width() != width or pixbuf.get_height() != height:
|
||||
pixbuf = pixbuf.scale_simple(width, height,
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
GdkPixbuf.InterpType.BILINEAR)
|
||||
|
||||
return pixbuf
|
||||
|
||||
|
||||
'''
|
||||
class to search through a dict without case-sensitivity nor
|
||||
unicode vs string issues
|
||||
'''
|
||||
|
||||
|
||||
class CaseInsensitiveDict(collections.Mapping):
|
||||
def __init__(self, d):
|
||||
self._d = d
|
||||
self._s = dict((RB.search_fold(k), k) for k in d)
|
||||
|
||||
def __contains__(self, k):
|
||||
return RB.search_fold(k) in self._s
|
||||
|
||||
def __len__(self):
|
||||
return len(self._s)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._s)
|
||||
|
||||
def __getitem__(self, k):
|
||||
return self._d[self._s[RB.search_fold(k)]]
|
||||
|
||||
def actual_key_case(self, k):
|
||||
return self._s.get(RB.search_fold(k))
|
||||
|
||||
|
||||
def check_lastfm(force_check=False):
|
||||
'''
|
||||
check validity of lastfm connection
|
||||
|
||||
returns True if connected with an account
|
||||
|
||||
Also returns True if lastFM is not in the list of search providers
|
||||
'''
|
||||
|
||||
providers = get_search_providers()
|
||||
print(providers)
|
||||
print(force_check)
|
||||
|
||||
if force_check or 'lastfm-search' in providers:
|
||||
connected = lastfm_connected()
|
||||
print(connected)
|
||||
return connected
|
||||
elif not 'lastfm-search' in providers:
|
||||
print("not lastm-search")
|
||||
return True
|
||||
else:
|
||||
print("returning default")
|
||||
return False
|
||||
|
||||
|
||||
def create_button_image(plugin, icon_name):
|
||||
'create a pixbuf for the given icon_name sized according to the stock icon size'
|
||||
path = 'img/'
|
||||
|
||||
return create_pixbuf_from_file_at_size(
|
||||
rb.find_plugin_file(plugin, path + icon_name),
|
||||
*get_stock_size())
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/* ContentFlowAddOn_black, version 2.0
|
||||
* (c) 2008 - 2010 Sebastian Kutsch
|
||||
* <http://www.jacksasylum.eu/ContentFlow/>
|
||||
*
|
||||
* This file is distributed under the terms of the MIT license.
|
||||
* (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
|
||||
*
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/* ========== ContentFlow ========== */
|
||||
/*
|
||||
* Within this file you can ajust the styling of ContentFlow
|
||||
* to your personal needs. The default styling is the same as found on the
|
||||
* projectpage.
|
||||
*
|
||||
*/
|
||||
|
||||
.ContentFlowAddOn_black {
|
||||
background: black;
|
||||
}
|
||||
|
||||
/* ----- styling of items ----- */
|
||||
.ContentFlowAddOn_black .flow .item .caption {
|
||||
background: url(img/1x1_0.5_black.png);
|
||||
}
|
||||
* html .ContentFlowAddOn_black .flow .item .caption {
|
||||
background-image: none;
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='img/1x1_0.5_black.png');
|
||||
}
|
||||
.ContentFlowAddOn_black .flow .item .caption a,
|
||||
.ContentFlowAddOn_black .flow .item .caption a:link,
|
||||
.ContentFlowAddOn_black .flow .item .caption a:visited,
|
||||
.ContentFlowAddOn_black .flow .item .caption a:active,
|
||||
.ContentFlowAddOn_black .flow .item .caption a:hover {
|
||||
color: black;
|
||||
}
|
||||
/* ----- scrollbar ----- */
|
||||
.ContentFlowAddOn_black .scrollbar {
|
||||
background: url(img/scrollbar_white.png) left center repeat-x;
|
||||
}
|
||||
|
||||
.ContentFlowAddOn_black .scrollbar .slider {
|
||||
background: url(img/slider_white.png) center center no-repeat;
|
||||
}
|
||||
|
||||
/* only for IE <= 6 and a alphatransparent slider image */
|
||||
* html .ContentFlowAddOn_black .scrollbar .slider { background-image: none; }
|
||||
* html .ContentFlowAddOn_black .scrollbar .slider .virtualSlider {
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='img/slider_white.png');
|
||||
}
|
||||
.ContentFlowAddOn_black .scrollbar .slider .position {
|
||||
color:silver;
|
||||
}
|
||||
|
||||
|
||||
/* ----- global caption ----- */
|
||||
.ContentFlowAddOn_black .globalCaption {
|
||||
color: white;
|
||||
}
|
||||
.ContentFlowAddOn_black .globalCaption .caption a,
|
||||
.ContentFlowAddOn_black .globalCaption .caption a:link,
|
||||
.ContentFlowAddOn_black .globalCaption .caption a:visited,
|
||||
.ContentFlowAddOn_black .globalCaption .caption a:active,
|
||||
.ContentFlowAddOn_black .globalCaption .caption a:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* ----- load indicator ----- */
|
||||
.ContentFlowAddOn_black .loadIndicator {
|
||||
background: url(img/1x1_0.5_black.png);
|
||||
}
|
||||
* html .ContentFlowAddOn_black .loadIndicator {
|
||||
background-image: none;
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='img/1x1_0.5_black.png');
|
||||
}
|
||||
.ContentFlowAddOn_black .loadIndicator .indicator {
|
||||
background: url(img/loader_black.gif) center center no-repeat;
|
||||
}
|
||||
|
||||
/* ================================= */
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/* ContentFlowAddOn_black, version 2.0
|
||||
* (c) 2008 - 2010 Sebastian Kutsch
|
||||
* <http://www.jacksasylum.eu/ContentFlow/>
|
||||
*
|
||||
* This file is distributed under the terms of the MIT license.
|
||||
* (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
|
||||
*/
|
||||
|
||||
new ContentFlowAddOn ('black', {
|
||||
|
||||
init: function () {
|
||||
this.addStylesheet();
|
||||
},
|
||||
|
||||
ContentFlowConf: {
|
||||
reflectionColor: "#000000" // none, transparent, overlay or hex RGB CSS style #RRGGBB
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
/* ContentFlowAddOn_carousel, version 1.1
|
||||
* (c) 2008 - 2010 Sebastian Kutsch
|
||||
* <http://www.jacksasylum.eu/ContentFlow/>
|
||||
*
|
||||
* This file is distributed under the terms of the MIT license.
|
||||
* (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
|
||||
*
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
.ContentFlowAddOn_carousel {
|
||||
|
||||
border: 5px solid #767676;
|
||||
margin: 0 25px;
|
||||
padding: 25px 0px;
|
||||
overflow: visible;
|
||||
/*overflow: hidden;*/
|
||||
}
|
||||
.ContentFlowAddOn_carousel #preButton,
|
||||
.ContentFlowAddOn_carousel #nextButton {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -25px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.ContentFlowAddOn_carousel #preButton {
|
||||
background: url(img/pre_h.png) center no-repeat;
|
||||
left: -25px;
|
||||
left: -28px;
|
||||
}
|
||||
* html .ContentFlowAddOn_carousel #preButton {
|
||||
background-image: none;
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='img/pre_h.png');
|
||||
}
|
||||
.ContentFlowAddOn_carousel #preButton:hover {
|
||||
background: url(img/pre_h.png) center no-repeat;
|
||||
}
|
||||
.ContentFlowAddOn_carousel #nextButton {
|
||||
background: url(img/next_h.png) center no-repeat;
|
||||
right: -25px;
|
||||
right: -28px;
|
||||
}
|
||||
* html .ContentFlowAddOn_carousel #nextButton {
|
||||
background-image: none;
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='img/next_h.png');
|
||||
}
|
||||
.ContentFlowAddOn_carousel #nextButton:hover {
|
||||
background: url(img/next_h.png) center no-repeat;
|
||||
}
|
||||
|
||||
/* ----- styling of items ----- */
|
||||
.ContentFlowAddOn_carousel .showCaption .item .caption {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
|
||||
/* ----- global caption ----- */
|
||||
.ContentFlowAddOn_carousel .globalCaption {
|
||||
margin-top: -3em;
|
||||
}
|
||||
|
||||
|
||||
/* ================================= */
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/* ContentFlowAddOn_carousel, version 1.1
|
||||
* (c) 2008 - 2010 Sebastian Kutsch
|
||||
* <http://www.jacksasylum.eu/ContentFlow/>
|
||||
*
|
||||
* This file is distributed under the terms of the MIT license.
|
||||
* (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
|
||||
*/
|
||||
|
||||
new ContentFlowAddOn ('carousel', {
|
||||
|
||||
conf: {
|
||||
shownItems: 3,
|
||||
showCaption: true,
|
||||
width: 75,
|
||||
height: 75,
|
||||
space:0.0
|
||||
},
|
||||
|
||||
|
||||
init: function() {
|
||||
this.addStylesheet();
|
||||
},
|
||||
|
||||
onloadInit: function (flow) {
|
||||
},
|
||||
|
||||
afterContentFlowInit: function (flow) {
|
||||
var SI = flow.getAddOnConf('carousel').shownItems;
|
||||
var c = flow.Container;
|
||||
var ac = flow.getAddOnConf('carousel')
|
||||
if (ac.showCaption) {
|
||||
$CF(flow.Flow).addClassName('showCaption');
|
||||
}
|
||||
|
||||
var p = document.createElement('div');
|
||||
p.id = "preButton";
|
||||
var pre = function () {
|
||||
var item = flow._activeItem;
|
||||
for (var i=0; i< SI; i++) { item = item.pre; }
|
||||
flow.moveToItem(item);
|
||||
}
|
||||
p.onclick = pre;
|
||||
c.appendChild(p);
|
||||
|
||||
var n = document.createElement('div');
|
||||
n.id = "nextButton";
|
||||
var next = function () {
|
||||
var item = flow._activeItem;
|
||||
for (var i=0; i< SI; i++) { item = item.next; }
|
||||
flow.moveToItem(item);
|
||||
}
|
||||
n.onclick = next;
|
||||
c.appendChild(n);
|
||||
|
||||
flow.Flow.style.fontSize = 12*(flow.maxHeight / 150) +"px";
|
||||
if (flow.Browser.IE) {
|
||||
window.setTimeout(function () {flow.Flow.style.overflow = "hidden"}, 1000);
|
||||
}
|
||||
else {
|
||||
flow.Flow.style.overflow = "hidden";
|
||||
}
|
||||
|
||||
flow.setConfig({visibleItems: Math.ceil((flow.getAddOnConf('carousel').shownItems - 1)/2) + 1});
|
||||
},
|
||||
|
||||
ContentFlowConf: {
|
||||
scaleFactorLandscape: "max", // scale factor of landscape images ('max' := height= maxItemHeight)
|
||||
scaleFactorPortrait: "max",
|
||||
fixItemSize: true,
|
||||
relativeItemPosition: "center", // align top/above, bottom/below, left, right, center of position coordinate
|
||||
visibleItems: 2, // how man item are visible on each side (-1 := auto)
|
||||
reflectionHeight: 0, // float (relative to original image height)
|
||||
|
||||
|
||||
/* ==================== actions ==================== */
|
||||
onclickInactiveItem : function (item) {
|
||||
this.conf.onclickActiveItem(item);
|
||||
return false;
|
||||
},
|
||||
|
||||
/* ==================== calculations ==================== */
|
||||
|
||||
calcStepWidth: function(diff) {
|
||||
var vI = this.conf.visibleItems;
|
||||
var items = this.items.length;
|
||||
items = items == 0 ? 1 : items;
|
||||
var absDiff = Math.abs(diff);
|
||||
if (absDiff > vI) {
|
||||
if (diff > 0) {
|
||||
var stepwidth = diff - vI;
|
||||
} else {
|
||||
var stepwidth = diff + vI;
|
||||
}
|
||||
} else if (vI >= items) {
|
||||
var stepwidth = diff / items;
|
||||
} else {
|
||||
var c = this.getAddOnConf('carousel');
|
||||
var f = 0.1 * 2/3 * c.shownItems * diff/absDiff;
|
||||
var d = diff * ( vI / items);
|
||||
var stepwidth = absDiff > 0.1 ? f : d*8;
|
||||
}
|
||||
return stepwidth;
|
||||
},
|
||||
|
||||
|
||||
calcSize: function (item) {
|
||||
var c = this.getAddOnConf('carousel');
|
||||
var a = c.width / c.height;
|
||||
//if (this.conf.verticalFlow) a = 1/a;
|
||||
var h = 3/c.shownItems / a;
|
||||
//if (this.conf.verticalFlow) h *= 2/3;
|
||||
var w = h * a;
|
||||
return {width: w, height: h};
|
||||
},
|
||||
|
||||
calcCoordinates: function (item) {
|
||||
var rP = item.relativePosition;
|
||||
var c = this.getAddOnConf('carousel');
|
||||
var w = item.size.width;
|
||||
//if (this.conf.verticalFlow) w = item.size.height;
|
||||
var x = rP*w/2*(1 + c.space) *this.conf.scaleFactor - w* (c.shownItems % 2 ? 0 : 0.5) / 1.4;
|
||||
if (this.conf.verticalFlow) x *= 2*2/3;
|
||||
var y = 0;
|
||||
|
||||
return {x: x, y: y};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
/* ContentFlowAddOn_roundabout, version 3.0
|
||||
* (c) 2008 - 2010 Sebastian Kutsch
|
||||
* <http://www.jacksasylum.eu/ContentFlow/>
|
||||
*
|
||||
* This file is distributed under the terms of the MIT license.
|
||||
* (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
|
||||
*/
|
||||
|
||||
new ContentFlowAddOn ('roundabout', {
|
||||
|
||||
ContentFlowConf: {
|
||||
circularFlow: true,
|
||||
visibleItems: -1,
|
||||
relativeItemPosition: "top center",
|
||||
endOpacity: 0.5,
|
||||
|
||||
/*
|
||||
* calculates the size of the item at its relative position x
|
||||
* returns a size object
|
||||
*/
|
||||
calcSize: function (item) {
|
||||
var rP = item.relativePosition;
|
||||
//var rPN = relativePositionNormed;
|
||||
//var vI = rPN != 0 ? rP/rPN : 0 ; // visible Items
|
||||
|
||||
var h = 1/(Math.abs(rP)+1);
|
||||
var w = h;
|
||||
return {width: w, height: h};
|
||||
},
|
||||
|
||||
/*
|
||||
* calculates the position of an item within the flow element
|
||||
* returns a vector object
|
||||
*/
|
||||
calcCoordinates: function (item) {
|
||||
var rP = item.relativePosition;
|
||||
var rPN = item.relativePositionNormed;
|
||||
var vI = rPN != 0 ? rP/rPN : 0 ; // visible Items
|
||||
|
||||
var f = 1 - 1/Math.exp( Math.abs(rP)*0.75);
|
||||
var x = item.side * vI/(vI+1)* f;
|
||||
var y = 1;
|
||||
|
||||
var f = Math.sin(Math.PI * (rP*(1+1/(rP*rP+1))) / (vI+1));
|
||||
var x = vI/(vI+1)* f;
|
||||
var y = 1 - Math.abs(rP)*1.5/(vI+1);
|
||||
|
||||
return {x: x, y: y};
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
/* ContentFlowAddOn_vertical, version 2.0
|
||||
* (c) 2008 - 2010 Sebastian Kutsch
|
||||
* <http://www.jacksasylum.eu/ContentFlow/>
|
||||
*
|
||||
* This file is distributed under the terms of the MIT license.
|
||||
* (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
|
||||
*/
|
||||
|
||||
|
||||
new ContentFlowAddOn ('vertical', {
|
||||
|
||||
ContentFlowConf: {
|
||||
relativeItemPosition: "center", // top, bottom, left, right, center
|
||||
verticalFlow: true, // turn ContentFlow 90 degree counterclockwise
|
||||
reflectionHeight: 0,
|
||||
|
||||
calcCoordinates: function (item) {
|
||||
var rP = item.relativePosition;
|
||||
var rPN = item.relativePositionNormed;
|
||||
var vI = rPN != 0 ? rP/rPN : 0 ; // visible Items
|
||||
|
||||
var f = 1 - 1/Math.exp( Math.abs(rP)*0.75);
|
||||
var x = item.side * vI/(vI+1)* f;
|
||||
var y = 0;
|
||||
|
||||
return {x: x, y: y};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,80 @@
|
||||
/* ContentFlowAddOn_white, version 2.0
|
||||
* (c) 2008 - 2010 Sebastian Kutsch
|
||||
* <http://www.jacksasylum.eu/ContentFlow/>
|
||||
*
|
||||
* This file is distributed under the terms of the MIT license.
|
||||
* (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
|
||||
*
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/* ========== ContentFlow ========== */
|
||||
/*
|
||||
* Within this file you can ajust the styling of ContentFlow
|
||||
* to your personal needs. The default styling is the same as found on the
|
||||
* projectpage.
|
||||
*
|
||||
*/
|
||||
|
||||
.ContentFlowAddOn_white {
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* ----- styling of items ----- */
|
||||
.ContentFlowAddOn_white .flow .item .caption {
|
||||
background: url(img/1x1_0.5_white.png);
|
||||
}
|
||||
* html .ContentFlowAddOn_white .flow .item .caption {
|
||||
background-image: none;
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='img/1x1_0.5_white.png');
|
||||
}
|
||||
.ContentFlowAddOn_white .flow .item .caption a,
|
||||
.ContentFlowAddOn_white .flow .item .caption a:link,
|
||||
.ContentFlowAddOn_white .flow .item .caption a:visited,
|
||||
.ContentFlowAddOn_white .flow .item .caption a:active,
|
||||
.ContentFlowAddOn_white .flow .item .caption a:hover {
|
||||
color: black;
|
||||
}
|
||||
/* ----- scrollbar ----- */
|
||||
.ContentFlowAddOn_white .scrollbar {
|
||||
background: url(img/scrollbar_black.png) left center repeat-x;
|
||||
}
|
||||
|
||||
.ContentFlowAddOn_white .scrollbar .slider {
|
||||
background: url(img/slider_black.png) center center no-repeat;
|
||||
}
|
||||
|
||||
/* only for IE <= 6 and a alphatransparent slider image */
|
||||
* html .ContentFlowAddOn_white .scrollbar .slider { background-image: none; }
|
||||
* html .ContentFlowAddOn_white .scrollbar .slider .virtualSlider {
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='img/slider_black.png');
|
||||
}
|
||||
.ContentFlowAddOn_white .scrollbar .slider .position {
|
||||
color:gray;
|
||||
}
|
||||
|
||||
|
||||
/* ----- global caption ----- */
|
||||
.ContentFlowAddOn_white .globalCaption {
|
||||
color: black;
|
||||
}
|
||||
.ContentFlowAddOn_white .globalCaption .caption a,
|
||||
.ContentFlowAddOn_white .globalCaption .caption a:link,
|
||||
.ContentFlowAddOn_white .globalCaption .caption a:visited,
|
||||
.ContentFlowAddOn_white .globalCaption .caption a:active,
|
||||
.ContentFlowAddOn_white .globalCaption .caption a:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* ----- load indicator ----- */
|
||||
.ContentFlowAddOn_white .loadIndicator {
|
||||
background: url(img/1x1_0.5_white.png);
|
||||
}
|
||||
* html .ContentFlowAddOn_white .loadIndicator {
|
||||
background-image: none;
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='img/1x1_0.5_white.png');
|
||||
}
|
||||
.ContentFlowAddOn_white .loadIndicator .indicator {
|
||||
background: url(img/loader_white.gif) center center no-repeat;
|
||||
}
|
||||
|
||||
/* ================================= */
|
||||
@@ -0,0 +1,19 @@
|
||||
/* ContentFlowAddOn_white, version 2.0
|
||||
* (c) 2008 - 2010 Sebastian Kutsch
|
||||
* <http://www.jacksasylum.eu/ContentFlow/>
|
||||
*
|
||||
* This file is distributed under the terms of the MIT license.
|
||||
* (see http://www.jacksasylum.eu/ContentFlow/LICENSE)
|
||||
*/
|
||||
|
||||
new ContentFlowAddOn ('white', {
|
||||
|
||||
init: function () {
|
||||
this.addStylesheet();
|
||||
},
|
||||
|
||||
ContentFlowConf: {
|
||||
reflectionColor: "#ffffff" // none, transparent, overlay or hex RGB CSS style #RRGGBB
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2007 - 2010 Sebastian Kutsch
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,250 @@
|
||||
|
||||
/* ========== ContentFlow ========== */
|
||||
/*
|
||||
* default style to look nice
|
||||
*/
|
||||
|
||||
.ContentFlow {
|
||||
}
|
||||
.ContentFlow .flow {
|
||||
/*border: 1px solid green;*/
|
||||
}
|
||||
.ContentFlow .flow * {
|
||||
}
|
||||
|
||||
.ContentFlow .flow .item {
|
||||
/*border: 1px solid red;*/
|
||||
}
|
||||
.ContentFlow .flow .item canvas.content {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
/*border: 1px solid yellow;*/
|
||||
}
|
||||
.ContentFlow .flow .item img.content {
|
||||
/*border: 1px solid yellow;*/
|
||||
width: 100%;
|
||||
}
|
||||
.ContentFlow .flow .item img.reflection,
|
||||
.ContentFlow .flow .item canvas.reflection {
|
||||
width: 100%;
|
||||
}
|
||||
/* ----- styling of items ----- */
|
||||
.ContentFlow .flow .item.active {
|
||||
cursor: pointer;
|
||||
}
|
||||
.ContentFlow .flow .item .caption {
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: white;
|
||||
max-height: 30%;
|
||||
bottom: 10%;
|
||||
background: url(img/1x1_0.5_black.png);
|
||||
width: 100%;
|
||||
}
|
||||
* html .ContentFlow .flow .item .caption {
|
||||
background-image: none;
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='img/1x1_0.5_black.png');
|
||||
}
|
||||
.ContentFlow .flow .item .caption a,
|
||||
.ContentFlow .flow .item .caption a:link,
|
||||
.ContentFlow .flow .item .caption a:visited,
|
||||
.ContentFlow .flow .item .caption a:active,
|
||||
.ContentFlow .flow .item .caption a:hover {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
font-style: italic;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.ContentFlow .flow .item .caption a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.ContentFlow .flow .item.active .caption {
|
||||
/*display: block;*/ /* uncomment to show caption inside item */
|
||||
}
|
||||
|
||||
/* ----- scrollbar ----- */
|
||||
.ContentFlow .scrollbar {
|
||||
width: 50%;
|
||||
margin: 0px auto;
|
||||
margin-top: 10px;
|
||||
height: 16px;
|
||||
background: url(img/scrollbar_white.png) left center repeat-x;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.ContentFlow .scrollbar .slider {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(img/slider_white.png) center center no-repeat;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
/* only for IE <= 6 and a alphatransparent slider image */
|
||||
* html .ContentFlow .scrollbar .slider { background-image: none; }
|
||||
* html .ContentFlow .scrollbar .slider .virtualSlider {
|
||||
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='img/slider_white.png');
|
||||
}
|
||||
.ContentFlow .scrollbar .slider .position {
|
||||
top: 120%;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: silver
|
||||
}
|
||||
|
||||
/* ----- global caption ----- */
|
||||
.ContentFlow .globalCaption {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
height: 20px;
|
||||
margin: 2em auto;
|
||||
}
|
||||
.ContentFlow .globalCaption .caption {
|
||||
}
|
||||
.ContentFlow .globalCaption .caption a,
|
||||
.ContentFlow .globalCaption .caption a:link,
|
||||
.ContentFlow .globalCaption .caption a:visited,
|
||||
.ContentFlow .globalCaption .caption a:active,
|
||||
.ContentFlow .globalCaption .caption a:hover {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
font-style: italic;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.ContentFlow .globalCaption .caption a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ----- load indicator ----- */
|
||||
.ContentFlow .loadIndicator {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
background: black;
|
||||
}
|
||||
.ContentFlow .loadIndicator .indicator {
|
||||
background: url(img/loader.gif) center center no-repeat;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
* html .ContentFlow .loadIndicator .indicator {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
/* ================================= */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ========== ContentFlow ========== */
|
||||
/*
|
||||
* This is the basic CSS file needed for the correct functioning of ContentFlow.
|
||||
* DON'T CHANGE IT.
|
||||
*
|
||||
*/
|
||||
.ContentFlow {
|
||||
position: relative; /* needed so overlay dimensions are constrained to the ContentFlow */
|
||||
overflow: hidden;
|
||||
}
|
||||
.ContentFlow * {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
/*border: none;*/
|
||||
}
|
||||
.ContentFlow img {
|
||||
-ms-interpolation-mode: bicubic;
|
||||
}
|
||||
|
||||
.ContentFlow .mouseoverCheckElement {
|
||||
position: absolute;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
left: 0px;
|
||||
/*display: none;*/
|
||||
visibility: hidden;
|
||||
}
|
||||
.ContentFlow:hover .mouseoverCheckElement {
|
||||
left: 1px;
|
||||
/*width: 1px;*/
|
||||
/*left: -1px;*/
|
||||
/*background-color: red;*/
|
||||
}
|
||||
.ContentFlow .flow {
|
||||
position: relative; /* needed so that items can be positioned relative to flow*/
|
||||
z-index: 0; /* need so every item has a z-index relative to the flow-box */
|
||||
visibility: hidden; /* needed so that content is hidden while loading */
|
||||
width: 100%; /* needed for IE6 */
|
||||
margin: 0 auto;
|
||||
}
|
||||
.ContentFlow .flow.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.ContentFlow .flow .item {
|
||||
position: absolute; /* needed */
|
||||
visibility: hidden;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
.ContentFlow .flow .item.active {
|
||||
}
|
||||
.ContentFlow .flow .item .content {
|
||||
display: block;
|
||||
}
|
||||
.ContentFlow .flow .item div.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.ContentFlow .flow .item .label {
|
||||
display: none;
|
||||
}
|
||||
.ContentFlow .flow .item .reflection {
|
||||
display: block;
|
||||
}
|
||||
.ContentFlow .flow .item canvas.reflection {
|
||||
margin-top: -1px; /* for FF */
|
||||
}
|
||||
.ContentFlow .flow .item .caption {
|
||||
position: absolute; /* needed */
|
||||
display: none; /* needed to hide it on inactive items */
|
||||
}
|
||||
.ContentFlow .flow .item.active .caption {
|
||||
/*display: block;*/ /* uncomment to show caption inside item */
|
||||
}
|
||||
|
||||
/* ----- scrollbar ----- */
|
||||
|
||||
.ContentFlow .scrollbar {
|
||||
position: relative; /* needed for z-index */
|
||||
z-index: 1; /* set above flow */
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.ContentFlow .scrollbar .slider {
|
||||
position: absolute; /* needed */
|
||||
}
|
||||
* html .ContentFlow .scrollbar .slider .virtualSlider {
|
||||
height: 100%;
|
||||
}
|
||||
.ContentFlow .scrollbar .slider .position {
|
||||
position: absolute; /* needed */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ----- global caption ----- */
|
||||
.ContentFlow .globalCaption {
|
||||
position: relative; /* needed for z-index */
|
||||
z-index: 1; /* set above flow */
|
||||
}
|
||||
/* ----- load indicator ----- */
|
||||
.ContentFlow .loadIndicator {
|
||||
position: absolute; /* needed */
|
||||
z-index: 65000; /* set above everything */
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" title="Standard" href="styles.css" type="text/css" media="screen" />
|
||||
|
||||
<!--<style>
|
||||
|
||||
</style> -->
|
||||
|
||||
<style type="text/css">
|
||||
.className{
|
||||
width:270px;
|
||||
height:150px;
|
||||
position:absolute;
|
||||
left:50%;
|
||||
top:50%;
|
||||
margin:-75px 0 0 -135px;
|
||||
}
|
||||
|
||||
.className p{
|
||||
font-size:22px;
|
||||
margin:45px 10px 10px;
|
||||
color: #BACKGROUND_COLOUR;
|
||||
text-align:center;
|
||||
position:absolute;
|
||||
}
|
||||
|
||||
body{
|
||||
background: #BACKGROUND_COLOUR;
|
||||
font-size:0.825em;
|
||||
font-family:Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="className">
|
||||
<p>Use the Search and Filter options to display covers
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
Depois Largura: | Altura: | Tamanho: 82 B |
|
Depois Largura: | Altura: | Tamanho: 82 B |
|
Depois Largura: | Altura: | Tamanho: 43 B |
@@ -0,0 +1,241 @@
|
||||
<?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://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: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="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.47 r22583"
|
||||
version="1.1"
|
||||
sodipodi:docname="New document 1.2009_11_04_18_16_23.0.2009_11_29_20_35_24.0.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3612">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3614" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3616" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3157">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.57391304;"
|
||||
offset="0"
|
||||
id="stop3159" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3161" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3157"
|
||||
id="radialGradient3163"
|
||||
cx="307.14285"
|
||||
cy="582.36218"
|
||||
fx="307.14285"
|
||||
fy="582.36218"
|
||||
r="158.57143"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3157"
|
||||
id="radialGradient3187"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="307.14285"
|
||||
cy="582.36218"
|
||||
fx="307.14285"
|
||||
fy="582.36218"
|
||||
r="158.57143" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3195">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
id="path3197"
|
||||
sodipodi:cx="268.57144"
|
||||
sodipodi:cy="569.50507"
|
||||
sodipodi:rx="171.42857"
|
||||
sodipodi:ry="171.42857"
|
||||
d="M 440.00002,569.50507 A 171.42857,171.42857 0 1 1 97.142868,569.50507 A 171.42857,171.42857 0 1 1 440.00002,569.50507 z"
|
||||
transform="matrix(0.5151267,0,0,0.5151267,47.101979,154.22678)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3205">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
id="path3207"
|
||||
sodipodi:cx="268.57144"
|
||||
sodipodi:cy="569.50507"
|
||||
sodipodi:rx="171.42857"
|
||||
sodipodi:ry="171.42857"
|
||||
d="M 440.00002,569.50507 A 171.42857,171.42857 0 1 1 97.142868,569.50507 A 171.42857,171.42857 0 1 1 440.00002,569.50507 z"
|
||||
transform="matrix(0.5151267,0,0,0.5151267,385.50521,158.17142)" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3612"
|
||||
id="radialGradient3618"
|
||||
cx="307.14285"
|
||||
cy="582.36218"
|
||||
fx="307.14285"
|
||||
fy="582.36218"
|
||||
r="158.57143"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3612"
|
||||
id="radialGradient3639"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="307.14285"
|
||||
cy="582.36218"
|
||||
fx="307.14285"
|
||||
fy="582.36218"
|
||||
r="158.57143" />
|
||||
</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="0.35"
|
||||
inkscape:cx="-159.28571"
|
||||
inkscape:cy="405.71429"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g3620"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1400"
|
||||
inkscape:window-height="1002"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0" />
|
||||
<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" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g3620">
|
||||
<g
|
||||
id="g2835"
|
||||
transform="matrix(-1,0,0,1,370.9006,0)">
|
||||
<path
|
||||
d="m 440.00002,569.50507 c 0,94.67738 -76.75119,171.42857 -171.42858,171.42857 -94.67739,0 -171.428572,-76.75119 -171.428572,-171.42857 0,-94.67739 76.751182,-171.42858 171.428572,-171.42858 94.67739,0 171.42858,76.75119 171.42858,171.42858 z"
|
||||
sodipodi:ry="171.42857"
|
||||
sodipodi:rx="171.42857"
|
||||
sodipodi:cy="569.50507"
|
||||
sodipodi:cx="268.57144"
|
||||
id="path3173"
|
||||
style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
sodipodi:type="arc"
|
||||
transform="matrix(0.5151267,0,0,0.5151267,47.101979,154.22678)" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 193.02128,416.31621 0,17.11698 -69.31988,0 0,28.32175 69.31988,0 0,17.11698 27.09543,-15.63248 27.08251,-15.64537 -27.08251,-15.63248 -27.09543,-15.64538 z"
|
||||
id="rect3165" />
|
||||
<path
|
||||
d="m 440.00002,569.50507 c 0,94.67738 -76.75119,171.42857 -171.42858,171.42857 -94.67739,0 -171.428572,-76.75119 -171.428572,-171.42857 0,-94.67739 76.751182,-171.42858 171.428572,-171.42858 94.67739,0 171.42858,76.75119 171.42858,171.42858 z"
|
||||
sodipodi:ry="171.42857"
|
||||
sodipodi:rx="171.42857"
|
||||
sodipodi:cy="569.50507"
|
||||
sodipodi:cx="268.57144"
|
||||
id="path3175"
|
||||
style="fill:none;stroke:#808080;stroke-width:10.80000019;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc"
|
||||
transform="matrix(0.4679068,0,0,0.4679068,59.783914,181.11879)" />
|
||||
</g>
|
||||
<path
|
||||
transform="matrix(0.5847384,0,0,0.5847384,30.872504,70.269726)"
|
||||
d="m 465.71428,582.36218 a 158.57143,158.57143 0 1 1 -317.14285,0 158.57143,158.57143 0 1 1 317.14285,0 z"
|
||||
sodipodi:ry="158.57143"
|
||||
sodipodi:rx="158.57143"
|
||||
sodipodi:cy="582.36218"
|
||||
sodipodi:cx="307.14285"
|
||||
id="path2385"
|
||||
style="fill:url(#radialGradient3618);fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
<g
|
||||
id="g3627"
|
||||
transform="translate(314.28571,5.7142857)">
|
||||
<g
|
||||
id="g3629">
|
||||
<path
|
||||
transform="matrix(0.5151267,0,0,0.5151267,47.101979,154.22678)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
id="path3631"
|
||||
sodipodi:cx="268.57144"
|
||||
sodipodi:cy="569.50507"
|
||||
sodipodi:rx="171.42857"
|
||||
sodipodi:ry="171.42857"
|
||||
d="m 440.00002,569.50507 c 0,94.67738 -76.75119,171.42857 -171.42858,171.42857 -94.67739,0 -171.428572,-76.75119 -171.428572,-171.42857 0,-94.67739 76.751182,-171.42858 171.428572,-171.42858 94.67739,0 171.42858,76.75119 171.42858,171.42858 z" />
|
||||
<path
|
||||
id="path3633"
|
||||
d="m 193.02128,416.31621 0,17.11698 -69.31988,0 0,28.32175 69.31988,0 0,17.11698 27.09543,-15.63248 27.08251,-15.64537 -27.08251,-15.63248 -27.09543,-15.64538 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
transform="matrix(0.4679068,0,0,0.4679068,59.783914,181.11879)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#808080;stroke-width:10.80000019;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3635"
|
||||
sodipodi:cx="268.57144"
|
||||
sodipodi:cy="569.50507"
|
||||
sodipodi:rx="171.42857"
|
||||
sodipodi:ry="171.42857"
|
||||
d="m 440.00002,569.50507 c 0,94.67738 -76.75119,171.42857 -171.42858,171.42857 -94.67739,0 -171.428572,-76.75119 -171.428572,-171.42857 0,-94.67739 76.751182,-171.42858 171.428572,-171.42858 94.67739,0 171.42858,76.75119 171.42858,171.42858 z" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:url(#radialGradient3639);fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
id="path3637"
|
||||
sodipodi:cx="307.14285"
|
||||
sodipodi:cy="582.36218"
|
||||
sodipodi:rx="158.57143"
|
||||
sodipodi:ry="158.57143"
|
||||
d="m 465.71428,582.36218 c 0,87.57658 -70.99485,158.57143 -158.57143,158.57143 -87.57658,0 -158.57142,-70.99485 -158.57142,-158.57143 0,-87.57658 70.99484,-158.57142 158.57142,-158.57142 87.57658,0 158.57143,70.99484 158.57143,158.57142 z"
|
||||
transform="matrix(0.5847384,0,0,0.5847384,30.872504,70.269726)" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 9.2 KiB |
|
Depois Largura: | Altura: | Tamanho: 8.0 KiB |
|
Depois Largura: | Altura: | Tamanho: 8.0 KiB |
|
Depois Largura: | Altura: | Tamanho: 8.0 KiB |
|
Depois Largura: | Altura: | Tamanho: 2.0 KiB |
|
Depois Largura: | Altura: | Tamanho: 3.0 KiB |
|
Depois Largura: | Altura: | Tamanho: 1.9 KiB |
|
Depois Largura: | Altura: | Tamanho: 3.0 KiB |
|
Depois Largura: | Altura: | Tamanho: 82 B |
|
Depois Largura: | Altura: | Tamanho: 82 B |
|
Depois Largura: | Altura: | Tamanho: 175 B |
|
Depois Largura: | Altura: | Tamanho: 178 B |
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" title="Standard" href="styles.css" type="text/css" media="screen" />
|
||||
|
||||
<!-- styles.css contains white for background colour - we'll need an equivalent css statement for a black background -->
|
||||
<script language="JavaScript" type="text/javascript" src="contentflow.js" load="#BACKGROUND_COLOUR #ADDON"></script>
|
||||
<script style="text/javascript">
|
||||
var cf = new ContentFlow('contentFlow',
|
||||
{reflectionColor: "#000000",
|
||||
endOpacity : 0.3,
|
||||
circularFlow: true,
|
||||
startItem: #START,
|
||||
scaleFactor: #FACTOR,
|
||||
visibleItems: 7
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body{
|
||||
background: #BACKGROUND_COLOUR;
|
||||
color: #FOREGROUND_COLOUR;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
#MAXCOVERS
|
||||
<div class="maincontent">
|
||||
<div style="width: #WIDTHpx; margin: 0px auto;">
|
||||
|
||||
<!-- ===== FLOW ===== -->
|
||||
<div id="contentFlow" class="ContentFlow">
|
||||
<!-- should be place before flow so that contained images will be loaded first -->
|
||||
<div class="loadIndicator"><div class="indicator"></div></div>
|
||||
|
||||
<div class="flow">
|
||||
|
||||
#ITEMS
|
||||
|
||||
</div>
|
||||
#GLOBAL_CAPTION
|
||||
<!--
|
||||
<div class="scrollbar">
|
||||
<div class="slider"></div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,231 @@
|
||||
body {
|
||||
background: white;
|
||||
color: white;
|
||||
font-size: 8pt;
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0 7%;
|
||||
}
|
||||
|
||||
.className{
|
||||
background-color:#338BC7;
|
||||
width:270px;
|
||||
height:150px;
|
||||
position:relative;
|
||||
|
||||
-moz-border-radius:6px;
|
||||
-webkit-border-radius:6px;
|
||||
border-radius:6px;
|
||||
}
|
||||
|
||||
a,
|
||||
a:link,
|
||||
a:visited,
|
||||
a:active,
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.clear { clear: both; }
|
||||
|
||||
img { border: none; }
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
text-decoration: underline;
|
||||
font-family: serif;
|
||||
color: white;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 2.5em;
|
||||
font-size: 1.7em;
|
||||
text-decoration: underline;
|
||||
}
|
||||
h3 {
|
||||
margin-top: 2em;
|
||||
font-size: 1.3em;
|
||||
text-decoration: underline;
|
||||
}
|
||||
p {
|
||||
line-height: 150%;
|
||||
text-align: justify;
|
||||
}
|
||||
pre {
|
||||
font-family: sans-serif;
|
||||
background: #222;
|
||||
}
|
||||
.simpleBlack {
|
||||
background: black;
|
||||
width: 80ex;
|
||||
margin: 0 auto;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: monospace;
|
||||
font-size: 0.9em;
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-left: 4ex;
|
||||
}
|
||||
|
||||
dl dt {
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
color: #eee;
|
||||
font-family: monospace;
|
||||
}
|
||||
dl dd {
|
||||
margin-bottom: 1.5em;
|
||||
color: #ccc;
|
||||
font-size: 0.85em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
|
||||
ol {
|
||||
}
|
||||
ol li {
|
||||
margin-bottom: 1em;
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
ul {
|
||||
}
|
||||
ul li {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#title {
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
#sponsor {
|
||||
position: absolute;
|
||||
right: 7%;
|
||||
font-size: 10px;
|
||||
height: 66px;
|
||||
line-height: 66px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
div.maincontent {
|
||||
margin: 0px auto 20pt auto;
|
||||
}
|
||||
|
||||
#menu {
|
||||
display: block;
|
||||
text-align: center;
|
||||
background: #222;
|
||||
padding: 1em;
|
||||
margin: 2em auto 4em auto;
|
||||
}
|
||||
|
||||
#menu li {
|
||||
display: inline;
|
||||
padding: 0px 20px;
|
||||
}
|
||||
|
||||
.totop {
|
||||
text-align: center;
|
||||
margin: 4em 10%;
|
||||
padding: 0.25em;
|
||||
background: #161616;
|
||||
}
|
||||
.totop a {
|
||||
margin-right: 7%;
|
||||
color: silver;
|
||||
}
|
||||
|
||||
|
||||
.block {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
#browserComp {
|
||||
border-collapse: collapse;
|
||||
margin: 40px auto;
|
||||
}
|
||||
#browserComp caption {
|
||||
text-align: center;
|
||||
margin: 20px auto;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
#browserComp th {
|
||||
font-size: 10px;
|
||||
padding: 5px 10px;
|
||||
border-bottom: 1px solid silver;
|
||||
}
|
||||
#browserComp th img {
|
||||
width: 22px;
|
||||
}
|
||||
#browserComp td {
|
||||
text-align: center;
|
||||
}
|
||||
#browserComp th.feature,
|
||||
#browserComp td.feature {
|
||||
text-align: right;
|
||||
padding: 5px;
|
||||
padding-right: 10px;
|
||||
border-right: 1px solid silver;
|
||||
}
|
||||
|
||||
.addon {
|
||||
border: 1px solid #222;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
background: #222;
|
||||
}
|
||||
.addon .flowBox {
|
||||
width: 500px;
|
||||
margin-right: 40px;
|
||||
float: left;
|
||||
}
|
||||
.addon .discription {
|
||||
margin-left: 540px;
|
||||
}
|
||||
.addon .title {
|
||||
line-height: 1.3em;
|
||||
}
|
||||
.addon .title h3 {
|
||||
margin: 0;
|
||||
display: inline;
|
||||
}
|
||||
.addon .title .by {
|
||||
margin-left: 2em;
|
||||
font-size: 0.8em;
|
||||
text-decoration: none;
|
||||
}
|
||||
.addon p {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.addon .comment {
|
||||
margin-top: 2em;
|
||||
font-style: italic;
|
||||
}
|
||||
.addon .download {
|
||||
font-size: 0.8em;
|
||||
float: right;
|
||||
margin: 0 0 2em 4em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
.addon .download a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#info { /* for example.php */
|
||||
color: white;
|
||||
/*display: none;*/
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import gi
|
||||
from gi.repository import Pango
|
||||
from gi.repository import Gtk
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
|
||||
import logging
|
||||
|
||||
|
Depois Largura: | Altura: | Tamanho: 14 KiB |
|
Depois Largura: | Altura: | Tamanho: 9.6 KiB |
|
Depois Largura: | Altura: | Tamanho: 7.2 KiB |
|
Depois Largura: | Altura: | Tamanho: 8.5 KiB |
|
Depois Largura: | Altura: | Tamanho: 7.6 KiB |
|
Depois Largura: | Altura: | Tamanho: 9.0 KiB |
|
Antes Largura: | Altura: | Tamanho: 60 KiB Depois Largura: | Altura: | Tamanho: 60 KiB |
|
Depois Largura: | Altura: | Tamanho: 541 B |
|
Depois Largura: | Altura: | Tamanho: 3.7 KiB |
|
Depois Largura: | Altura: | Tamanho: 3.4 KiB |
|
Depois Largura: | Altura: | Tamanho: 13 KiB |
|
Depois Largura: | Altura: | Tamanho: 1.3 KiB |
|
Depois Largura: | Altura: | Tamanho: 1.2 KiB |
|
Depois Largura: | Altura: | Tamanho: 54 KiB |
|
Depois Largura: | Altura: | Tamanho: 2.7 KiB |
|
Depois Largura: | Altura: | Tamanho: 68 KiB |
|
Depois Largura: | Altura: | Tamanho: 19 KiB |
|
Depois Largura: | Altura: | Tamanho: 3.8 KiB |
|
Depois Largura: | Altura: | Tamanho: 17 KiB |
|
Depois Largura: | Altura: | Tamanho: 22 KiB |
|
Depois Largura: | Altura: | Tamanho: 2.7 KiB |
|
Depois Largura: | Altura: | Tamanho: 3.9 KiB |
|
Depois Largura: | Altura: | Tamanho: 368 B |
@@ -0,0 +1,202 @@
|
||||
<?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://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: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="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="Franco.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
y2="244.95164"
|
||||
x2="99.124153"
|
||||
y1="400.5535"
|
||||
x1="101.42937"
|
||||
gradientTransform="matrix(1.340328,0,0,1.340328,-31.467381,555.95415)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient6460-1"
|
||||
xlink:href="#linearGradient6364-8"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364-8">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366-5" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368-9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="244.95164"
|
||||
x2="99.124153"
|
||||
y1="400.5535"
|
||||
x1="101.42937"
|
||||
gradientTransform="matrix(1.340328,0,0,1.340328,133.59345,299.76445)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3022"
|
||||
xlink:href="#linearGradient6364-8"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6364-8"
|
||||
id="linearGradient3966"
|
||||
x1="440.96436"
|
||||
y1="94.980904"
|
||||
x2="447.48547"
|
||||
y2="491.33676"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6364-8-2"
|
||||
id="linearGradient3966-8"
|
||||
x1="440.96436"
|
||||
y1="94.980904"
|
||||
x2="447.48547"
|
||||
y2="491.33676"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364-8-2">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366-5-8" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368-9-1" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
id="filter4002"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4004"
|
||||
stdDeviation="7"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4006"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4008"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4010"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4012"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4014"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.52225797"
|
||||
inkscape:cx="353.55944"
|
||||
inkscape:cy="380.57923"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="1000"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1" />
|
||||
<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" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
id="path3048"
|
||||
style="fill:#333333"
|
||||
d="m 196.23032,388.02753 c -3.1625,-0.17639 -5.74997,-0.41075 -5.74994,-0.5208 4e-5,-0.11006 1.35004,-7.10107 3,-15.53558 1.64997,-8.43452 2.99994,-15.52202 2.99994,-15.75 0,-0.22799 3.08413,-0.41452 6.85362,-0.41452 l 6.85363,0 3.13824,15.6748 c 1.72603,8.62114 3.0294,15.7589 2.89638,15.86169 -0.62424,0.48234 -14.87054,0.97005 -19.99187,0.68441 z m -37.58129,91.8046 c 5.68507,-26.43563 21.62839,-41.0255 44.83129,-41.0255 18.15518,0 31.82505,8.81969 39.52313,25.5 2.87004,6.21885 3.86007,9.44962 6.43518,21 l 0.66884,3 21.92273,0 c 20.18917,0 21.94973,-0.14015 22.26407,-1.77237 0.40759,-2.11648 -10.69635,-24.34334 -26.54806,-53.14148 -11.39707,-20.70531 -11.50643,-20.96649 -10.96706,-26.19245 0.39075,-3.78605 0.15862,-5.5991 -0.82097,-6.41209 -1.04547,-0.86766 -1.11356,-1.68703 -0.29035,-3.49378 1.48268,-3.25413 0.45149,-5.28386 -2.87844,-5.66571 -2.4629,-0.28243 -3.42556,-1.55441 -7.8119,-10.32212 -6.23802,-12.46895 -13.04989,-32.67223 -12.70848,-37.69199 0.14323,-2.10603 -0.32646,-4.23152 -1.0934,-4.94795 -1.12497,-1.05087 -1.10874,-1.72854 0.0994,-4.15034 0.79415,-1.59191 1.50272,-5.1916 1.5746,-7.9993 0.11147,-4.35393 -0.19922,-5.27281 -2.112,-6.24624 -3.68961,-1.87767 -6.00171,-5.26503 -6.6488,-9.74089 -1.36194,-9.42061 -8.59426,-100.10119 -10.02716,-125.72329 -1.81034,-32.3711 -1.86263,-43.55534 -0.21854,-46.73467 2.00375,-3.87483 2.13663,-10.60596 0.24044,-12.17965 -0.76822,-0.63757 -1.16783,-2.03465 -0.88802,-3.10463 0.37015,-1.41548 -0.18621,-2.20962 -2.04244,-2.91536 -3.73433,-1.41979 -4.67277,-4.0055 -4.67277,-12.87495 0,-10.503593 -0.78166,-14.190743 -3.00837,-14.190743 -2.34316,0 -2.96163,2.76543 -2.97798,13.315743 -0.0151,9.73751 -0.89079,12.30685 -4.68642,13.74995 -1.90884,0.72574 -2.41663,1.48443 -2.01682,3.0133 0.32514,1.24334 -0.0225,2.25705 -0.88803,2.58917 -2.02638,0.77759 -1.87332,9.71399 0.22113,12.91052 1.43529,2.19053 1.57348,5.00498 1.09076,22.21482 -0.30401,10.83857 -1.0474,24.6565 -1.65198,30.7065 -0.60458,6.05 -2.02755,24.275 -3.16216,40.5 -1.80776,25.85116 -3.20459,43.53305 -5.49034,69.5 -1.10665,12.57186 -2.71725,16.47258 -7.85201,19.01682 -2.69729,1.33648 -3.098,5.22174 -1.20469,11.68045 1.09273,3.72763 1.22363,5.68776 0.47345,7.08948 -0.57027,1.06555 -0.81718,3.08648 -0.5487,4.49096 0.65367,3.41945 -7.51963,27.25432 -13.27839,38.72229 -4.17675,8.31754 -4.76589,9.02376 -7.76945,9.31336 -3.47466,0.33502 -4.25346,2.44314 -2.27101,6.14738 0.70326,1.31405 0.58446,2.15668 -0.42181,2.99181 -1.02028,0.84675 -1.25209,2.60341 -0.85335,6.46677 0.53305,5.16476 0.33701,5.68256 -7.45546,19.69245 -11.62472,20.89979 -25.68313,47.58052 -28.25219,53.61838 -3.64643,8.56989 -4.21545,8.34839 20.65307,8.03942 l 21.697,-0.26957 1.82246,-8.4745 z"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 dark icons/Tour_Effel_Dark.png"
|
||||
inkscape:export-xdpi="29.227327"
|
||||
inkscape:export-ydpi="29.227327" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d=""
|
||||
id="path3019"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d=""
|
||||
id="path3017"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d=""
|
||||
id="path3015"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d=""
|
||||
id="path3013"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3048-1"
|
||||
style="fill:url(#linearGradient3966);stroke:#666666;fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 435.07498,387.56901 c -3.1625,-0.17639 -5.74997,-0.41075 -5.74994,-0.5208 4e-5,-0.11006 1.35004,-7.10107 3,-15.53558 1.64997,-8.43452 2.99994,-15.52202 2.99994,-15.75 0,-0.22799 3.08413,-0.41452 6.85362,-0.41452 l 6.85363,0 3.13824,15.6748 c 1.72603,8.62114 3.0294,15.7589 2.89638,15.86169 -0.62424,0.48234 -14.87054,0.97005 -19.99187,0.68441 z m -37.58129,91.8046 c 5.68507,-26.43563 21.62839,-41.0255 44.83129,-41.0255 18.15518,0 31.82505,8.81969 39.52313,25.5 2.87004,6.21885 3.86007,9.44962 6.43518,21 l 0.66884,3 21.92273,0 c 20.18917,0 21.94973,-0.14015 22.26407,-1.77237 0.40759,-2.11648 -10.69635,-24.34334 -26.54806,-53.14148 -11.39707,-20.70531 -11.50643,-20.96649 -10.96706,-26.19245 0.39075,-3.78605 0.15862,-5.5991 -0.82097,-6.41209 -1.04547,-0.86766 -1.11356,-1.68703 -0.29035,-3.49378 1.48268,-3.25413 0.45149,-5.28386 -2.87844,-5.66571 -2.4629,-0.28243 -3.42556,-1.55441 -7.8119,-10.32212 -6.23802,-12.46895 -13.04989,-32.67223 -12.70848,-37.69199 0.14323,-2.10603 -0.32646,-4.23152 -1.0934,-4.94795 -1.12497,-1.05087 -1.10874,-1.72854 0.0994,-4.15034 0.79415,-1.59191 1.50272,-5.1916 1.5746,-7.9993 0.11147,-4.35393 -0.19922,-5.27281 -2.112,-6.24624 -3.68961,-1.87767 -6.00171,-5.26503 -6.6488,-9.74089 -1.36194,-9.42061 -8.59426,-100.10119 -10.02716,-125.72329 -1.81034,-32.3711 -1.86263,-43.55534 -0.21854,-46.73467 2.00375,-3.87483 2.13663,-10.60596 0.24044,-12.17965 -0.76822,-0.63757 -1.16783,-2.03465 -0.88802,-3.10463 0.37015,-1.41548 -0.18621,-2.20962 -2.04244,-2.91536 -3.73433,-1.41979 -4.67277,-4.0055 -4.67277,-12.87495 0,-10.503592 -0.78166,-14.190742 -3.00837,-14.190742 -2.34316,0 -2.96163,2.76543 -2.97798,13.315742 -0.0151,9.73751 -0.89079,12.30685 -4.68642,13.74995 -1.90884,0.72574 -2.41663,1.48443 -2.01682,3.0133 0.32514,1.24334 -0.0225,2.25705 -0.88803,2.58917 -2.02638,0.77759 -1.87332,9.71399 0.22113,12.91052 1.43529,2.19053 1.57348,5.00498 1.09076,22.21482 -0.30401,10.83857 -1.0474,24.6565 -1.65198,30.7065 -0.60458,6.05 -2.02755,24.275 -3.16216,40.5 -1.80776,25.85116 -3.20459,43.53305 -5.49034,69.5 -1.10665,12.57186 -2.71725,16.47258 -7.85201,19.01682 -2.69729,1.33648 -3.098,5.22174 -1.20469,11.68045 1.09273,3.72763 1.22363,5.68776 0.47345,7.08948 -0.57027,1.06555 -0.81718,3.08648 -0.5487,4.49096 0.65367,3.41945 -7.51963,27.25432 -13.27839,38.72229 -4.17675,8.31754 -4.76589,9.02376 -7.76945,9.31336 -3.47466,0.33502 -4.25346,2.44314 -2.27101,6.14738 0.70326,1.31405 0.58446,2.15668 -0.42181,2.99181 -1.02028,0.84675 -1.25209,2.60341 -0.85335,6.46677 0.53305,5.16476 0.33701,5.68256 -7.45546,19.69245 -11.62472,20.89979 -25.68313,47.58052 -28.25219,53.61838 -3.64643,8.56989 -4.21545,8.34839 20.65307,8.03942 l 21.697,-0.26957 1.82246,-8.4745 z"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 icons/Tour_Effel.png"
|
||||
inkscape:export-xdpi="28.748562"
|
||||
inkscape:export-ydpi="28.748562" />
|
||||
<path
|
||||
id="path3048-1-8"
|
||||
style="fill:#b3b3b3;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;filter:url(#filter4002)"
|
||||
d="m 201.47395,870.08916 c -3.1625,-0.17639 -5.74997,-0.41075 -5.74994,-0.5208 4e-5,-0.11006 1.35004,-7.10107 3,-15.53558 1.64997,-8.43452 2.99994,-15.52202 2.99994,-15.75 0,-0.22799 3.08413,-0.41452 6.85362,-0.41452 l 6.85363,0 3.13824,15.6748 c 1.72603,8.62114 3.0294,15.7589 2.89638,15.86169 -0.62424,0.48234 -14.87054,0.97005 -19.99187,0.68441 z m -37.58129,91.8046 c 5.68507,-26.43563 21.62839,-41.0255 44.83129,-41.0255 18.15518,0 31.82505,8.81969 39.52313,25.5 2.87004,6.21885 3.86007,9.44962 6.43518,21 l 0.66884,3 21.92273,0 c 20.18917,0 21.94973,-0.14015 22.26407,-1.77237 0.40759,-2.11648 -10.69635,-24.34334 -26.54806,-53.14148 -11.39707,-20.70531 -11.50643,-20.96649 -10.96706,-26.19245 0.39075,-3.78605 0.15862,-5.5991 -0.82097,-6.41209 -1.04547,-0.86766 -1.11356,-1.68703 -0.29035,-3.49378 1.48268,-3.25413 0.45149,-5.28386 -2.87844,-5.66571 -2.4629,-0.28243 -3.42556,-1.55441 -7.8119,-10.32212 -6.23802,-12.46895 -13.04989,-32.67223 -12.70848,-37.69199 0.14323,-2.10603 -0.32646,-4.23152 -1.0934,-4.94795 -1.12497,-1.05087 -1.10874,-1.72854 0.0994,-4.15034 0.79415,-1.59191 1.50272,-5.1916 1.5746,-7.9993 0.11147,-4.35393 -0.19922,-5.27281 -2.112,-6.24624 -3.68961,-1.87767 -6.00171,-5.26503 -6.6488,-9.74089 -1.36194,-9.42061 -8.59426,-100.10119 -10.02716,-125.72328 -1.81034,-32.3711 -1.86263,-43.55534 -0.21854,-46.73467 2.00375,-3.87483 2.13663,-10.60596 0.24044,-12.17965 -0.76822,-0.63757 -1.16783,-2.03465 -0.88802,-3.10463 0.37015,-1.41548 -0.18621,-2.20962 -2.04244,-2.91536 -3.73433,-1.41979 -4.67277,-4.0055 -4.67277,-12.87495 0,-10.5036 -0.78166,-14.19075 -3.00837,-14.19075 -2.34316,0 -2.96163,2.76543 -2.97798,13.31575 -0.0151,9.73751 -0.89079,12.30685 -4.68642,13.74995 -1.90884,0.72574 -2.41663,1.48443 -2.01682,3.0133 0.32514,1.24334 -0.0225,2.25705 -0.88803,2.58917 -2.02638,0.77759 -1.87332,9.71399 0.22113,12.91052 1.43529,2.19053 1.57348,5.00498 1.09076,22.21482 -0.30401,10.83857 -1.0474,24.6565 -1.65198,30.70649 -0.60458,6.05 -2.02755,24.275 -3.16216,40.5 -1.80776,25.85116 -3.20459,43.53305 -5.49034,69.5 -1.10665,12.57186 -2.71725,16.47258 -7.85201,19.01682 -2.69729,1.33648 -3.098,5.22174 -1.20469,11.68045 1.09273,3.72763 1.22363,5.68776 0.47345,7.08948 -0.57027,1.06555 -0.81718,3.08648 -0.5487,4.49096 0.65367,3.41945 -7.51963,27.25432 -13.27839,38.72229 -4.17675,8.31754 -4.76589,9.02376 -7.76945,9.31336 -3.47466,0.33502 -4.25346,2.44314 -2.27101,6.14738 0.70326,1.31405 0.58446,2.15668 -0.42181,2.99181 -1.02028,0.84675 -1.25209,2.60341 -0.85335,6.46677 0.53305,5.16476 0.33701,5.68256 -7.45546,19.69245 -11.62472,20.89979 -25.68313,47.58052 -28.25219,53.61838 -3.64643,8.56989 -4.21545,8.34839 20.65307,8.03942 l 21.697,-0.26957 1.82246,-8.4745 z"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 light/Tour_Effel_Light.png"
|
||||
inkscape:export-xdpi="100"
|
||||
inkscape:export-ydpi="100" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 14 KiB |
@@ -0,0 +1,373 @@
|
||||
<?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://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"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Genre_Quebecois.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter3839">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="1.885992"
|
||||
id="feGaussianBlur3841" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:collect="always"
|
||||
id="filter3839-4">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="1.885992"
|
||||
id="feGaussianBlur3841-9" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.53212713"
|
||||
inkscape:cx="231.89759"
|
||||
inkscape:cy="589.80239"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="838"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<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" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#333333;stroke:none;filter:url(#filter3839)"
|
||||
d="m 158.66886,202.42048 c -1.24282,-1.91859 -3.99614,-4.74624 -6.11849,-6.28367 l -3.85881,-2.79531 2.42335,-2.95395 c 4.57156,-5.57251 10.43395,-19.45395 8.21576,-19.45395 -0.49617,0 -0.90213,0.47833 -0.90213,1.06295 0,0.58462 -1.20409,3.52202 -2.67576,6.52756 -3.34771,6.83692 -10.71552,13.84722 -16.31733,15.52557 -3.7809,1.13278 -4.6427,1.05924 -7.87617,-0.67206 -3.17425,-1.6996 -3.66904,-2.47097 -3.93536,-6.13518 -0.26372,-3.62839 0.0617,-4.43119 2.42372,-5.97883 2.02052,-1.3239 2.83615,-1.46425 3.14391,-0.54099 0.7042,2.1126 3.28859,4.21098 5.18629,4.21098 5.25901,0 12.87594,-5.72708 14.96233,-11.25 l 1.03887,-2.75 -4.77525,0 c -5.23603,0 -7.17525,-1.24133 -7.17525,-4.59301 0,-2.69216 1.70981,-3.40699 8.14917,-3.40699 4.70924,0 4.94713,-0.12472 4.29153,-2.25 -2.16346,-7.01337 -10.02555,-15.96707 -17.26216,-19.65891 -4.35269,-2.22058 -10.13687,-2.71894 -13.10713,-1.12931 -3.83357,2.05166 -4.76949,7.97721 -2.4937,15.78822 0.61968,2.12688 0.37382,2.25 -4.4932,2.25 -2.83181,0 -6.60382,-0.60797 -8.38225,-1.35104 -7.92003,-3.3092 -12.963546,-14.24304 -10.609576,-23.00046 2.312466,-8.60297 14.134186,-15.55932 24.463236,-14.39509 8.93345,1.00693 20.22327,8.99665 26.58443,18.81358 1.75731,2.71199 3.35834,4.76765 3.55785,4.56814 0.69158,-0.69158 -5.11825,-13.16126 -8.62402,-18.5098 -2.9593,-4.51482 -3.58357,-6.44847 -3.90216,-12.08672 -0.5025,-8.89315 1.68676,-13.162576 10.23904,-19.967833 3.56979,-2.84057 7.41267,-6.38104 8.53973,-7.86772 l 2.04921,-2.70305 2.04921,2.70305 c 1.12706,1.48668 4.96994,5.02715 8.53973,7.86772 7.83453,6.234117 10.41106,10.793073 10.41106,18.421503 0,6.62555 -1.41372,10.31711 -6.48774,16.94111 -4.65595,6.0782 -8.05961,12.86293 -8.93796,17.81661 -0.36571,2.0625 -0.47319,3.75 -0.23884,3.75 0.23435,0 1.71724,-2.58058 3.29531,-5.73461 3.50271,-7.00073 14.20441,-17.99154 20.47842,-21.03164 10.08278,-4.88567 21.38081,-3.49588 28.76857,3.53885 7.18183,6.83865 7.52916,18.27754 0.78809,25.95519 -3.92717,4.4728 -8.15884,6.27221 -14.75036,6.27221 -4.86702,0 -5.11288,-0.12312 -4.4932,-2.25 1.5791,-5.41982 1.74838,-8.92375 0.56872,-11.7717 -1.53377,-3.70286 -3.70253,-4.9783 -8.46511,-4.9783 -8.75282,0 -21.75002,11.32269 -24.9666,21.75 -0.6556,2.12528 -0.41771,2.25 4.29152,2.25 6.43937,0 8.14918,0.71483 8.14918,3.40699 0,3.35168 -1.93922,4.59301 -7.17525,4.59301 l -4.77525,0 1.03887,2.75 c 2.08639,5.52292 9.70332,11.25 14.96232,11.25 1.89771,0 4.4821,-2.09838 5.1863,-4.21098 0.30776,-0.92326 1.12338,-0.78291 3.14391,0.54099 2.362,1.54764 2.68744,2.35044 2.42372,5.97883 -0.26632,3.66421 -0.76111,4.43558 -3.93536,6.13518 -3.23347,1.7313 -4.09527,1.80484 -7.87617,0.67206 -5.60181,-1.67835 -12.96962,-8.68865 -16.31733,-15.52557 -1.47167,-3.00554 -2.67576,-5.94294 -2.67576,-6.52756 0,-0.58462 -0.40596,-1.06295 -0.90213,-1.06295 -2.21819,0 3.6442,13.88144 8.21576,19.45395 l 2.42335,2.95395 -3.85881,2.79531 c -2.12235,1.53743 -4.87567,4.36508 -6.11849,6.28367 -1.24283,1.9186 -2.48468,3.48836 -2.75968,3.48836 -0.275,0 -1.51685,-1.56976 -2.75968,-3.48836 z m 3.75968,-42.48688 c 0,-1.65 -0.45,-3 -1,-3 -0.55,0 -1,1.35 -1,3 0,1.65 0.45,3 1,3 0.55,0 1,-1.35 1,-3 z"
|
||||
id="path3047-4"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.0 New light/path3047.png"
|
||||
inkscape:export-xdpi="82.564102"
|
||||
inkscape:export-ydpi="82.564102" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke:none;filter:url(#filter3839-4)"
|
||||
d="m 158.66886,208.42047 c -1.24282,-1.91859 -3.99614,-4.74624 -6.11849,-6.28367 l -3.85881,-2.79531 2.42335,-2.95395 c 4.57156,-5.57251 10.43395,-19.45394 8.21576,-19.45394 -0.49617,0 -0.90213,0.47833 -0.90213,1.06295 0,0.58462 -1.20409,3.52202 -2.67576,6.52755 -3.34771,6.83692 -10.71552,13.84722 -16.31733,15.52557 -3.7809,1.13278 -4.6427,1.05924 -7.87617,-0.67206 -3.17425,-1.6996 -3.66904,-2.47097 -3.93536,-6.13518 -0.26372,-3.62839 0.0617,-4.43119 2.42372,-5.97883 2.02052,-1.3239 2.83615,-1.46425 3.14391,-0.54099 0.7042,2.1126 3.28859,4.21098 5.18629,4.21098 5.25901,0 12.87594,-5.72708 14.96233,-11.24999 l 1.03887,-2.75 -4.77525,0 c -5.23603,0 -7.17525,-1.24133 -7.17525,-4.59301 0,-2.69216 1.70981,-3.40699 8.14917,-3.40699 4.70924,0 4.94713,-0.12472 4.29153,-2.25 -2.16346,-7.01337 -10.02555,-15.96707 -17.26216,-19.65891 -4.35269,-2.22058 -10.13687,-2.71894 -13.10713,-1.12931 -3.83357,2.05166 -4.76949,7.97721 -2.4937,15.78822 0.61968,2.12688 0.37382,2.25 -4.4932,2.25 -2.83181,0 -6.60382,-0.60797 -8.38225,-1.35104 -7.92003,-3.3092 -12.963546,-14.24304 -10.609576,-23.00046 2.312466,-8.60297 14.134186,-15.55932 24.463236,-14.39509 8.93345,1.00693 20.22327,8.99665 26.58443,18.81358 1.75731,2.71199 3.35834,4.76765 3.55785,4.56814 0.69158,-0.69158 -5.11825,-13.16126 -8.62402,-18.5098 -2.9593,-4.51482 -3.58357,-6.44847 -3.90216,-12.08672 -0.5025,-8.89315 1.68676,-13.16258 10.23904,-19.967836 3.56979,-2.84057 7.41267,-6.38104 8.53973,-7.86772 l 2.04921,-2.70305 2.04921,2.70305 c 1.12706,1.48668 4.96994,5.02715 8.53973,7.86772 7.83453,6.234116 10.41106,10.793076 10.41106,18.421506 0,6.62555 -1.41372,10.31711 -6.48774,16.94111 -4.65595,6.0782 -8.05961,12.86293 -8.93796,17.81661 -0.36571,2.0625 -0.47319,3.75 -0.23884,3.75 0.23435,0 1.71724,-2.58058 3.29531,-5.73461 3.50271,-7.00073 14.20441,-17.99154 20.47842,-21.03164 10.08278,-4.88567 21.38081,-3.49588 28.76857,3.53885 7.18183,6.83865 7.52916,18.27754 0.78809,25.95519 -3.92717,4.4728 -8.15884,6.27221 -14.75036,6.27221 -4.86702,0 -5.11288,-0.12312 -4.4932,-2.25 1.5791,-5.41982 1.74838,-8.92375 0.56872,-11.7717 -1.53377,-3.70286 -3.70253,-4.9783 -8.46511,-4.9783 -8.75282,0 -21.75002,11.32269 -24.9666,21.75 -0.6556,2.12528 -0.41771,2.25 4.29152,2.25 6.43937,0 8.14918,0.71483 8.14918,3.40699 0,3.35168 -1.93922,4.59301 -7.17525,4.59301 l -4.77525,0 1.03887,2.75 c 2.08639,5.52291 9.70332,11.24999 14.96232,11.24999 1.89771,0 4.4821,-2.09838 5.1863,-4.21098 0.30776,-0.92326 1.12338,-0.78291 3.14391,0.54099 2.362,1.54764 2.68744,2.35044 2.42372,5.97883 -0.26632,3.66421 -0.76111,4.43558 -3.93536,6.13518 -3.23347,1.7313 -4.09527,1.80484 -7.87617,0.67206 -5.60181,-1.67835 -12.96962,-8.68865 -16.31733,-15.52557 -1.47167,-3.00553 -2.67576,-5.94293 -2.67576,-6.52755 0,-0.58462 -0.40596,-1.06295 -0.90213,-1.06295 -2.21819,0 3.6442,13.88143 8.21576,19.45394 l 2.42335,2.95395 -3.85881,2.79531 c -2.12235,1.53743 -4.87567,4.36508 -6.11849,6.28367 -1.24283,1.9186 -2.48468,3.48836 -2.75968,3.48836 -0.275,0 -1.51685,-1.56976 -2.75968,-3.48836 z m 3.75968,-42.48687 c 0,-1.65 -0.45,-3 -1,-3 -0.55,0 -1,1.35 -1,3 0,1.65 0.45,3 1,3 0.55,0 1,-1.35 1,-3 z"
|
||||
id="path3047-4-5"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.0 New light/path3047.png"
|
||||
inkscape:export-xdpi="82.564102"
|
||||
inkscape:export-ydpi="82.564102" />
|
||||
<path
|
||||
style="fill:#b3b3b3;stroke:#333333"
|
||||
d="m 158.66886,205.13477 c -1.24282,-1.91859 -3.99614,-4.74624 -6.11849,-6.28367 l -3.85881,-2.79531 2.42335,-2.95395 c 4.57156,-5.57251 10.43395,-19.45395 8.21576,-19.45395 -0.49617,0 -0.90213,0.47833 -0.90213,1.06295 0,0.58462 -1.20409,3.52202 -2.67576,6.52756 -3.34771,6.83692 -10.71552,13.84722 -16.31733,15.52557 -3.7809,1.13278 -4.6427,1.05924 -7.87617,-0.67206 -3.17425,-1.6996 -3.66904,-2.47097 -3.93536,-6.13518 -0.26372,-3.62839 0.0617,-4.43119 2.42372,-5.97883 2.02052,-1.3239 2.83615,-1.46425 3.14391,-0.54099 0.7042,2.1126 3.28859,4.21098 5.18629,4.21098 5.25901,0 12.87594,-5.72708 14.96233,-11.25 l 1.03887,-2.75 -4.77525,0 c -5.23603,0 -7.17525,-1.24133 -7.17525,-4.59301 0,-2.69216 1.70981,-3.40699 8.14917,-3.40699 4.70924,0 4.94713,-0.12472 4.29153,-2.25 -2.16346,-7.01337 -10.02555,-15.96707 -17.26216,-19.65891 -4.35269,-2.22058 -10.13687,-2.71894 -13.10713,-1.12931 -3.83357,2.05166 -4.76949,7.97721 -2.4937,15.78822 0.61968,2.12688 0.37382,2.25 -4.4932,2.25 -2.83181,0 -6.60382,-0.60797 -8.38225,-1.35104 -7.92003,-3.3092 -12.963546,-14.24304 -10.609576,-23.00046 2.312466,-8.60297 14.134186,-15.55932 24.463236,-14.39509 8.93345,1.00693 20.22327,8.99665 26.58443,18.81358 1.75731,2.71199 3.35834,4.76765 3.55785,4.56814 0.69158,-0.69158 -5.11825,-13.16126 -8.62402,-18.5098 -2.9593,-4.51482 -3.58357,-6.44847 -3.90216,-12.08672 -0.5025,-8.89315 1.68676,-13.16258 10.23904,-19.967836 3.56979,-2.84057 7.41267,-6.38104 8.53973,-7.86772 l 2.04921,-2.70305 2.04921,2.70305 c 1.12706,1.48668 4.96994,5.02715 8.53973,7.86772 7.83453,6.234116 10.41106,10.793076 10.41106,18.421506 0,6.62555 -1.41372,10.31711 -6.48774,16.94111 -4.65595,6.0782 -8.05961,12.86293 -8.93796,17.81661 -0.36571,2.0625 -0.47319,3.75 -0.23884,3.75 0.23435,0 1.71724,-2.58058 3.29531,-5.73461 3.50271,-7.00073 14.20441,-17.99154 20.47842,-21.03164 10.08278,-4.88567 21.38081,-3.49588 28.76857,3.53885 7.18183,6.83865 7.52916,18.27754 0.78809,25.95519 -3.92717,4.4728 -8.15884,6.27221 -14.75036,6.27221 -4.86702,0 -5.11288,-0.12312 -4.4932,-2.25 1.5791,-5.41982 1.74838,-8.92375 0.56872,-11.7717 -1.53377,-3.70286 -3.70253,-4.9783 -8.46511,-4.9783 -8.75282,0 -21.75002,11.32269 -24.9666,21.75 -0.6556,2.12528 -0.41771,2.25 4.29152,2.25 6.43937,0 8.14918,0.71483 8.14918,3.40699 0,3.35168 -1.93922,4.59301 -7.17525,4.59301 l -4.77525,0 1.03887,2.75 c 2.08639,5.52292 9.70332,11.25 14.96232,11.25 1.89771,0 4.4821,-2.09838 5.1863,-4.21098 0.30776,-0.92326 1.12338,-0.78291 3.14391,0.54099 2.362,1.54764 2.68744,2.35044 2.42372,5.97883 -0.26632,3.66421 -0.76111,4.43558 -3.93536,6.13518 -3.23347,1.7313 -4.09527,1.80484 -7.87617,0.67206 -5.60181,-1.67835 -12.96962,-8.68865 -16.31733,-15.52557 -1.47167,-3.00554 -2.67576,-5.94294 -2.67576,-6.52756 0,-0.58462 -0.40596,-1.06295 -0.90213,-1.06295 -2.21819,0 3.6442,13.88144 8.21576,19.45395 l 2.42335,2.95395 -3.85881,2.79531 c -2.12235,1.53743 -4.87567,4.36508 -6.11849,6.28367 -1.24283,1.9186 -2.48468,3.48836 -2.75968,3.48836 -0.275,0 -1.51685,-1.56976 -2.75968,-3.48836 z m 3.75968,-42.48688 c 0,-1.65 -0.45,-3 -1,-3 -0.55,0 -1,1.35 -1,3 0,1.65 0.45,3 1,3 0.55,0 1,-1.35 1,-3 z"
|
||||
id="path3047"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-xdpi="82.564102"
|
||||
inkscape:export-ydpi="82.564102" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 448.04252,335.21056 c -2.58411,-3.90486 -2.64377,-4.28088 -1.38842,-8.75 2.36519,-8.4202 2.42052,-9.16981 0.67677,-9.16981 -1.00491,0 -1.6228,0.85134 -1.63303,2.25 -0.009,1.2375 -1.03276,4.05 -2.27492,6.25 -1.89789,3.36138 -2.83489,4.04846 -5.86886,4.30353 -2.9275,0.24611 -4.01039,-0.20497 -5.72508,-2.38486 -2.79351,-3.55136 -2.74637,-7.86282 0.10782,-9.86197 3.1443,-2.20235 3.59164,-1.98118 3.42494,1.6933 -0.11897,2.62223 0.26851,3.30928 2.00599,3.5569 1.34948,0.19232 2.7495,-0.54409 3.75,-1.97251 2.11855,-3.02465 2.01917,-3.63527 -0.65344,-4.01484 -1.47682,-0.20974 -2.25,-1.00682 -2.25,-2.31955 0,-1.31273 0.77318,-2.10981 2.25,-2.31955 2.7935,-0.39674 2.91486,-3.12231 0.38652,-8.68045 -2.32594,-5.11319 -4.31878,-6.72462 -7.81866,-6.32226 -3.67436,0.42243 -6.04813,4.92407 -4.44818,8.43558 0.59809,1.31268 1.7759,2.38668 2.61736,2.38668 1.24341,0 1.3115,-0.34972 0.36361,-1.86753 -1.50331,-2.4072 -0.3652,-5.37672 1.89633,-4.94783 2.11197,0.40053 2.84387,4.84283 1.27949,7.76591 -1.4247,2.66207 -6.35601,2.71991 -8.97069,0.10523 -4.18792,-4.18792 -3.47358,-15.24888 1.19603,-18.5196 1.20626,-0.8449 3.69042,-1.53618 5.52036,-1.53618 7.61625,0 11.51476,4.7897 13.54483,16.64112 0.59907,3.49738 1.50025,6.35888 2.00261,6.35888 1.61541,0 -0.39,-13.16311 -3.40998,-22.38242 -1.6003,-4.88534 -2.90523,-9.38534 -2.89986,-10 0.0166,-1.90269 4.68879,-10.96512 7.22385,-14.01186 l 2.4082,-2.89428 4.17909,6.25823 c 5.01866,7.5155 5.27378,10.72719 1.69822,21.37862 -2.70903,8.07006 -4.46866,21.65171 -2.80519,21.65171 0.55063,0 1.28393,-2.70554 1.62956,-6.01231 0.70613,-6.75588 3.52118,-13.07907 6.86562,-15.42161 1.22974,-0.86134 4.12076,-1.56608 6.42449,-1.56608 3.40366,0 4.65039,0.54881 6.6528,2.92853 3.50935,4.17063 4.2565,9.30215 2.01935,13.86925 -3.72668,7.60797 -10.80576,7.34195 -10.80576,-0.40606 0,-2.77121 0.45944,-3.95281 1.62417,-4.17712 2.15621,-0.41524 3.14674,2.41068 1.75591,5.00947 -0.95142,1.77776 -0.86656,1.98472 0.58537,1.42756 0.93397,-0.3584 1.88632,-0.65163 2.11634,-0.65163 0.85544,0 0.38112,-6.20078 -0.61697,-8.06574 -1.43017,-2.6723 -6.08256,-2.50391 -8.72389,0.31574 -4.3537,4.64763 -5.77777,12.75 -2.24093,12.75 1.36314,0 2,0.66667 2,2.09362 0,1.25262 -0.8034,2.30371 -2,2.61663 -2.52507,0.66032 -2.55372,2.47867 -0.0744,4.72242 2.98769,2.70382 5.60373,1.63421 5.42695,-2.21889 -0.17171,-3.7426 0.8241,-4.03713 3.75162,-1.10961 1.60208,1.60208 1.95717,2.83914 1.48812,5.18438 -0.94053,4.70267 -3.40555,6.85902 -7.44184,6.50996 -3.96575,-0.34296 -6.96288,-3.64633 -8.02644,-8.84655 -0.73703,-3.60366 -3.12401,-5.29489 -3.12401,-2.21343 0,1.04785 0.71747,4.01085 1.59438,6.58443 1.56902,4.60484 1.55245,4.75078 -1.04216,9.17814 -1.45009,2.4744 -2.83617,4.4989 -3.08019,4.4989 -0.24401,0 -1.65872,-1.83609 -3.1438,-4.08019 z"
|
||||
id="path3086" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 297.75775,335.13026 c -1.11979,-1.83671 -2.03767,-4.99265 -2.03972,-7.01319 -0.005,-4.61059 2.0777,-13.82632 3.1242,-13.82632 0.43144,0 0.93974,3.2625 1.12955,7.25 l 0.34512,7.25 0.19869,-7.25 c 0.10929,-3.9875 0.60353,-7.25 1.09832,-7.25 0.49479,0 1.64743,3.36125 2.56141,7.46945 1.54629,6.95026 1.54686,7.71166 0.008,10.954 -2.73186,5.75698 -4.07995,6.26384 -6.42584,2.41603 z"
|
||||
id="path3084" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 369.14283,335.63774 c -1.56934,-2.31669 -1.89237,-4.38358 -1.73433,-11.09696 0.20904,-8.88036 -1.04265,-11.08058 -2.14015,-3.76195 -0.37016,2.46843 -1.3534,5.16843 -2.18497,6 -2.27749,2.2775 -5.97236,1.83177 -8.19043,-0.98805 -2.4382,-3.09967 -3.92463,-3.18379 -4.41772,-0.25 -0.36648,2.18047 -0.41995,2.16502 -1.73007,-0.5 -1.06645,-2.16935 -1.10263,-3.29709 -0.17133,-5.34108 1.10298,-2.42077 1.4961,-2.54768 5.98072,-1.93089 3.75544,0.5165 5.08886,0.31231 6.12671,-0.93824 1.12775,-1.35885 0.98017,-1.96716 -0.98467,-4.05863 -2.2283,-2.37192 -2.24716,-2.53101 -0.52549,-4.43344 2.03943,-2.25354 1.55361,-4.43659 -1.33088,-5.98032 -2.75582,-1.4749 -5.12593,1.07003 -5.12593,5.504 0,6.45265 -7.09337,9.98875 -10.4433,5.20606 -1.55766,-2.22387 -2.12165,-5.77749 -0.91694,-5.77749 0.35186,0 1.21973,0.7875 1.92858,1.75 1.20809,1.64038 1.33027,1.64311 1.95051,0.0436 0.36394,-0.93855 0.23948,-3.6861 -0.27657,-6.10568 -1.30712,-6.12868 -0.47791,-10.22412 2.77517,-13.70656 3.18422,-3.40872 7.21342,-3.90877 10.86826,-1.34882 2.75274,1.9281 6.06123,8.74808 6.09233,12.55848 0.0121,1.48004 0.47196,2.9691 1.02196,3.30902 1.75578,1.08513 1.09889,-6.90558 -1.07636,-13.09345 -2.71508,-7.72349 -2.14883,-14.26052 2.22157,-25.64687 1.84514,-4.80718 3.60368,-8.74468 3.90789,-8.75 0.3042,-0.005 2.2167,4.48884 4.25,9.98703 4.23884,11.46215 4.5981,16.75574 1.6969,25.00329 -2.07382,5.89546 -2.68552,13.54171 -1,12.5 0.55,-0.33992 1.00251,-1.37898 1.00558,-2.30902 0.0129,-3.9017 2.37309,-9.72349 5.01177,-12.36218 7.83481,-7.83481 17.79989,1.14831 14.90117,13.43282 -0.61797,2.61889 -0.84306,5.49265 -0.5002,6.38612 0.5655,1.47366 0.80715,1.45819 2.60253,-0.16661 1.90733,-1.72611 1.97915,-1.72098 1.97915,0.14138 0,4.57848 -5.13247,7.9277 -8.6003,5.61218 -1.73792,-1.16045 -3.3997,-4.87412 -3.3997,-7.59752 0,-3.60688 -2.59778,-5.9228 -5.12593,-4.56977 -2.88449,1.54373 -3.37031,3.72678 -1.33088,5.98032 1.71913,1.89962 1.70748,2.05678 -0.3124,4.21276 -1.63664,1.7469 -1.8698,2.64599 -1.06001,4.0874 0.86694,1.54312 1.77337,1.73762 5.49611,1.17936 5.04192,-0.75608 7.33311,0.46373 7.33311,3.90408 0,1.20253 -0.71174,3.05993 -1.58164,4.12755 -1.31039,1.60824 -1.48937,1.64651 -1.04367,0.22316 0.91426,-2.91967 -1.39978,-3.13217 -4.26067,-0.39127 -4.97808,4.7693 -9.31352,2.66374 -10.59377,-5.14501 -1.10118,-6.71656 -2.59247,-3.87259 -1.89643,3.61659 0.51603,5.55228 0.283,7.41241 -1.32004,10.53707 l -1.9467,3.79451 -1.92854,-2.84696 z"
|
||||
id="path3082" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 588.10408,336.11152 c -3.1521,-3.49715 -3.43416,-5.23021 -1.8445,-11.3333 1.67975,-6.44899 1.79296,-7.81453 0.58606,-7.06862 -0.47775,0.29527 -1.17525,2.45427 -1.55,4.79779 -1.53241,9.58316 -9.91102,11.84791 -14.071,3.80341 -1.88939,-3.65369 -2.0597,-5.96937 -0.31035,-4.22002 2.67439,2.67439 10.8,0.13028 10.8,-3.38145 0,-0.80743 -1.2375,-1.94053 -2.75,-2.51801 -2.6256,-1.00245 -2.66442,-1.11279 -0.85819,-2.43918 1.0405,-0.76408 2.36767,-1.54785 2.94927,-1.74172 1.41667,-0.47222 -2.50671,-7.13595 -4.39522,-7.46512 -2.52381,-0.4399 -4.20673,1.41879 -4.88147,5.39132 l -0.65464,3.85416 -3.61515,-3.56028 c -5.66759,-5.58155 -6.16316,-14.1497 -1.25195,-21.64515 2.31782,-3.53744 7.28989,-3.11136 11.14923,0.95543 4.08964,4.30947 5.87984,8.05607 7.42584,15.54108 0.70534,3.41491 1.67272,6.20892 2.14974,6.20892 0.47703,0 0.64559,-0.7875 0.37458,-1.75 -0.271,-0.9625 -0.80625,-3.325 -1.18945,-5.25 -0.38321,-1.925 -2.23412,-7.22887 -4.11315,-11.78637 -4.07464,-9.88286 -3.87149,-12.54118 1.60387,-20.9878 5.81479,-8.97023 6.23932,-9.11456 10.31852,-3.508 7.92107,10.88694 8.30957,13.99595 3.28858,26.31711 -3.18571,7.81752 -5.7629,18.32517 -4.12461,16.81677 0.38727,-0.35657 1.36949,-3.50048 2.18272,-6.98647 3.46919,-14.8711 12.11116,-22.05033 18.43723,-15.31654 1.93435,2.05902 2.45839,3.8362 2.72755,9.25 0.35745,7.18941 -1.52706,11.92878 -5.61265,14.11532 -1.71339,0.91698 -2.02223,0.63738 -2.57998,-2.33569 -1.14749,-6.11668 -6.02791,-7.28168 -8.42891,-2.01206 -1.58501,3.47872 -1.46086,4.20085 0.84824,4.93373 2.72574,0.86512 2.51297,2.35447 -0.5,3.5 -3.097,1.17748 -3.13089,2.05868 -0.18555,4.82569 2.49639,2.34523 5.6969,2.77379 8.70242,1.16528 1.74176,-0.93216 1.80532,-0.77935 0.83433,2.00602 -1.18553,3.40083 -5.23639,7.00301 -7.87527,7.00301 -3.09098,0 -5.85027,-3.34985 -7.41335,-9 -1.29014,-4.66352 -1.45018,-4.89165 -1.05229,-1.5 0.25809,2.2 0.7481,5.83016 1.08891,8.06702 0.51401,3.37365 0.21583,4.53649 -1.749,6.82074 l -2.36865,2.75373 -2.09176,-2.32075 z"
|
||||
id="path3078" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 659.28148,333.57168 -2.71511,-4.10281 1.96073,-6.53561 c 1.0784,-3.59458 1.71168,-6.78465 1.40729,-7.08904 -1.23368,-1.23369 -2.0963,-0.38763 -2.74936,2.69656 -0.97296,4.59495 -4.50274,10.62538 -6.61099,11.29451 -3.33266,1.05775 -6.30842,-1.75793 -8.23769,-7.79451 -0.70437,-2.20394 -2.21381,-2.25628 -3.03918,-0.10538 -0.35989,0.93786 0.1313,2.49906 1.14301,3.6329 1.71984,1.92746 1.70529,1.96686 -0.47589,1.28799 -1.64839,-0.51304 -2.25,-0.29698 -2.25,0.80809 0,0.8296 -0.52023,1.82989 -1.15607,2.22286 -1.98058,1.22407 -0.13307,-6.75177 2.07558,-8.96042 1.94397,-1.94397 2.06456,-1.94697 6.04814,-0.15063 4.05876,1.83025 4.06822,1.82952 6.54849,-0.50057 3.18476,-2.99196 3.17831,-4.98487 -0.0161,-4.98487 -2.02406,0 -2.5,-0.49376 -2.5,-2.59362 0,-1.75262 0.64852,-2.76321 2,-3.11663 1.1,-0.28766 2,-0.92053 2,-1.40638 0,-1.17035 -3.74739,-4.88337 -4.92857,-4.88337 -1.76735,0 -4.07143,3.15295 -4.07143,5.57143 0,3.16381 -3.32412,6.42857 -6.54545,6.42857 -3.53675,0 -7.45455,-4.18058 -7.45455,-7.95455 0,-1.675 0.45,-3.04545 1,-3.04545 0.55,0 1,0.9 1,2 0,1.1 0.64511,2 1.43358,2 0.80829,0 1.57159,1.16584 1.75,2.67288 0.17403,1.47009 0.93143,2.87509 1.68311,3.12223 1.05708,0.34755 1.24111,-0.42787 0.81234,-3.42288 -1.96645,-13.73581 -1.96606,-13.75782 0.2952,-16.62223 5.26969,-6.67531 14.82875,-0.82483 17.97283,11 0.67691,2.54582 1.71605,4.25 2.59148,4.25 2.2984,0 1.76875,-3.79437 -2.0988,-15.03562 -2.30849,-6.70977 -3.34019,-11.2249 -2.93434,-12.84192 0.34425,-1.37161 2.39637,-5.47395 4.56026,-9.11631 2.16389,-3.64237 3.95227,-7.27131 3.97419,-8.06432 0.0219,-0.79301 0.85697,0.13317 1.85568,2.05817 0.99871,1.925 3.23078,6.1332 4.96016,9.35155 1.72937,3.21835 3.14431,6.59797 3.14431,7.51026 0,0.9123 -1.57046,6.1541 -3.48992,11.64846 -3.95712,11.3271 -4.39582,14.80696 -1.80374,14.30777 1.08148,-0.20828 2.0093,-1.7868 2.53366,-4.31058 2.18326,-10.50809 12.30669,-16.96077 17.87435,-11.39311 1.84944,1.84944 2.02925,2.82043 1.43515,7.75 -1.09936,9.12197 -1.11119,12.0777 -0.0495,12.36502 0.55,0.14885 1.14322,-1.22148 1.31827,-3.04516 0.26383,-2.74874 0.56311,-3.11258 1.75,-2.12755 1.18041,0.97965 1.43173,0.72789 1.43173,-1.43422 0,-1.44234 0.45,-2.62244 1,-2.62244 0.55,0 1,1.37045 1,3.04545 0,3.77397 -3.9178,7.95455 -7.45455,7.95455 -3.07081,0 -6.54545,-3.21998 -6.54545,-6.06574 0,-2.90888 -1.8023,-5.93426 -3.53518,-5.93426 -1.5948,0 -5.46482,3.45825 -5.46482,4.88337 0,0.48585 0.9,1.11872 2,1.40638 1.35148,0.35342 2,1.36401 2,3.11663 0,2.09986 -0.47594,2.59362 -2.5,2.59362 -3.13748,0 -3.21365,1.98093 -0.18555,4.82569 2.77561,2.60754 2.94485,2.61963 7.35785,0.52552 3.30705,-1.56929 3.569,-1.55436 5.43314,0.30978 2.19116,2.19117 4.01798,10.15135 2.05063,8.93547 -0.63584,-0.39297 -1.15607,-1.39326 -1.15607,-2.22286 0,-1.10507 -0.60161,-1.32113 -2.25,-0.80809 -2.21842,0.69046 -2.22373,0.67087 -0.37872,-1.39536 1.02921,-1.15261 1.60583,-2.78742 1.28139,-3.6329 -0.94095,-2.45207 -2.36788,-1.79295 -3.56734,1.64782 -1.41385,4.05576 -3.90438,6.81493 -6.15142,6.81493 -2.60334,0 -6.49075,-5.18298 -7.80647,-10.40816 -0.63593,-2.52551 -1.59976,-4.59184 -2.14184,-4.59184 -1.4811,0 -1.18648,4.27497 0.58716,8.5199 1.82547,4.36896 1.39354,6.83848 -1.91028,10.92196 l -2.38017,2.94185 -2.71512,-4.10281 z"
|
||||
id="path3076" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 283.93108,325.73005 c -2.68937,-1.88372 -5.21679,-6.51724 -5.21679,-9.56395 l 0,-2.22398 2.31445,2.17432 c 2.88524,2.71054 5.29579,2.77128 6.91762,0.17431 1.66599,-2.66767 3.7371,-2.5981 3.03105,0.10182 -0.3023,1.156 -1.94767,2.95432 -3.65638,3.99626 -2.72662,1.66265 -2.84032,1.8949 -0.92932,1.89818 2.26372,0.004 6.32258,-4.25304 6.32258,-6.63112 0,-0.75083 0.48032,-1.36514 1.06739,-1.36514 0.58706,0 0.84777,0.7875 0.57934,1.75 -0.26842,0.9625 -0.80046,2.875 -1.18232,4.25 -0.79724,2.87073 -4.28719,7 -5.91622,7 -0.60675,0 -2.10588,-0.70232 -3.3314,-1.5607 z"
|
||||
id="path3074" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 310.49778,325.54075 c -2.51655,-2.88502 -3.78824,-5.95385 -3.70227,-8.93426 l 0.0812,-2.81574 1.16878,2.60441 c 1.81875,4.05276 3.72371,5.89916 6.04123,5.85555 1.9296,-0.0363 1.87808,-0.17549 -0.55378,-1.49595 -2.63744,-1.43209 -4.59103,-5.02498 -3.38697,-6.22904 0.33787,-0.33787 1.30447,0.37105 2.14801,1.57536 1.95648,2.79327 4.15239,2.77499 7.24774,-0.0603 l 2.45635,-2.25 -0.60717,4 c -0.40957,2.69822 -1.59994,4.89497 -3.65768,6.75 -3.54913,3.19951 -5.12669,3.41754 -7.23546,1 z"
|
||||
id="path3072" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 286.46038,311.04075 c -0.23132,-0.6875 -0.21633,-2.0375 0.0333,-3 0.40366,-1.5564 1.92794,-1.75 13.77823,-1.75 7.88299,0 13.579,0.41203 13.94791,1.00895 0.34296,0.55492 0.3392,1.90492 -0.008,3 -0.58938,1.85707 -1.53016,1.99105 -13.98118,1.99105 -9.78845,0 -13.46147,-0.33343 -13.76986,-1.25 z"
|
||||
id="path3070" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 308.71429,309.29075 c 1.02799,-0.66434 -1.42932,-0.97419 -7.80902,-0.98469 -5.95501,-0.01 -9.08634,0.34499 -8.69098,0.98469 0.79182,1.28119 14.5175,1.28119 16.5,0 z"
|
||||
id="path3068" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 277.42155,306.53307 c -5.29714,-5.89259 -1.52406,-19.24232 5.43852,-19.24232 2.34399,0 7.80642,4.7708 9.05826,7.91133 1.68762,4.23382 2.64296,9.08867 1.78847,9.08867 -0.43827,0 -1.25495,-1.31406 -1.81483,-2.92014 -1.15149,-3.30318 -4.56561,-7.07986 -6.40019,-7.07986 -0.67238,0 -0.28439,0.65708 0.86219,1.46017 2.26971,1.58977 5.01109,7.22239 4.00485,8.22863 -0.34357,0.34357 -1.73265,-0.57086 -3.08685,-2.03206 -1.3542,-1.46121 -2.84766,-2.65674 -3.3188,-2.65674 -2.06342,0 -4.15087,2.76337 -4.43291,5.8683 -0.30142,3.31817 -0.33265,3.33862 -2.09871,1.37402 z"
|
||||
id="path3066" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 321.24089,306.49177 c 0.69387,-2.49537 -1.75333,-7.20102 -3.74493,-7.20102 -0.64473,0 -2.42966,1.20469 -3.96652,2.6771 -1.53686,1.4724 -3.03657,2.43481 -3.3327,2.13869 -0.85366,-0.85367 1.24258,-5.54082 3.47762,-7.77586 1.12196,-1.12196 1.66837,-2.03993 1.21424,-2.03993 -1.19103,0 -4.67227,4.009 -6.51268,7.5 -1.57739,2.99209 -1.58166,2.99331 -1.62159,0.46189 -0.0557,-3.52907 3.92732,-10.95701 7.12291,-13.2836 8.0805,-5.88313 16.34253,9.26507 9.28073,17.01595 -2.3968,2.63067 -2.51644,2.6623 -1.91708,0.5068 z"
|
||||
id="path3064" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 297.23844,299.54075 c -0.38661,-2.6125 -2.08064,-8.24849 -3.76451,-12.52443 -2.72891,-6.92968 -2.93882,-8.18416 -1.93182,-11.54522 1.10355,-3.68333 7.49871,-12.18035 9.16736,-12.18035 0.46164,0 2.71365,2.80681 5.00448,6.23735 4.79188,7.17589 4.8449,8.7817 0.66909,20.26265 -1.40031,3.85 -2.81903,8.6875 -3.1527,10.75 -1.23207,7.6157 -2.46669,3.37941 -2.76865,-9.5 l -0.31066,-13.25 -0.21837,13.25 c -0.22118,13.42066 -1.41067,17.17339 -2.69422,8.5 z"
|
||||
id="path3062" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 660.89088,245.49153 c -0.64712,-2.91457 -1.17659,-8.65207 -1.17659,-12.75 0,-6.44661 -0.23585,-7.44466 -1.75,-7.40539 -1.10111,0.0286 -2.67699,1.97524 -4.25,5.25 -1.40668,2.9285 -3.57867,5.72947 -4.96651,6.40477 -1.35658,0.66008 -2.57866,1.08801 -2.71572,0.95094 -0.13707,-0.13707 0.86036,-2.4409 2.21651,-5.11963 2.98861,-5.90326 3.08929,-7.53147 0.46572,-7.53147 -1.46667,0 -2,-0.66667 -2,-2.5 0,-2 0.5,-2.5 2.5,-2.5 2.7383,0 2.96809,-0.63862 1.56126,-4.33887 -2.25025,-5.91861 -9.01269,-8.61724 -12.30669,-4.91113 -0.85547,0.9625 -2.25225,3.4375 -3.10396,5.5 -1.90425,4.61135 -3.11594,4.79729 -3.25821,0.5 -0.0592,-1.7875 -0.28418,-6.05053 -0.5,-9.47339 -0.36092,-5.72411 -0.16995,-6.44615 2.38033,-9 3.77938,-3.78467 10.33443,-3.91165 14.27905,-0.27661 3.51752,3.24146 7.25737,11.23904 8.06649,17.25 0.44326,3.29295 1.10369,4.75 2.15302,4.75 2.2209,0 0.96171,-10.03742 -2.41041,-19.21418 -1.4725,-4.0072 -2.87405,-9.41628 -3.11454,-12.02019 -0.38221,-4.1383 0.0784,-5.6287 3.6582,-11.83784 2.2525,-3.90691 4.09546,-7.48739 4.09546,-7.95662 0,-0.46922 0.41191,-1.10771 0.91536,-1.41886 0.50345,-0.31115 2.97845,3.21906 5.5,7.84491 5.52568,10.137 5.72681,13.09034 1.65189,24.25591 -3.58104,9.81228 -5.06849,20.34687 -2.87292,20.34687 0.9871,0 1.81538,-1.95042 2.58444,-6.08582 2.02031,-10.86368 8.58924,-18.90105 15.45545,-18.91044 1.60179,-0.002 4.06476,1.18509 5.94675,2.86665 2.58885,2.31313 3.20651,3.62358 3.18153,6.75 -0.0573,7.17065 -0.85708,15.37865 -1.49856,15.37913 -0.34983,2.7e-4 -1.41975,-1.68702 -2.3776,-3.74952 -2.49009,-5.36181 -4.42818,-7.25451 -7.39133,-7.2182 -3.48162,0.0427 -5.76615,1.93688 -7.5844,6.28857 -1.95185,4.67143 -1.95011,4.67963 0.98939,4.67963 2,0 2.5,0.5 2.5,2.5 0,1.83333 -0.53333,2.5 -2,2.5 -2.62357,0 -2.52289,1.62821 0.46572,7.53147 1.35615,2.67873 2.35358,4.98256 2.21651,5.11963 -0.13706,0.13707 -1.35914,-0.29086 -2.71572,-0.95094 -1.38784,-0.6753 -3.55983,-3.47627 -4.96651,-6.40477 -1.57301,-3.27476 -3.14889,-5.22143 -4.25,-5.25 -1.53112,-0.0397 -1.75961,1.04901 -1.82685,8.70461 -0.0423,4.8125 -0.6378,10.55 -1.32341,12.75 l -1.24655,4 -1.1766,-5.29922 z"
|
||||
id="path3060" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 587.37421,244.97342 c -3.50524,-5.98123 -4.0391,-8.83882 -2.3896,-12.79064 2.38252,-5.70798 3.04885,-10.89203 1.39999,-10.89203 -0.78481,0 -1.69458,1.37136 -2.03329,3.0649 -1.30748,6.53741 -8.50028,10.6842 -13.70276,7.89992 -2.88262,-1.54274 -2.3399,-2.96482 1.13148,-2.96482 4.13496,0 6.61075,-1.47372 8.44959,-5.02964 1.50751,-2.91521 1.48914,-2.97036 -0.98965,-2.97036 -1.85901,0 -2.52568,-0.52791 -2.52568,-2 0,-1.46667 0.66667,-2 2.5,-2 2.92346,0 2.93123,-0.0322 1.07878,-4.4657 -1.59213,-3.81049 -6.6311,-6.96986 -9.609,-6.02471 -1.06164,0.33695 -2.78816,2.55207 -3.8367,4.92248 -3.23633,7.31624 -4.13649,6.63078 -4.10128,-3.12305 0.0353,-9.7628 0.86687,-11.68053 5.81296,-13.40475 7.15984,-2.49593 14.8435,5.79599 15.9394,17.2012 0.42972,4.47226 1.40636,6.0654 2.54071,4.14453 0.95429,-1.61597 -1.4263,-14.10251 -3.92017,-20.56184 -3.14378,-8.14267 -2.93829,-9.69141 2.66389,-20.0775 l 4.19688,-7.78073 4.58035,8.33504 c 5.16474,9.39846 5.54434,12.63221 2.34436,19.97114 -2.31077,5.29961 -4.94333,19.44408 -3.82673,20.56067 1.08528,1.08528 2.60349,-1.76336 2.62124,-4.91827 0.0195,-3.47547 4.14874,-12.77869 6.62093,-14.91722 4.56188,-3.94618 13.36232,-2.68838 14.89108,2.1283 0.86509,2.72566 0.19812,17.92285 -0.76099,17.33954 -0.42036,-0.25566 -1.65933,-2.21925 -2.75327,-4.36354 -2.647,-5.18856 -5.11212,-6.46701 -8.79624,-4.56188 -3.55667,1.83923 -4.84335,3.38208 -5.71421,6.85188 -0.61922,2.46717 -0.4253,2.74441 1.9196,2.74441 1.94174,0 2.60841,0.51117 2.60841,2 0,1.44592 -0.66667,2 -2.40638,2 -1.92361,0 -2.30019,0.40608 -1.87706,2.02412 0.8168,3.12347 5.14767,5.97588 9.07329,5.97588 3.45678,0 3.48756,0.036 1.71015,2 -3.41395,3.77237 -10.38623,1.86686 -12.95181,-3.53969 -0.8515,-1.79441 -1.54819,-3.98206 -1.54819,-4.86144 0,-0.87938 -0.675,-1.59887 -1.5,-1.59887 -1.97452,0 -1.89374,1.55803 0.47499,9.16091 l 1.975,6.33909 -2.92246,6.25 c -1.60735,3.4375 -3.12833,6.25 -3.37997,6.25 -0.25163,0 -1.59607,-1.9428 -2.98764,-4.31733 z"
|
||||
id="path3058" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 447.11158,243.09214 c -1.27055,-2.45698 -1.52185,-4.77559 -1.08386,-10 l 0.57021,-6.80139 -5.31938,0 c -6.03869,0 -8.75405,-1.86146 -6.56426,-4.5 0.68469,-0.825 2.08979,-1.5 3.12244,-1.5 4.36462,0 1.09533,-8.22656 -3.75285,-9.44338 -4.45886,-1.1191 -8.2061,1.12249 -9.42143,5.63589 -0.88414,3.28345 -1.30994,3.75213 -2.50661,2.75898 -1.99084,-1.65225 -1.86936,-9.89569 0.18914,-12.83462 1.80955,-2.58349 7.06228,-5.11687 10.60935,-5.11687 3.39163,0 9.47464,5.44546 10.34295,9.25893 0.72395,3.17945 1.16808,6.00707 1.33368,8.49107 0.0458,0.6875 0.5986,1.25 1.22837,1.25 1.89732,0 0.27754,-12.72829 -2.57989,-20.27283 -4.09139,-10.80259 -3.27977,-14.98931 4.87898,-25.1683 1.54014,-1.92151 1.5716,-1.92151 3.11174,0 8.18624,10.21329 8.89626,13.96048 4.83495,25.5168 -2.47518,7.04303 -3.98984,19.92433 -2.34282,19.92433 0.40606,0 1.22578,-2.8125 1.82158,-6.25 1.88526,-10.87705 9.81082,-15.68124 17.8166,-10.79977 1.7524,1.06851 3.71701,2.93462 4.3658,4.1469 1.65049,3.08397 1.37397,9.90549 -0.47654,11.756 -1.39424,1.39424 -1.60369,1.25671 -2.13783,-1.40373 -0.88883,-4.42714 -2.83664,-6.47762 -6.75773,-7.11392 -2.90377,-0.47122 -3.99125,-0.11501 -6.10641,2.00014 -3.09468,3.09468 -3.5096,7.66438 -0.69591,7.66438 1.03265,0 2.43775,0.675 3.12244,1.5 2.18979,2.63854 -0.52557,4.5 -6.56426,4.5 l -5.31938,0 0.57021,6.80139 c 0.43799,5.22441 0.18669,7.54302 -1.08386,10 -0.90974,1.75923 -2.08096,3.19861 -2.60271,3.19861 -0.52175,0 -1.69297,-1.43938 -2.60271,-3.19861 z"
|
||||
id="path3056" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 296.66953,243.04074 c -2.1471,-2.27591 -2.23296,-5.26148 -0.33663,-11.70685 0.67642,-2.29907 0.53527,-2.2532 -2.19789,0.71431 -4.01372,4.35787 -7.43636,5.016 -10.74234,2.06563 -1.43169,-1.2777 -2.87956,-3.50381 -3.21747,-4.94692 -0.58538,-2.49993 -0.43007,-2.61899 3.2891,-2.52147 2.30427,0.0604 5.09275,-0.67688 6.80632,-1.79965 l 2.90282,-1.902 -2.64356,-0.88119 c -3.72316,-1.24105 -4.16313,-3.35333 -1.18621,-5.69497 l 2.53837,-1.99668 -2.49073,-0.62514 c -4.28789,-1.07619 -10.67702,3.28211 -10.67702,7.28325 0,3.19394 -1.88602,2.51367 -4.75,-1.7133 -7.30142,-10.7762 5.50982,-27.48497 15.63571,-20.39252 1.28189,0.89788 3.21412,3.48538 4.29384,5.75 l 1.96312,4.1175 -0.59529,-3.5 c -0.32741,-1.925 -1.93451,-6.36302 -3.57134,-9.86227 -1.63682,-3.49925 -2.97604,-7.0091 -2.97604,-7.79966 0,-3.58276 8.7474,-15.33807 11.41341,-15.33807 1.29289,0 7.31919,6.04766 9.93729,9.97251 2.34439,3.51453 2.05831,6.65959 -1.23996,13.63144 -1.58822,3.35718 -3.18501,7.63218 -3.54841,9.5 -0.65321,3.35736 -0.63862,3.34914 1.28025,-0.72145 2.37933,-5.04736 5.53467,-7.3825 9.97556,-7.3825 6.84846,0 12.18186,6.73593 12.18186,15.38535 0,3.63348 -0.59471,5.24869 -2.87023,7.79544 l -2.87022,3.21234 -0.74471,-2.44657 c -1.62858,-5.35029 -7.18441,-8.82099 -11.78372,-7.36122 -2.01381,0.63916 -1.99012,0.72306 0.58505,2.07233 3.36324,1.76219 3.43908,4.04109 0.18383,5.52428 -1.375,0.6265 -2.5,1.53981 -2.5,2.02959 0,1.49765 7.13596,3.97115 9.64202,3.34217 2.81555,-0.70666 3.11305,1.08547 0.89289,5.37878 -2.65972,5.14334 -9.82622,4.54511 -14.09725,-1.17678 -1.45471,-1.94887 -1.58397,-1.98366 -0.95023,-0.25571 0.40344,1.1 0.9614,3.8599 1.23992,6.13312 0.40501,3.30554 0.0825,4.55699 -1.61047,6.25 -2.7073,2.7073 -4.51364,2.67372 -7.16164,-0.13312 z"
|
||||
id="path3054" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 301.644,236.48172 c -0.0387,-2.58004 -0.41412,-5.56992 -0.83436,-6.64417 -0.64702,-1.65396 -0.86605,-1.44331 -1.42971,1.375 -0.84431,4.22156 -0.85774,9.55275 -0.0262,10.38434 1.41853,1.41853 2.35673,-0.67692 2.29023,-5.11517 z"
|
||||
id="path3052" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 291.88555,230.63575 c 2.71439,-2.45649 2.21497,-3.42788 -0.92126,-1.79187 -1.5125,0.789 -3.56406,1.43731 -4.55902,1.4407 -0.99496,0.003 -1.5309,0.45616 -1.19098,1.00616 0.95494,1.54513 4.63993,1.18334 6.67126,-0.65499 z"
|
||||
id="path3050" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 315.21429,231.29074 c 0.33992,-0.55 -0.19602,-1.00277 -1.19098,-1.00616 -0.99496,-0.003 -3.04652,-0.6517 -4.55902,-1.4407 -3.28919,-1.7158 -3.67942,-0.31754 -0.52749,1.89016 2.53483,1.77546 5.36892,2.0268 6.27749,0.5567 z"
|
||||
id="path3048" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 309.14953,219.39552 c 0.87191,-1.41078 -2.07427,-2.10478 -8.93524,-2.10478 -7.30433,0 -10.42835,0.79614 -8.33385,2.12385 1.78571,1.13196 16.56781,1.11564 17.26909,-0.0191 z"
|
||||
id="path3046" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 323.68063,208.68874 c -1.47123,-4.45785 -5.8444,-6.68507 -10.16728,-5.17811 -1.5627,0.54476 -3.26769,1.78724 -3.78887,2.76107 -0.83794,1.5657 -0.34438,1.82856 4.26494,2.27145 4.33019,0.41608 5.63675,1.03044 7.7187,3.62939 2.95028,3.68293 3.82682,2.13481 1.97251,-3.4838 z"
|
||||
id="path3044" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 278.36686,212.75375 c 0.86593,-2.2566 5.72713,-4.46301 9.83295,-4.46301 3.20864,0 3.47843,-0.19885 2.57077,-1.89482 -1.27636,-2.3849 -5.93799,-4.06511 -8.56147,-3.08585 -2.90819,1.08555 -5.17534,4.02477 -5.96298,7.73067 -0.71566,3.36721 0.96501,4.72477 2.12073,1.71301 z"
|
||||
id="path3042" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 304.55138,194.37878 c 2.88294,-5.53103 2.72847,-7.9938 -0.76054,-12.12581 -3.43147,-4.06387 -5.33375,-3.56176 -8.51843,2.24845 l -1.94187,3.54281 2.8371,6.32191 c 1.56041,3.47706 3.07924,8.37002 3.37518,10.87326 l 0.53808,4.55134 1.15379,-5.63117 c 0.63458,-3.09714 2.1271,-7.4985 3.31669,-9.78079 z"
|
||||
id="path3040" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 516.21037,241.28641 c -1.63435,-1.80594 -1.72217,-2.95171 -0.88718,-11.57564 1.08111,-11.16596 -0.24334,-19.79171 -4.25429,-27.70694 -3.59948,-7.10323 -3.37591,-12.42949 0.81206,-19.34583 1.83333,-3.02771 4.11153,-6.21029 5.06267,-7.07239 1.58356,-1.43532 1.90212,-1.36629 3.77876,0.81884 4.00269,4.66066 7.97327,12.43246 7.98252,15.62458 0.005,1.78106 -1.52402,6.95606 -3.39817,11.5 -4.18973,10.15812 -5.17435,17.38316 -3.62264,26.5827 1.01541,6.02003 0.95696,7.41994 -0.42104,10.08471 -1.87714,3.62998 -2.61079,3.78824 -5.05269,1.08997 z"
|
||||
id="path3036" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 502.80828,234.54074 c -1.61566,-1.5125 -3.22671,-3.75819 -3.58012,-4.99042 -0.6387,-2.22694 -0.62429,-2.22995 2.39604,-0.5 2.99539,1.71567 3.07621,1.70285 5.68372,-0.90168 3.14168,-3.1381 3.53209,-9.21019 0.85489,-13.29612 -2.86894,-4.37856 -7.44852,-2.7565 -7.44852,2.63822 0,3.42443 -0.93715,3.51436 -4.28548,0.41123 -6.85923,-6.35692 -4.52596,-21.61123 3.30561,-21.61123 5.6523,0 11.32516,7.63857 13.95118,18.78541 2.00468,8.50937 -0.37241,18.75334 -4.91592,21.18495 -2.61735,1.40076 -2.63189,1.39656 -5.9614,-1.72036 z"
|
||||
id="path3030" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 527.54534,236.24783 c -3.20749,-1.85604 -5.16686,-9.33389 -4.55735,-17.39294 0.63544,-8.40201 3.02837,-14.58643 7.47319,-19.31415 5.70867,-6.072 12.48368,-3.56373 13.78333,5.10293 0.84762,5.65235 -0.82705,10.9488 -4.33412,13.70746 l -2.65913,2.09167 -0.76449,-2.95027 c -1.61718,-6.24093 -5.63987,-6.64475 -8.40613,-0.84385 -2.18715,4.5865 -1.16258,10.07424 2.30507,12.34634 2.36484,1.5495 2.80537,1.55863 5.32881,0.11037 2.54876,-1.46279 2.71812,-1.45364 2.30543,0.12451 -0.67517,2.58183 -4.55351,6.81944 -6.80566,7.43608 -1.1,0.30118 -2.75103,0.11301 -3.66895,-0.41815 z"
|
||||
id="path3028" />
|
||||
<g
|
||||
id="g3217">
|
||||
<path
|
||||
id="path3038"
|
||||
d="m 373.27099,241.06823 c -1.84628,-2.63593 -1.95033,-5.32861 -0.43799,-11.33467 1.61864,-6.4282 4.3072,-6.11508 6.34255,0.73868 1.96801,6.62701 1.94689,7.0299 -0.53384,10.18364 -2.52614,3.21146 -3.36503,3.27587 -5.37072,0.41235 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
id="path3034"
|
||||
d="m 361.46427,236.21063 c -1.52802,-0.88999 -4.74998,-5.87251 -4.74998,-7.34548 0,-0.2887 1.18444,-0.0746 2.63208,0.47581 3.15303,1.19878 5.48207,0.58612 7.89102,-2.07575 0.98278,-1.08596 2.5693,-1.97447 3.52559,-1.97447 1.52353,0 1.62459,0.52599 0.81659,4.25 -1.39084,6.41021 -5.69191,9.24628 -10.1153,6.66989 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
id="path3032"
|
||||
d="m 383.50366,236.23263 c -1.5524,-0.905 -3.76993,-6.58507 -3.78379,-9.69193 -0.009,-2.05468 2.73324,-1.42027 5.40351,1.25 2.70807,2.70807 4.64221,3.0781 7.65665,1.46482 2.8803,-1.54149 2.52031,1.18525 -0.65463,4.95845 -2.64398,3.14219 -5.53385,3.81881 -8.62174,2.01866 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
id="path3026"
|
||||
d="m 368.78843,223.41349 c -3.24581,-0.90704 -3.69702,-2.72315 -0.86503,-3.48176 3.75717,-1.00645 13.45518,-0.72293 16.47579,0.48166 l 2.8151,1.12264 -3,1.33225 c -3.15862,1.4027 -11.32454,1.69131 -15.42586,0.54521 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
id="path3024"
|
||||
d="m 355.01357,218.04075 c -3.23464,-3.55134 -4.29928,-6.2843 -4.29928,-11.03638 0,-5.50199 3.43432,-11.08028 7.08696,-11.51119 5.3124,-0.62673 11.97142,8.33556 13.43248,18.07861 0.62854,4.19146 0.49934,4.71825 -1.1559,4.71264 -1.02495,-0.003 -2.63011,-1.35348 -3.56703,-3 -2.8379,-4.98728 -7.79651,-3.11706 -7.79651,2.94058 0,2.673 -1.15044,2.61572 -3.70072,-0.18426 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
id="path3022"
|
||||
d="m 392.71429,217.49075 c 0,-5.59592 -4.97984,-7.12598 -7.16029,-2.2 -0.90934,2.05433 -2.03904,3 -3.58382,3 -2.77389,0 -2.79911,-1.0306 -0.22884,-9.35214 4.66972,-15.11881 15.54237,-18.38805 18.95875,-5.70061 1.40323,5.2112 -0.15236,11.37584 -3.70032,14.66398 -3.34833,3.10313 -4.28548,3.0132 -4.28548,-0.41123 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
id="path3020"
|
||||
d="m 373.29635,217.11089 c -0.22494,-0.72608 -0.66545,-2.8015 -0.97891,-4.61205 -0.31345,-1.81056 -1.92739,-6.68206 -3.58653,-10.82556 -1.65914,-4.14351 -3.0124,-8.73715 -3.00724,-10.20809 0.009,-2.61552 3.96102,-10.21858 7.87383,-15.1487 1.84172,-2.32055 2.07717,-2.37142 3.79025,-0.81883 1.0046,0.91048 3.31662,4.11628 5.13784,7.12399 4.15721,6.86561 4.33517,11.32146 0.74626,18.6863 -1.46947,3.01554 -3.24206,7.9578 -3.93908,10.9828 -1.01385,4.40006 -1.70329,5.56402 -3.44736,5.82014 -1.19903,0.17607 -2.36411,-0.27393 -2.58906,-1 z"
|
||||
style="fill:#000000" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 472.42807,161.65144 c -4.29218,-6.5176 -4.61264,-9.69845 -1.82774,-18.14224 1.03732,-3.14515 2.19581,-7.8954 2.57442,-10.55611 0.61402,-4.31513 0.49415,-4.80025 -1.10984,-4.49135 -1.24066,0.23893 -2.02181,1.65606 -2.51934,4.57045 -1.67587,9.81689 -6.0246,14.09861 -11.39833,11.22267 -2.53132,-1.35472 -6.43295,-8.29002 -6.43295,-11.43482 0,-1.66653 0.16435,-1.69591 1.75,-0.31278 4.02038,3.50689 6.07538,3.95811 8.22708,1.80641 2.91731,-2.91731 2.67131,-6.02292 -0.47708,-6.02292 -2.11111,0 -2.5,-0.46667 -2.5,-3 0,-2.53333 0.38889,-3 2.5,-3 1.58824,0 2.5,-0.56364 2.5,-1.54546 0,-1.9654 -4.43946,-6.45454 -6.38312,-6.45454 -2.70269,0 -4.81986,3.13564 -4.42144,6.5484 0.43568,3.73192 -1.15437,3.68942 -3.63545,-0.0972 -3.68975,-5.63128 -0.79027,-17.02227 5.00499,-19.66277 5.77829,-2.632771 13.70308,6.33567 15.15346,17.14906 0.42715,3.18459 0.96892,4.0625 2.50707,4.0625 1.78657,0 1.90143,-0.46982 1.28348,-5.25 -0.37327,-2.8875 -2.07006,-9.075 -3.77065,-13.75 -1.70058,-4.675001 -3.1234,-10.565641 -3.16182,-13.090311 -0.071,-4.66288 1.47523,-7.64415 7.992,-15.40969 l 2.51758,-3 3.50149,4 c 7.79243,8.90183 9.01238,14.60356 5.05497,23.62557 -4.248,9.684491 -6.245,22.130631 -3.63204,22.636441 1.09797,0.21254 1.99112,-1.54002 3.27024,-6.41696 1.95437,-7.45149 5.57568,-12.95977 9.50138,-14.45232 9.53391,-3.624791 16.32607,14.26944 8.20571,21.61827 -1.88379,1.70481 -1.93307,1.65194 -1.79843,-1.92945 0.26597,-7.07507 -6.429,-8.88651 -9.67123,-2.61672 -1.98213,3.83302 -1.97732,3.8495 1.23181,4.21875 2.18229,0.2511 2.75,0.83252 2.75,2.81642 0,1.9839 -0.56771,2.56532 -2.75,2.81642 -3.06486,0.35265 -3.26944,0.94943 -1.58948,4.63653 1.6558,3.63408 4.86591,3.741 8.58948,0.28608 l 2.25,-2.08766 0,2.72398 c 0,3.49599 -2.37156,8.07106 -5.21679,10.06395 -5.45161,3.81845 -9.94702,0.22953 -11.9679,-9.55459 -0.73082,-3.53828 -1.73379,-5.88471 -2.51539,-5.88471 -2.12209,0 -1.54527,7.11585 1.28914,15.90337 2.2004,6.82187 2.42096,8.53625 1.46923,11.42 -1.07823,3.26708 -6.882,11.67663 -8.05851,11.67663 -0.31472,0 -2.24342,-2.53769 -4.286,-5.63931 z"
|
||||
id="path3018" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 297.65022,157.87605 c -2.2006,-4.14817 -2.25612,-4.72375 -1.07435,-11.13745 1.01644,-5.51645 1.0058,-6.91568 -0.0577,-7.59022 -2.09414,-1.32824 -2.26904,-1.11667 -3.55604,4.30126 -2.44208,10.28061 -7.5788,11.78157 -14.12212,4.12653 -2.21645,-2.59301 -3.83105,-4.91343 -3.588,-5.15647 0.24304,-0.24304 2.2683,0.3817 4.50057,1.38832 3.96071,1.78603 4.10326,1.78377 5.90569,-0.0935 3.20534,-3.3385 3.41052,-5.94119 0.57039,-7.23524 -3.00177,-1.3677 -3.32056,-4.66808 -0.61415,-6.35826 2.14593,-1.34016 1.79515,-3.22663 -1.22354,-6.58024 -2.31284,-2.56944 -5.86253,-2.93592 -7.64413,-0.78922 -0.66679,0.80343 -1.45799,3.39093 -1.75823,5.75 -0.68255,5.36303 -1.70964,7.40829 -4.02425,8.01357 -1.53525,0.40148 -1.75335,-0.0391 -1.42245,-2.87349 0.21495,-1.84121 -0.33333,-5.15749 -1.2184,-7.3695 -0.88507,-2.21201 -1.60922,-5.85773 -1.60922,-8.1016 0,-3.30639 0.64451,-4.72427 3.4,-7.47976 7.46217,-7.46217 17.46811,-2.56624 21.28275,10.41371 1.37379,4.67458 2.26574,6.18386 3.65515,6.1849 1.60567,0.001 1.7493,-0.53562 1.13671,-4.24861 -0.38566,-2.3375 -1.82368,-7.82895 -3.19561,-12.20322 -3.22539,-10.28389 -2.79188,-14.437901 2.80234,-26.852911 l 4.41866,-9.80612 4.41578,9.30612 c 5.69234,11.99644 6.23101,17.404191 2.82479,28.358611 -3.54723,11.40788 -4.05189,15.44973 -1.9277,15.43897 1.18837,-0.006 2.25078,-1.81601 3.59376,-6.12254 1.23521,-3.96097 3.20554,-7.47943 5.59516,-9.99145 3.20598,-3.37018 4.26481,-3.87455 8.09337,-3.85522 9.43959,0.0477 13.20279,7.87737 9.29638,19.34206 -0.88466,2.59632 -1.39706,5.82649 -1.13868,7.17814 0.30478,1.59432 0.0115,2.45756 -0.83483,2.45756 -2.00513,0 -4.41803,-4.09611 -4.41803,-7.5 0,-6.75824 -5.58111,-9.7037 -9.82569,-5.18555 -2.75235,2.92975 -2.73687,4.45582 0.0757,7.45971 l 2.25,2.40307 -2.88476,2.3064 c -2.31157,1.84813 -2.75629,2.81827 -2.23819,4.88252 0.99254,3.95458 3.93874,5.05236 8.17033,3.04434 1.93827,-0.91977 3.71148,-1.48496 3.94047,-1.25598 0.22898,0.22899 -1.39712,2.5379 -3.61357,5.13091 -3.10664,3.63447 -4.70274,4.71458 -6.96678,4.71458 -3.45447,0 -6.39793,-4.02441 -7.43558,-10.1662 -0.66026,-3.90802 -1.12144,-4.36766 -3.07883,-3.06849 -0.79603,0.52835 -0.82076,2.62419 -0.088,7.46232 0.88025,5.81233 0.76913,7.28145 -0.81675,10.79831 -1.00959,2.23887 -2.14977,4.26484 -2.53373,4.50214 -0.38397,0.2373 -1.74235,-1.53695 -3.01864,-3.94278 z"
|
||||
id="path3016" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 388.25173,159.32983 c -3.62395,-3.78259 -4.48377,-10.81352 -2.15736,-17.64115 2.0869,-6.12471 2.05789,-6.39793 -0.67919,-6.39793 -1.71354,0 -2.6169,0.87883 -3.54684,3.45051 -3.6298,10.03804 -16.37653,11.47636 -21.23606,2.39624 -0.96238,-1.79822 -0.86828,-1.89051 0.94057,-0.92244 2.83535,1.51743 7.739,1.33516 11.12023,-0.41334 3.53714,-1.82913 4.94561,-5.41415 2.6351,-6.70717 -2.18858,-1.22479 -2.02984,-2.53701 0.4002,-3.30827 1.9317,-0.6131 1.94539,-0.75554 0.33473,-3.48218 -3.31849,-5.61774 -12.03695,-6.88526 -16.82667,-2.4463 l -2.76989,2.56705 0.67169,-3.81705 c 1.89727,-10.7818 9.05502,-17.6342 16.01919,-15.33581 5.90372,1.9484 9.35388,7.35593 11.01797,17.26876 0.49333,2.93874 1.08243,3.75 2.72309,3.75 1.9431,0 2.05572,-0.41328 1.56687,-5.75 -0.28969,-3.1625 -2.15219,-9.90281 -4.13889,-14.97847 -1.9867,-5.07566 -3.61218,-10.741281 -3.61218,-12.590281 0,-3.60626 4.47114,-13.34338 8.30001,-18.07553 l 2.34181,-2.89428 4.16592,6.23851 c 7.22727,10.82292 7.54674,15.31323 2.01367,28.303221 -1.86711,4.38342 -3.28601,9.71637 -3.59101,13.49683 -0.46452,5.7579 -0.34621,6.25 1.50258,6.25 1.64486,0 2.21144,-1.03708 3.14138,-5.75 2.80814,-14.23161 12.59932,-20.02942 20.64909,-12.22727 3.27212,3.17146 6.52993,10.70781 6.44475,14.90877 -0.0287,1.41518 -0.15088,1.41341 -1.25,-0.0182 -4.42019,-5.75714 -15.59203,-4.87518 -18.47796,1.45873 -0.99615,2.18631 -0.88894,2.60465 0.80531,3.14239 2.37519,0.75385 2.51189,2.0742 0.34056,3.28933 -2.31051,1.29303 -0.90204,4.87805 2.6351,6.70717 3.39603,1.75616 7.31613,1.91405 10.13018,0.40802 3.46945,-1.8568 3.26681,-0.13718 -0.41806,3.54768 -6.26578,6.26579 -14.24686,4.32754 -18.78155,-4.56119 -1.3032,-2.55448 -2.67724,-3.90547 -3.9721,-3.90547 -2.37288,0 -2.39595,0.30996 -0.4905,6.59107 2.58616,8.52504 1.59138,14.31109 -3.20706,18.65362 -1.84221,1.66717 -2.0407,1.61673 -4.74468,-1.20561 z"
|
||||
id="path3014" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 648.71928,156.18512 c -1.91535,-3.03634 -2.07749,-4.31729 -1.53716,-12.14437 0.51527,-7.46427 0.37834,-8.75 -0.9319,-8.75 -0.91246,0 -1.53593,0.88665 -1.53593,2.18428 0,3.47554 -3.79112,10.36597 -6.50145,11.8165 -3.68767,1.97358 -6.84916,0.0955 -9.11557,-5.415 -1.03564,-2.51806 -2.2346,-4.57997 -2.66436,-4.58203 -1.52702,-0.007 -2.01484,3.29227 -0.77926,5.27076 1.12682,1.80432 1.0408,1.95356 -0.84218,1.46115 -1.57067,-0.41074 -2.09718,-0.0846 -2.09718,1.29894 0,1.01605 -0.45,2.12548 -1,2.4654 -0.56789,0.35098 -1,-0.49597 -1,-1.96004 0,-2.24937 -0.31818,-2.49821 -2.49556,-1.95172 -2.16848,0.54425 -1.90025,0.0225 2.04656,-3.98095 2.49817,-2.53401 5.01871,-4.60729 5.6012,-4.60729 0.5825,0 2.39607,1.125 4.03017,2.5 3.6798,3.09634 7.21239,3.20219 9.26093,0.27749 2.28645,-3.26437 1.90822,-5.49988 -1.18107,-6.98054 -3.69591,-1.7714 -4.07412,-4.46991 -0.83343,-5.94646 1.41416,-0.64434 2.5712,-1.67416 2.5712,-2.2885 0,-2.10103 -3.11126,-5.56199 -5,-5.56199 -2.39402,0 -5,3.66606 -5,7.03395 0,3.60784 -3.41892,6.96605 -7.09201,6.96605 -1.65775,0 -4.66968,-1.125 -6.69318,-2.5 -2.02349,-1.375 -4.50118,-2.5 -5.50596,-2.5 -1.00479,0 -1.54877,-0.45 -1.20885,-1 0.33992,-0.55 1.49148,-1 2.55902,-1 1.3912,0 1.94098,-0.69141 1.94098,-2.44098 0,-3.18614 1.76205,-4.25667 2.17899,-1.32385 0.20366,1.43258 0.96147,2.21436 2.06227,2.12748 1.35677,-0.10708 1.60753,0.39164 1.13785,2.26298 -0.63105,2.5143 1.20878,5.7471 2.7342,4.80434 1.2188,-0.75326 1.11126,-4.94838 -0.2427,-9.46749 -2.40513,-8.02762 2.42516,-16.96248 9.17011,-16.96248 4.96054,0 10.36163,5.97036 11.9921,13.25604 1.03201,4.61153 1.67357,5.74396 3.25412,5.74396 1.74425,0 1.89405,-0.46669 1.31404,-4.09387 -0.36005,-2.25164 -1.76756,-6.73808 -3.12781,-9.96987 -1.39598,-3.31672 -2.47317,-7.83914 -2.47317,-10.383301 0,-4.57306 2.92597,-13.5672 7.03202,-21.61572 l 2.25947,-4.42893 3.22805,7.09844 c 6.60969,14.53458 7.1973,20.115231 3.14822,29.899181 -1.36706,3.30326 -2.80163,7.69076 -3.18795,9.75 -0.62963,3.35623 -0.48566,3.74407 1.38985,3.74407 1.47313,0 2.26635,-0.81374 2.68064,-2.75 2.19968,-10.28051 6.9235,-16.27686 12.77643,-16.2182 7.88732,0.079 11.47247,8.21249 8.50711,19.29965 -1.43828,5.37755 -0.59135,8.54212 1.76315,6.58806 0.96728,-0.80278 1.41816,-2.36291 1.17052,-4.05022 -0.35092,-2.39093 -0.16865,-2.61916 1.41484,-1.7717 1.5294,0.81851 1.81765,0.58009 1.81765,-1.50339 0,-2.86574 1.94122,-4.6097 2.11848,-1.90322 0.0652,0.99496 0.0454,2.37152 -0.0438,3.05902 -0.0893,0.6875 0.73085,1.25 1.8225,1.25 1.09165,0 2.26293,0.45 2.60285,1 0.33992,0.55 -0.20406,1 -1.20885,1 -1.00478,0 -3.48247,1.125 -5.50596,2.5 -4.30569,2.92579 -8.81868,3.22546 -11.07231,0.73523 -0.87841,-0.97063 -2.04003,-3.7361 -2.58138,-6.14549 -1.59527,-7.1 -5.90347,-8.25381 -8.9818,-2.40548 -1.51302,2.8745 -1.48479,2.99485 0.84525,3.60417 3.10581,0.81218 3.69124,3.73751 1.15843,5.78845 -1.19908,0.97096 -2.68383,1.93327 -3.29946,2.13848 -1.37522,0.45841 -0.31944,4.17626 1.78302,6.27872 2.17571,2.17572 4.79133,1.85788 8.18069,-0.99408 1.6341,-1.375 3.48541,-2.5 4.11403,-2.5 0.62862,0 3.16574,2.08129 5.63803,4.6251 3.19105,3.28335 3.90548,4.47092 2.4627,4.09362 -1.50158,-0.39266 -2.03242,-0.049 -2.03242,1.31588 0,2.87356 -1.87067,3.32888 -2.55036,0.62075 -0.47631,-1.89774 -1.08189,-2.30304 -2.77932,-1.86008 -2.09015,0.54543 -2.10383,0.49978 -0.37037,-1.23584 1.95023,-1.95266 1.92268,-5.05943 -0.0449,-5.05943 -0.66964,0 -2.23848,2.02452 -3.48631,4.49893 -1.51335,3.00093 -3.21811,4.82512 -5.11992,5.47861 -2.54265,0.87368 -3.16604,0.62725 -5.7615,-2.27758 -1.6007,-1.79149 -3.44852,-5.26936 -4.10627,-7.72861 -0.70881,-2.65032 -1.77765,-4.47135 -2.62438,-4.47135 -1.15261,0 -1.27015,0.91743 -0.60859,4.75 1.35636,7.85771 0.98677,12.50647 -1.28355,16.14437 l -2.11834,3.39437 -2.1412,-3.39437 z"
|
||||
id="path3012" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 660.82626,157.54075 c -0.79087,-1.40166 -1.23867,-1.50119 -2.24969,-0.5 -2.13582,2.11504 -2.80892,1.39537 -1.69188,-1.80896 0.5865,-1.68243 0.76716,-4.93003 0.40148,-7.21689 l -0.66488,-4.15792 2.32652,3.45232 c 1.27958,1.89877 3.438,4.02134 4.7965,4.71682 l 2.46998,1.2645 -2.24041,0.61419 c -1.77372,0.48625 -2.11567,1.11117 -1.64159,3.00006 0.70205,2.79718 -0.0963,3.13428 -1.50603,0.63588 z"
|
||||
id="path3010" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 639.42454,156.29075 c 0.36373,-1.39092 0.0307,-2 -1.09362,-2 -2.3745,0 -1.96884,-1.51849 0.73476,-2.75033 1.29326,-0.58926 3.34056,-3.02399 4.54954,-5.41052 l 2.19815,-4.33915 -0.73626,4 c -0.93085,5.05715 -0.9285,6.30774 0.0188,9.97285 0.74904,2.89805 0.71927,2.92841 -1.18306,1.20682 -1.71483,-1.5519 -2.02323,-1.57891 -2.5436,-0.22284 -0.87281,2.27444 -2.55558,1.87914 -1.94471,-0.45683 z"
|
||||
id="path3008" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 559.33389,152.29805 c -1.36096,-3.40136 -1.60986,-5.78322 -1.08074,-10.34215 0.49271,-4.24518 0.37211,-5.72816 -0.42571,-5.23508 -0.61223,0.37838 -1.11315,1.28882 -1.11315,2.02319 0,2.11942 -5.60257,7.54674 -7.79043,7.54674 -1.0934,0 -3.05035,-0.88503 -4.34879,-1.96673 l -2.36078,-1.96673 2.31574,-0.0333 c 3.11832,-0.0448 5.90334,-1.63985 7.24702,-4.15054 0.90882,-1.69815 0.71442,-2.49101 -1.07878,-4.39979 l -2.18738,-2.32836 2.1017,-1.79953 c 1.15593,-0.98974 2.10002,-2.71202 2.09796,-3.82729 -0.01,-5.30251 -7.74635,-12.37663 -12.04391,-11.01264 -2.53059,0.80318 -3.49325,4.81583 -2.18107,9.0913 1.20581,3.9289 0.5328,4.20721 -3.1564,1.30528 -3.74589,-2.94651 -5.61488,-7.07208 -5.61488,-12.39416 0,-9.10194 4.25301,-14.790271 11.05829,-14.790271 7.84838,0 13.00716,6.931041 15.3955,20.684461 0.73687,4.24334 1.61121,7.9866 1.94299,8.31838 1.39708,1.39708 0.42618,-7.62798 -1.94067,-18.03965 -4.71604,-20.745631 -4.15173,-29.870761 2.32573,-37.607851 l 2.86102,-3.4174 2.79571,3.66536 c 6.38236,8.36771 6.84993,14.88375 2.55331,35.582971 -3.12581,15.05877 -3.69319,20.63793 -1.99188,19.58646 0.55,-0.33992 1.00534,-2.05398 1.01187,-3.80902 0.016,-4.30623 2.22262,-12.29036 4.77801,-17.28823 5.05289,-9.882491 15.99745,-10.516041 20.8125,-1.20477 1.67788,3.24466 1.83876,12.07486 0.27543,15.11776 -1.41068,2.74581 -5.97323,7.68426 -7.09934,7.68426 -0.46605,0 -0.55944,-2.17044 -0.20754,-4.8232 0.65011,-4.90076 -0.91279,-8.18251 -3.89236,-8.17306 -2.55594,0.008 -7.42529,3.94274 -9.00861,7.27933 -2.1768,4.58727 -2.10667,5.89853 0.43174,8.07198 2.1014,1.79928 2.10142,1.79985 0.10725,3.97224 -3.30503,3.60042 -1.05459,7.33372 5.20376,8.63262 l 3.08729,0.64075 -2.74271,1.80991 c -3.6265,2.3931 -7.40378,1.39839 -9.5744,-2.52134 -3.79073,-6.84534 -4.21981,-6.83231 -3.64856,0.11077 0.41513,5.04556 0.12293,7.38681 -1.30588,10.4632 l -1.84068,3.96321 -1.76817,-4.41911 z"
|
||||
id="path3006" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 639.30715,107.25171 c -2.80055,-4.23192 -7.86815,-7.950871 -10.84286,-7.957221 -2.66872,-0.006 -2.08483,-1.70289 0.83825,-2.43653 2.09086,-0.52478 2.36325,-0.92073 1.41742,-2.06037 -0.64395,-0.77592 -1.01774,-2.20565 -0.83064,-3.17717 0.30604,-1.58913 0.54862,-1.54267 2.41708,0.46289 l 2.0769,2.22929 1.37964,-2.76092 c 1.34281,-2.68724 1.39463,-2.58743 1.94144,3.73907 0.30899,3.575 1.53732,8.637501 2.72963,11.250001 1.1923,2.6125 2.02792,4.75 1.85694,4.75 -0.17099,0 -1.5137,-1.81757 -2.9838,-4.03904 z"
|
||||
id="path3004" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 659.73653,110.00091 c -0.0122,-0.43441 0.96219,-2.68441 2.16539,-5 1.4775,-2.84349 2.20788,-6.092081 2.25,-10.007601 0.0614,-5.70604 0.0903,-5.76302 1.83303,-3.61371 1.71029,2.1093 1.83833,2.12249 3.75613,0.38691 2.49397,-2.25702 3.52367,-1.37283 1.91083,1.64079 -0.77266,1.44374 -0.85488,2.41103 -0.22283,2.62171 0.55088,0.18363 1.8529,0.97833 2.8934,1.766 1.80807,1.36874 1.78352,1.43354 -0.55444,1.46394 -2.29392,0.0298 -10.02724,4.571731 -10.07599,5.917801 -0.0348,0.96003 -3.93055,5.71133 -3.95552,4.82416 z"
|
||||
id="path3000" />
|
||||
<g
|
||||
id="g3200"
|
||||
transform="matrix(1.585999,0,0,1.585999,169.37726,-81.031037)"
|
||||
style="fill:#ff0000">
|
||||
<path
|
||||
id="path3036-1"
|
||||
d="m 142.07892,371.19992 c -1.63435,-1.80594 -1.72217,-2.95171 -0.88718,-11.57564 1.08111,-11.16596 -0.24334,-19.79171 -4.25429,-27.70694 -3.59948,-7.10323 -3.37591,-12.42949 0.81206,-19.34583 1.83333,-3.02771 4.11153,-6.21029 5.06267,-7.07239 1.58356,-1.43532 1.90212,-1.36629 3.77876,0.81884 4.00269,4.66066 7.97327,12.43246 7.98252,15.62458 0.005,1.78106 -1.52402,6.95606 -3.39817,11.5 -4.18973,10.15812 -5.17435,17.38316 -3.62264,26.5827 1.01541,6.02003 0.95696,7.41994 -0.42104,10.08471 -1.87714,3.62998 -2.61079,3.78824 -5.05269,1.08997 z"
|
||||
style="fill:#ff0000"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3030-6"
|
||||
d="m 128.67683,364.45425 c -1.61566,-1.5125 -3.22671,-3.75819 -3.58012,-4.99042 -0.6387,-2.22694 -0.62429,-2.22995 2.39604,-0.5 2.99539,1.71567 3.07621,1.70285 5.68372,-0.90168 3.14168,-3.1381 3.53209,-9.21019 0.85489,-13.29612 -2.86894,-4.37856 -7.44852,-2.7565 -7.44852,2.63822 0,3.42443 -0.93715,3.51436 -4.28548,0.41123 -6.85923,-6.35692 -4.52596,-21.61123 3.30561,-21.61123 5.6523,0 11.32516,7.63857 13.95118,18.78541 2.00468,8.50937 -0.37241,18.75334 -4.91592,21.18495 -2.61735,1.40076 -2.63189,1.39656 -5.9614,-1.72036 z"
|
||||
style="fill:#ff0000"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3028-2"
|
||||
d="m 153.41389,366.16134 c -3.20749,-1.85604 -5.16686,-9.33389 -4.55735,-17.39294 0.63544,-8.40201 3.02837,-14.58643 7.47319,-19.31415 5.70867,-6.072 12.48368,-3.56373 13.78333,5.10293 0.84762,5.65235 -0.82705,10.9488 -4.33412,13.70746 l -2.65913,2.09167 -0.76449,-2.95027 c -1.61718,-6.24093 -5.63987,-6.64475 -8.40613,-0.84385 -2.18715,4.5865 -1.16258,10.07424 2.30507,12.34634 2.36484,1.5495 2.80537,1.55863 5.32881,0.11037 2.54876,-1.46279 2.71812,-1.45364 2.30543,0.12451 -0.67517,2.58183 -4.55351,6.81944 -6.80566,7.43608 -1.1,0.30118 -2.75103,0.11301 -3.66895,-0.41815 z"
|
||||
style="fill:#ff0000"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.7069309,0,0,1.7069309,-128.89437,105.97217)"
|
||||
id="g3217-6">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3038-5"
|
||||
d="m 373.27099,241.06823 c -1.84628,-2.63593 -1.95033,-5.32861 -0.43799,-11.33467 1.61864,-6.4282 4.3072,-6.11508 6.34255,0.73868 1.96801,6.62701 1.94689,7.0299 -0.53384,10.18364 -2.52614,3.21146 -3.36503,3.27587 -5.37072,0.41235 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3034-7"
|
||||
d="m 361.46427,236.21063 c -1.52802,-0.88999 -4.74998,-5.87251 -4.74998,-7.34548 0,-0.2887 1.18444,-0.0746 2.63208,0.47581 3.15303,1.19878 5.48207,0.58612 7.89102,-2.07575 0.98278,-1.08596 2.5693,-1.97447 3.52559,-1.97447 1.52353,0 1.62459,0.52599 0.81659,4.25 -1.39084,6.41021 -5.69191,9.24628 -10.1153,6.66989 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3032-7"
|
||||
d="m 383.50366,236.23263 c -1.5524,-0.905 -3.76993,-6.58507 -3.78379,-9.69193 -0.009,-2.05468 2.73324,-1.42027 5.40351,1.25 2.70807,2.70807 4.64221,3.0781 7.65665,1.46482 2.8803,-1.54149 2.52031,1.18525 -0.65463,4.95845 -2.64398,3.14219 -5.53385,3.81881 -8.62174,2.01866 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3026-1"
|
||||
d="m 368.78843,223.41349 c -3.24581,-0.90704 -3.69702,-2.72315 -0.86503,-3.48176 3.75717,-1.00645 13.45518,-0.72293 16.47579,0.48166 l 2.8151,1.12264 -3,1.33225 c -3.15862,1.4027 -11.32454,1.69131 -15.42586,0.54521 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3024-7"
|
||||
d="m 355.01357,218.04075 c -3.23464,-3.55134 -4.29928,-6.2843 -4.29928,-11.03638 0,-5.50199 3.43432,-11.08028 7.08696,-11.51119 5.3124,-0.62673 11.97142,8.33556 13.43248,18.07861 0.62854,4.19146 0.49934,4.71825 -1.1559,4.71264 -1.02495,-0.003 -2.63011,-1.35348 -3.56703,-3 -2.8379,-4.98728 -7.79651,-3.11706 -7.79651,2.94058 0,2.673 -1.15044,2.61572 -3.70072,-0.18426 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3022-6"
|
||||
d="m 392.71429,217.49075 c 0,-5.59592 -4.97984,-7.12598 -7.16029,-2.2 -0.90934,2.05433 -2.03904,3 -3.58382,3 -2.77389,0 -2.79911,-1.0306 -0.22884,-9.35214 4.66972,-15.11881 15.54237,-18.38805 18.95875,-5.70061 1.40323,5.2112 -0.15236,11.37584 -3.70032,14.66398 -3.34833,3.10313 -4.28548,3.0132 -4.28548,-0.41123 z"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3020-5"
|
||||
d="m 373.29635,217.11089 c -0.22494,-0.72608 -0.66545,-2.8015 -0.97891,-4.61205 -0.31345,-1.81056 -1.92739,-6.68206 -3.58653,-10.82556 -1.65914,-4.14351 -3.0124,-8.73715 -3.00724,-10.20809 0.009,-2.61552 3.96102,-10.21858 7.87383,-15.1487 1.84172,-2.32055 2.07717,-2.37142 3.79025,-0.81883 1.0046,0.91048 3.31662,4.11628 5.13784,7.12399 4.15721,6.86561 4.33517,11.32146 0.74626,18.6863 -1.46947,3.01554 -3.24206,7.9578 -3.93908,10.9828 -1.01385,4.40006 -1.70329,5.56402 -3.44736,5.82014 -1.19903,0.17607 -2.36411,-0.27393 -2.58906,-1 z"
|
||||
style="fill:#000000" />
|
||||
</g>
|
||||
<path
|
||||
style="color:#000000;fill:#2c2c2c;fill-opacity:1;fill-rule:nonzero;stroke:#2c2c2c;stroke-width:1.43718708;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 164.28043,528.44679 c -3.91612,-2.91534 -4.55691,-4.61021 -3.66768,-9.70101 0.59261,-3.39268 1.74495,-7.30762 2.56075,-8.69988 0.81582,-1.39226 -1.76374,-0.26048 -5.73237,2.51508 -4.44433,3.10819 -9.2105,5.0464 -12.40946,5.0464 -6.05029,0 -11.12011,-5.77601 -11.12011,-10.50782 0,-2.65046 0.50293,-3.05427 5.46109,-2.54533 3.24121,0.33269 6.80418,-0.72174 10.55758,-2.07919 l 6.82434,-2.46809 -5.52502,-2.02458 c -6.59267,-2.4158 -7.44963,-7.59864 -1.43824,-8.69808 5.71044,-1.04437 3.02541,-3.29502 -3.93096,-3.29502 -7.03817,0 -16.5956,4.97729 -16.5956,8.64261 0,4.32095 -3.46167,4.60324 -7.91323,0.64531 -8.48024,-7.53984 -7.27811,-19.35286 2.8238,-27.74914 10.85074,-9.01867 25.20095,-6.98906 33.21905,4.6983 4.50002,6.55933 4.86658,6.78795 3.63235,2.26542 -0.75504,-2.76658 -4.14961,-9.50256 -7.54349,-14.96883 -5.42212,-8.73301 -5.90194,-10.56366 -3.95534,-15.09047 1.21843,-2.83348 6.22367,-8.33268 11.12278,-12.22046 l 8.90741,-7.06866 8.10915,6.11516 c 14.93895,11.26555 16.39726,16.32278 8.37454,29.04186 -2.67964,4.24824 -5.49934,9.98763 -6.26604,12.75422 l -1.39394,5.03015 3.98865,-5.91762 c 6.92288,-10.27081 16.43155,-12.93174 28.23004,-7.89996 8.26862,3.52637 13.19281,11.03619 13.19281,20.12015 0,6.08962 -1.01591,8.08645 -6.10466,11.99889 -4.75053,2.71939 -5.1898,4.42271 -6.16486,0.67264 -0.076,-5.07712 -8.9853,-11.06957 -16.4576,-11.06957 -7.75112,0 -8.82255,1.35629 -3.55123,4.49539 l 4.53631,2.70138 -5.7648,3.34561 c -5.30719,3.08004 -5.49049,3.50484 -2.30913,5.35138 1.90062,1.10318 7.57865,1.6872 12.59062,2.03842 6.62376,0.46417 6.74133,0.74306 5.56002,4.89787 -3.32368,11.68985 -17.9597,11.91636 -27.41762,0.88354 -2.27674,-2.65585 -2.36707,-2.60123 -1.18808,0.71859 3.94061,11.09626 3.74213,14.43963 -1.0699,18.02192 -5.86621,4.3671 -6.31005,4.36723 -12.17191,0.003 z"
|
||||
id="path3080"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cssssssscssssssssssscssccsssccsscssssssscc"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.1 dark/genre_québécois.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#2c2c2c;fill-opacity:1;stroke:#2c2c2c;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 633.92274,511.61622 c -1.70784,-4.26831 -2.02018,-7.25725 -1.3562,-12.97816 0.61829,-5.32719 0.46695,-7.18816 -0.53422,-6.5694 -0.76827,0.47482 -1.39686,1.61731 -1.39686,2.53887 0,2.65961 -7.03056,9.47025 -9.77606,9.47025 -1.37209,0 -3.82783,-1.11061 -5.45721,-2.46801 l -2.96249,-2.46801 2.90597,-0.0418 c 3.91311,-0.0562 7.40798,-2.05782 9.09414,-5.20844 1.14046,-2.13097 0.89651,-3.12591 -1.35374,-5.5212 l -2.7449,-2.92181 2.63739,-2.2582 c 1.45055,-1.242 2.63527,-3.40326 2.63268,-4.80279 -0.0125,-6.65402 -9.72074,-15.53118 -15.11366,-13.81954 -3.17559,1.00789 -4.38361,6.04329 -2.73699,11.40848 1.51315,4.93031 0.6686,5.27955 -3.9609,1.63798 -4.70064,-3.69752 -7.046,-8.87462 -7.046,-15.55319 0,-11.42184 5.33702,-18.56003 13.87683,-18.56003 9.84878,0 16.32242,8.69764 19.3195,25.95654 0.92469,5.32488 2.02189,10.02222 2.43822,10.43856 1.75318,1.75318 0.53481,-9.5722 -2.4353,-22.6376 -5.91807,-26.03329 -5.20993,-37.48423 2.91851,-47.19335 l 3.59024,-4.28843 3.50828,4.59959 c 8.0091,10.50047 8.59584,18.67732 3.2041,44.65238 -3.92252,18.89695 -4.63452,25.89812 -2.49957,24.57866 0.69018,-0.42657 1.26158,-2.5775 1.26977,-4.77987 0.02,-5.40381 2.78912,-15.42293 5.99584,-21.69466 6.34076,-12.40135 20.07488,-13.19638 26.11719,-1.51184 2.10554,4.07166 2.30742,15.15251 0.34563,18.97098 -1.77023,3.44566 -7.49569,9.64283 -8.90882,9.64283 -0.58484,0 -0.70203,-2.72365 -0.26044,-6.05254 0.81581,-6.14987 -1.14544,-10.26808 -4.88444,-10.25622 -3.2074,0.01 -9.31785,4.94767 -11.30473,9.13469 -2.73163,5.75647 -2.64362,7.40195 0.54178,10.12937 2.637,2.25788 2.63703,2.2586 0.13459,4.98469 -4.14743,4.51809 -1.32339,9.20293 6.53009,10.8329 l 3.87418,0.80407 -3.44177,2.27122 c -4.55082,3.00304 -9.29086,1.75481 -12.01473,-3.16399 -4.75691,-8.59007 -5.29535,-8.57373 -4.5785,0.13901 0.52093,6.33157 0.15426,9.26956 -1.63873,13.13006 l -2.30983,4.97336 -2.21884,-5.54546 z"
|
||||
id="path3006-2" />
|
||||
<rect
|
||||
style="color:#000000;fill:none;stroke:none;stroke-width:2.36100698;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect3198"
|
||||
width="125.63898"
|
||||
height="125.63899"
|
||||
x="97.537636"
|
||||
y="288.19638"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.1 dark/genre_québécois.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<g
|
||||
transform="matrix(0.36596452,0,0,0.36596452,59.415002,137.45052)"
|
||||
id="layer1-9"
|
||||
style="color:#000000;fill:#2c2c2c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.25158429;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.1 dark/genre_québécois.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 144.15625,0.03125 c -0.13825,0.31354858 -36.40104,50.955423 -59,117.46875 41.30895,13.57365 48.17533,45.24368 51.28125,71.375 C 108.69377,86.75113 -18.822472,131.23717 2.375,208.75 7.218782,226.46225 40.75964,260.03271 78.65625,250.3125 119.07933,239.94428 105.98568,182.7267 72.25,190 50.415851,194.70736 49.77397,224.97331 71,230.40625 c -17.53122,4.74162 -34.12577,-34.17765 -3.15625,-49.375 21.344524,-10.47419 54.09634,2.35206 59.84375,35.75 l 16.46875,0 0.0312,0 16.46875,0 c 5.74741,-33.39794 38.49924,-46.22419 59.84375,-35.75 30.96952,15.19735 14.37499,54.11662 -3.15625,49.375 21.22603,-5.43294 20.58417,-35.69889 -1.25,-40.40625 -33.73568,-7.2733 -46.82932,49.94428 -6.40625,60.3125 37.89661,9.72021 71.43748,-23.85025 76.28125,-41.5625 21.19748,-77.51283 -106.31876,-121.99887 -134.0625,-19.875 3.10592,-26.13132 9.97229,-57.80135 51.28125,-71.375 -22.59896,-66.513324 -58.86175,-117.15520141 -59,-117.46875 -1.1e-4,-2.4516e-4 -0.0312,1.8357e-4 -0.0312,0 z m -16.625,243.28125 c -2.76917,13.76764 -10.5875,25.83587 -26.90625,34.46875 32.90955,1.68807 43.38373,38.1235 43.53125,38.8125 l 0,0.0937 c 0,-8.6e-4 0.0307,-0.0598 0.0312,-0.0625 2.2e-4,-0.001 -3.2e-4,-0.0298 0,-0.0312 0.14752,-0.689 10.62171,-37.12443 43.53125,-38.8125 C 171.4,269.14837 163.58168,257.08014 160.8125,243.3125 l -16.625,0 -0.0312,0 -16.625,0 z"
|
||||
transform="translate(147.05822,286.5625)"
|
||||
id="path3178"
|
||||
style="color:#000000;fill:#2c2c2c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.25158429;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="62.578949"
|
||||
height="20.152544"
|
||||
rx="10.076272"
|
||||
ry="10.076272"
|
||||
x="260.21054"
|
||||
y="506.52594"
|
||||
id="rect2392"
|
||||
style="color:#000000;fill:#2c2c2c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.25158429;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 67 KiB |
@@ -0,0 +1,213 @@
|
||||
<?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://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: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"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
width="500"
|
||||
height="500"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="Thumb_down.svg"><metadata
|
||||
id="metadata8"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6"><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient6232"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.98766169,0,0,1.0896755,-34.224531,-15.222843)"
|
||||
x1="257.69382"
|
||||
y1="97.573967"
|
||||
x2="360.56195"
|
||||
y2="97.573967" /><linearGradient
|
||||
id="linearGradient2515"
|
||||
y2="45.016998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="20.759001"
|
||||
y1="1"
|
||||
x1="20.759001"><stop
|
||||
id="stop3311"
|
||||
style="stop-color:#f6f6f6"
|
||||
offset="0" /><stop
|
||||
id="stop3313"
|
||||
style="stop-color:#d2d2d2"
|
||||
offset="1" /></linearGradient><linearGradient
|
||||
y2="97.573967"
|
||||
x2="360.56195"
|
||||
y1="97.573967"
|
||||
x1="257.69382"
|
||||
gradientTransform="matrix(0.79012935,0,0,-0.8717404,-322.99681,0.94435315)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient6249"
|
||||
xlink:href="#linearGradient2515"
|
||||
inkscape:collect="always" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient6782"
|
||||
x1="-189.35655"
|
||||
y1="50.600105"
|
||||
x2="-86.646011"
|
||||
y2="50.600105"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(256.87149,236.10798)" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515-8"
|
||||
id="linearGradient6782-8"
|
||||
x1="-189.35655"
|
||||
y1="50.600105"
|
||||
x2="-86.646011"
|
||||
y2="50.600105"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
id="linearGradient2515-8"
|
||||
y2="45.016998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="20.759001"
|
||||
y1="1"
|
||||
x1="20.759001"><stop
|
||||
id="stop3311-0"
|
||||
style="stop-color:#f6f6f6"
|
||||
offset="0" /><stop
|
||||
id="stop3313-1"
|
||||
style="stop-color:#d2d2d2"
|
||||
offset="1" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515-0"
|
||||
id="linearGradient6782-86"
|
||||
x1="-189.35655"
|
||||
y1="50.600105"
|
||||
x2="-86.646011"
|
||||
y2="50.600105"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
id="linearGradient2515-0"
|
||||
y2="45.016998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="20.759001"
|
||||
y1="1"
|
||||
x1="20.759001"><stop
|
||||
id="stop3311-00"
|
||||
style="stop-color:#f6f6f6"
|
||||
offset="0" /><stop
|
||||
id="stop3313-2"
|
||||
style="stop-color:#d2d2d2"
|
||||
offset="1" /></linearGradient><filter
|
||||
id="filter4056-0"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB"><feGaussianBlur
|
||||
id="feGaussianBlur4058-2"
|
||||
stdDeviation="7"
|
||||
result="result8" /><feOffset
|
||||
id="feOffset4060-8"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" /><feComposite
|
||||
id="feComposite4062-72"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" /><feFlood
|
||||
id="feFlood4064-7"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" /><feBlend
|
||||
id="feBlend4066-4"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" /><feComposite
|
||||
id="feComposite4068-6"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" /></filter><filter
|
||||
id="filter6856"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB"><feGaussianBlur
|
||||
id="feGaussianBlur6858"
|
||||
stdDeviation="7"
|
||||
result="result8" /><feOffset
|
||||
id="feOffset6860"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" /><feComposite
|
||||
id="feComposite6862"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" /><feFlood
|
||||
id="feFlood6864"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" /><feBlend
|
||||
id="feBlend6866"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" /><feComposite
|
||||
id="feComposite6868"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" /></filter></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="1000"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.827"
|
||||
inkscape:cx="250"
|
||||
inkscape:cy="250"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g10" /><g
|
||||
id="g10"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="wpzoom_developer"
|
||||
transform="matrix(1.25,0,0,-1.25,0,500)"><g
|
||||
inkscape:label="wpzoom_developer"
|
||||
id="g3030" /><path
|
||||
style="fill:url(#linearGradient6782);fill-opacity:1;stroke:#666666;stroke-width:2.4000001;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 68.714941,286.07266 c 0,0 23.66646,-8.02015 37.597189,-45.03399 1.64953,-4.38281 10.12858,-5.05491 11.65393,-1.89465 5.43194,11.25397 -0.91188,30.81556 -0.91188,30.81556 25.49151,0.25225 68.09402,-6.4894 45.65374,16.52624 0.96991,0.49199 14.81442,12.22014 -3.51183,17.14597 12.05736,9.74191 4.64063,13.34392 -2.85665,16.64724 16.78512,28.64473 -72.954709,11.50982 -87.211339,3.80398 z"
|
||||
id="path4017"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csscccccc"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 icons/Thumb_down.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" /><path
|
||||
style="fill:#333333;fill-opacity:1;stroke:none"
|
||||
d="m 70.253351,159.8587 c 0,0 23.66646,-8.02015 37.597189,-45.03398 1.64953,-4.38281 10.12858,-5.05491 11.65393,-1.89465 5.43194,11.25397 -0.91188,30.81555 -0.91188,30.81555 25.49151,0.25226 68.09402,-6.4894 45.65373,16.52624 0.96992,0.49199 14.81443,12.22014 -3.51182,17.14597 12.05736,9.74191 4.64063,13.34392 -2.85664,16.64725 16.78511,28.64472 -72.954719,11.50981 -87.211349,3.80397 z"
|
||||
id="path4017-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csscccccc"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 dark icons/Thumb_down.png"
|
||||
inkscape:export-xdpi="91.586052"
|
||||
inkscape:export-ydpi="91.586052" /><path
|
||||
style="fill:#b3b3b3;fill-opacity:1;stroke:none;filter:url(#filter6856)"
|
||||
d="m 212.08526,159.8587 c 0,0 23.66646,-8.02015 37.59719,-45.03399 1.64953,-4.3828 10.12858,-5.0549 11.65393,-1.89464 5.43194,11.25397 -0.91188,30.81556 -0.91188,30.81556 25.49151,0.25225 68.09402,-6.48941 45.65372,16.52623 0.96992,0.49199 14.81444,12.22014 -3.51182,17.14597 12.05737,9.74191 4.64063,13.34392 -2.85664,16.64725 16.78512,28.64472 -72.95471,11.50981 -87.21134,3.80397 z"
|
||||
id="path4017-21"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csscccccc"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 light/Thumb_down_light.png"
|
||||
inkscape:export-xdpi="73.268837"
|
||||
inkscape:export-ydpi="73.268837" /></g></svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 8.3 KiB |
@@ -0,0 +1,665 @@
|
||||
<?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://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: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="350"
|
||||
height="200"
|
||||
id="svg6462"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="arrow_up_down.svg"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/UpDownArrows.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.8051997"
|
||||
inkscape:cx="89.596418"
|
||||
inkscape:cy="295.35798"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="838"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true" />
|
||||
<defs
|
||||
id="defs6464">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6364"
|
||||
id="linearGradient6370"
|
||||
x1="101.42937"
|
||||
y1="400.5535"
|
||||
x2="99.124153"
|
||||
y2="244.95164"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.340328,0,0,1.340328,-155.22114,-66.380723)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364-8">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366-5" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368-9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="244.95164"
|
||||
x2="99.124153"
|
||||
y1="400.5535"
|
||||
x1="101.42937"
|
||||
gradientTransform="matrix(1.340328,0,0,1.340328,-66.590934,-328.62237)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient6531"
|
||||
xlink:href="#linearGradient6364-8"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="244.95164"
|
||||
x2="99.124153"
|
||||
y1="400.5535"
|
||||
x1="101.42937"
|
||||
gradientTransform="matrix(1.340328,0,0,1.340328,-31.467381,555.95415)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient6460"
|
||||
xlink:href="#linearGradient6364-2"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364-2">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366-7" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368-8" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="244.95164"
|
||||
x2="99.124153"
|
||||
y1="400.5535"
|
||||
x1="101.42937"
|
||||
gradientTransform="matrix(1.340328,0,0,-1.340328,133.5722,1341.1989)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient6421-9"
|
||||
xlink:href="#linearGradient6364-5-9"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364-5-9">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366-4-1" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368-6-9" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
id="filter3970"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3972"
|
||||
stdDeviation="4"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset3974"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite3976"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood3978"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend3980"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite3982"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter3984"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3986"
|
||||
stdDeviation="4"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset3988"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite3990"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood3992"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend3994"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite3996"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:label="Inner Shadow"
|
||||
id="filter3142">
|
||||
<feGaussianBlur
|
||||
result="result8"
|
||||
stdDeviation="4"
|
||||
id="feGaussianBlur3144" />
|
||||
<feOffset
|
||||
result="result11"
|
||||
dy="4"
|
||||
dx="4"
|
||||
id="feOffset3146" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
in="SourceGraphic"
|
||||
result="result6"
|
||||
in2="result11"
|
||||
id="feComposite3148" />
|
||||
<feFlood
|
||||
flood-color="rgb(0,0,0)"
|
||||
flood-opacity="1"
|
||||
in="result6"
|
||||
result="result10"
|
||||
id="feFlood3150" />
|
||||
<feBlend
|
||||
result="result12"
|
||||
in="result6"
|
||||
mode="normal"
|
||||
in2="result10"
|
||||
id="feBlend3152" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
result="result2"
|
||||
in2="SourceGraphic"
|
||||
id="feComposite3154" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:label="Inner Shadow"
|
||||
id="filter3938">
|
||||
<feGaussianBlur
|
||||
result="result8"
|
||||
stdDeviation="4"
|
||||
id="feGaussianBlur3940" />
|
||||
<feOffset
|
||||
result="result11"
|
||||
dy="4"
|
||||
dx="4"
|
||||
id="feOffset3942" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
in="SourceGraphic"
|
||||
result="result6"
|
||||
in2="result11"
|
||||
id="feComposite3944" />
|
||||
<feFlood
|
||||
flood-color="rgb(0,0,0)"
|
||||
flood-opacity="1"
|
||||
in="result6"
|
||||
result="result10"
|
||||
id="feFlood3946" />
|
||||
<feBlend
|
||||
result="result12"
|
||||
in="result6"
|
||||
mode="normal"
|
||||
in2="result10"
|
||||
id="feBlend3948" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
result="result2"
|
||||
in2="SourceGraphic"
|
||||
id="feComposite3950" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:label="Inner Shadow"
|
||||
id="filter3060">
|
||||
<feGaussianBlur
|
||||
result="result8"
|
||||
stdDeviation="4"
|
||||
id="feGaussianBlur3062" />
|
||||
<feOffset
|
||||
result="result11"
|
||||
dy="4"
|
||||
dx="4"
|
||||
id="feOffset3064" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
in="SourceGraphic"
|
||||
result="result6"
|
||||
in2="result11"
|
||||
id="feComposite3066" />
|
||||
<feFlood
|
||||
flood-color="rgb(0,0,0)"
|
||||
flood-opacity="1"
|
||||
in="result6"
|
||||
result="result10"
|
||||
id="feFlood3068" />
|
||||
<feBlend
|
||||
result="result12"
|
||||
in="result6"
|
||||
mode="normal"
|
||||
in2="result10"
|
||||
id="feBlend3070" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
result="result2"
|
||||
in2="SourceGraphic"
|
||||
id="feComposite3072" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4056"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4058"
|
||||
stdDeviation="10"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4060"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4062"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4064"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4066"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4068"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4070"
|
||||
inkscape:label="Darken edges"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Darken the edges with an inner blur"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4072"
|
||||
stdDeviation="10"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4074"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4076"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4078"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4080"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4082"
|
||||
in2="SourceGraphic"
|
||||
result="fbSourceGraphic"
|
||||
operator="in" />
|
||||
<feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix3318" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3320"
|
||||
result="result6"
|
||||
stdDeviation="1.5"
|
||||
in="fbSourceGraphic" />
|
||||
<feComposite
|
||||
in2="result6"
|
||||
id="feComposite3322"
|
||||
operator="atop"
|
||||
in="fbSourceGraphic"
|
||||
result="result8" />
|
||||
<feComposite
|
||||
in2="fbSourceGraphicAlpha"
|
||||
id="feComposite3324"
|
||||
in="result8"
|
||||
operator="atop"
|
||||
result="result9" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4092"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4094"
|
||||
result="result6"
|
||||
stdDeviation="1.5" />
|
||||
<feComposite
|
||||
id="feComposite4096"
|
||||
in2="result6"
|
||||
operator="atop"
|
||||
in="SourceGraphic"
|
||||
result="result8" />
|
||||
<feComposite
|
||||
id="feComposite4098"
|
||||
in2="SourceAlpha"
|
||||
in="result8"
|
||||
operator="atop"
|
||||
result="fbSourceGraphic" />
|
||||
<feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix3076" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3078"
|
||||
stdDeviation="4"
|
||||
result="result8"
|
||||
in="fbSourceGraphic" />
|
||||
<feOffset
|
||||
id="feOffset3080"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite3082"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="fbSourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood3084"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend3086"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite3088"
|
||||
in2="fbSourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4100"
|
||||
inkscape:label="Darken edges"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Darken the edges with an inner blur"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4102"
|
||||
result="result6"
|
||||
stdDeviation="1.5" />
|
||||
<feComposite
|
||||
id="feComposite4104"
|
||||
in2="result6"
|
||||
operator="atop"
|
||||
in="SourceGraphic"
|
||||
result="result8" />
|
||||
<feComposite
|
||||
id="feComposite4106"
|
||||
in2="SourceAlpha"
|
||||
in="result8"
|
||||
operator="atop"
|
||||
result="result9" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4108"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4110"
|
||||
stdDeviation="4"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4112"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4114"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4116"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4118"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4120"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4122"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4124"
|
||||
stdDeviation="4"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4126"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4128"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4130"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4132"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4134"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4056-2"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4058-5"
|
||||
stdDeviation="10"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4060-5"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4062-7"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4064-4"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4066-6"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4068-4"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata6467">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-852.36218)">
|
||||
<path
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
d="m 109.97665,1013.0365 c 3.88181,-4.4411 3.54747,-4.0586 5.66627,-6.4826 1.76561,-2.02 3.67098,-4.1998 5.66612,-6.4824 1.82615,-2.08923 3.72752,-4.2645 5.66577,-6.48199 1.86579,-2.13456 3.76575,-4.30824 5.66571,-6.48192 1.89982,-2.1735 3.79963,-4.34701 5.66526,-6.4814 1.93849,-2.21775 3.84008,-4.39328 5.66643,-6.48274 1.99496,-2.28236 3.90016,-4.46202 5.66562,-6.48182 2.1187,-2.42392 1.19183,-1.53132 5.66599,-6.48224 4.47415,-4.95091 4.18341,-8.07257 0.18958,-12.35877 -3.99382,-4.28619 -1.35465,-1.21511 -5.47603,-5.87689 -4.12139,-4.66178 -7.03279,-4.31521 -10.59786,-0.73851 -3.56507,3.57671 -3.28885,3.29959 -5.12216,5.13888 -1.68683,1.69234 -3.43546,3.44668 -5.12226,5.13899 -1.83328,1.83927 -3.59351,3.60525 -5.12196,5.13868 -3.0098,3.01962 -5.12078,5.13749 -5.12078,5.13749 0,0 0,-3.10277 0,-7.8321 0,-2.2865 0,-4.9532 0,-7.83328 0,-2.48748 0,-5.13414 0,-7.83248 0,-2.59519 0,-5.23821 0,-7.83341 0,-2.69857 0,-5.34545 0,-7.83313 0,-2.87975 -0.17088,-1.88099 0,-7.83249 0.17088,-5.9515 -2.20963,-7.83295 -7.27343,-7.83295 -5.06382,0 -4.7469,0 -7.27268,0 -2.52601,0 -1.22935,0.18081 -7.27341,0 -6.044056,-0.18081 -7.281234,2.73055 -7.295156,7.8321 -0.01393,5.10156 -0.01354,4.9532 -0.02142,7.83329 -0.0068,2.48748 -0.01405,5.13413 -0.02142,7.83247 -0.0071,2.5952 -0.01433,5.23822 -0.02142,7.83342 -0.0074,2.69857 -0.01462,5.34544 -0.02142,7.83313 -0.0079,2.87974 -0.01517,5.54616 -0.02142,7.83248 -0.01293,4.72981 -0.02142,7.83295 -0.02142,7.83295 0,0 -2.109697,-2.13039 -5.117535,-5.16773 -1.527284,-1.54227 -3.286133,-3.31836 -5.117936,-5.16813 -1.685436,-1.70198 -3.432634,-3.46631 -5.118041,-5.16826 -1.83177,-1.84973 -0.988687,-0.74002 -5.117737,-5.16792 -4.129049,-4.42791 -6.926679,-3.21051 -10.599651,0.75894 -3.672973,3.96945 -0.81191,1.16868 -5.48307,5.92566 -4.671161,4.75698 -3.511079,8.18189 0.18277,12.40788 3.693848,4.22599 3.547459,4.05852 5.666264,6.48256 1.76561,2.01996 3.670974,4.19982 5.666115,6.48238 1.826153,2.08923 3.727519,4.26451 5.665773,6.48199 1.865785,2.13457 3.765749,4.30824 5.665712,6.48192 1.899816,2.1735 3.799628,4.34701 5.665262,6.4814 1.938488,2.21776 3.840076,4.39329 5.666426,6.48275 1.994967,2.2824 3.900162,4.462 5.665617,6.4818 2.118707,2.4239 1.17313,1.1139 5.665992,6.4823 4.492855,5.3683 7.449735,4.4407 11.331535,-3e-4 z"
|
||||
id="path6832-1-9-7-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zccccccczzzzssscssssszzszzssssscssszzccssssssszz"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 dark icons/arrow_down_dark.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<path
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
d="m 240.24703,902.9148 c -3.8818,4.44108 -3.54746,4.0586 -5.66626,6.48262 -1.76561,2.01997 -3.67098,4.19982 -5.66612,6.48239 -1.82615,2.08923 -3.72752,4.26451 -5.66577,6.48199 -1.86579,2.13457 -3.76575,4.30824 -5.66571,6.48192 -1.89982,2.1735 -3.79963,4.34701 -5.66526,6.4814 -1.93849,2.21776 -3.84008,4.39328 -5.66643,6.48274 -1.99496,2.28237 -3.90016,4.46203 -5.66562,6.48182 -2.11871,2.42392 -1.19183,1.53132 -5.66599,6.48224 -4.47415,4.95091 -4.18341,8.07257 -0.18959,12.35877 3.99383,4.28619 1.35466,1.21511 5.47604,5.87689 4.12139,4.66179 7.03279,4.31521 10.59786,0.73851 3.56507,-3.5767 3.28885,-3.29958 5.12216,-5.13888 1.68683,-1.69234 3.43546,-3.44668 5.12226,-5.13899 1.83328,-1.83927 3.59351,-3.60524 5.12196,-5.13868 3.00979,-3.01962 5.12078,-5.13749 5.12078,-5.13749 0,0 0,3.10277 0,7.8321 0,2.2865 0,4.9532 0,7.83328 0,2.48748 0,5.13414 0,7.83248 0,2.59519 0,5.23821 0,7.83341 0,2.69857 0,5.34545 0,7.83313 0,2.87975 0.17088,1.88099 0,7.83245 -0.17088,5.9515 2.20963,7.833 7.27343,7.833 5.06382,0 4.74689,0 7.27267,0 2.52601,0 1.22936,-0.1808 7.27341,0 6.04406,0.1808 7.28124,-2.7306 7.29516,-7.8321 0.0139,-5.10157 0.0135,-4.95321 0.0214,-7.83329 0.007,-2.48749 0.014,-5.13414 0.0214,-7.83248 0.007,-2.5952 0.0143,-5.23821 0.0214,-7.83342 0.007,-2.69857 0.0146,-5.34544 0.0214,-7.83312 0.008,-2.87975 0.0152,-5.54617 0.0214,-7.83249 0.0129,-4.72981 0.0214,-7.83295 0.0214,-7.83295 0,0 2.1097,2.13039 5.11754,5.16773 1.52728,1.54227 3.28613,3.31836 5.11793,5.16813 1.68544,1.70198 3.43264,3.46631 5.11804,5.16826 1.83177,1.84973 0.98869,0.74002 5.11774,5.16792 4.12905,4.42792 6.92668,3.21051 10.59965,-0.75894 3.67297,-3.96945 0.81191,-1.16868 5.48307,-5.92566 4.67116,-4.75698 3.51108,-8.18189 -0.18277,-12.40788 -3.69385,-4.22599 -3.54746,-4.05851 -5.66626,-6.48255 -1.76561,-2.01997 -3.67098,-4.19982 -5.66612,-6.48239 -1.82615,-2.08923 -3.72752,-4.26451 -5.66577,-6.48199 -1.86579,-2.13457 -3.76575,-4.30824 -5.66571,-6.48192 -1.89982,-2.1735 -3.79963,-4.34701 -5.66527,-6.4814 -1.93848,-2.21775 -3.84007,-4.39328 -5.66642,-6.48274 -1.99497,-2.28236 -3.90016,-4.46203 -5.66562,-6.48182 -2.11871,-2.42394 -1.17313,-1.11392 -5.66599,-6.48227 -4.49286,-5.36834 -7.44974,-4.44071 -11.33154,2.7e-4 z"
|
||||
id="path6832-1-9-7-8-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zccccccczzzzssscssssszzszzssssscssszzccssssssszz"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 dark icons/arrow_up_dark.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 23 KiB |
|
Depois Largura: | Altura: | Tamanho: 84 KiB |
|
Depois Largura: | Altura: | Tamanho: 32 KiB |
@@ -0,0 +1,932 @@
|
||||
<?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://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: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"
|
||||
id="svg2527"
|
||||
height="192"
|
||||
width="672"
|
||||
version="1.0"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="playlist_sprites_dark.svg"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/0.8 dark icons/playlist_sprites_arrow.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<metadata
|
||||
id="metadata3118">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="838"
|
||||
id="namedview3116"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.49402629"
|
||||
inkscape:cx="260.00154"
|
||||
inkscape:cy="144.39242"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2527"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="32,116.97128"
|
||||
id="guide3157" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="160,144.38642"
|
||||
id="guide3159" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="109.66058,32"
|
||||
id="guide3161" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="0,160"
|
||||
id="guide3163" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="192,126.10966"
|
||||
id="guide3165" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="320,63.054831"
|
||||
id="guide3167" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="352,116.05744"
|
||||
id="guide3169" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="473.65901,-160.58525"
|
||||
id="guide3171" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="512,204.69974"
|
||||
id="guide3173" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="640,229.37337"
|
||||
id="guide3175" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs2529">
|
||||
<radialGradient
|
||||
id="radialGradient2436"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cy="4.625"
|
||||
cx="62.625"
|
||||
gradientTransform="matrix(2.1647,0,0,0.75294,-111.56,36.518)"
|
||||
r="10.625">
|
||||
<stop
|
||||
id="stop8840"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop8842"
|
||||
style="stop-opacity:0"
|
||||
offset="1" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2517"
|
||||
y2="45"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="37.201"
|
||||
y1="1"
|
||||
x1="37.201">
|
||||
<stop
|
||||
id="stop3399"
|
||||
style="stop-color:#aaa"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3401"
|
||||
style="stop-color:#8c8c8c"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2515"
|
||||
y2="45.016998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="20.759001"
|
||||
y1="1"
|
||||
x1="20.759001">
|
||||
<stop
|
||||
id="stop3311"
|
||||
style="stop-color:#f6f6f6"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3313"
|
||||
style="stop-color:#d2d2d2"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2512"
|
||||
y2="20.895"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="84.639"
|
||||
gradientTransform="matrix(0.32448,0,0,0.32448,3.2333,2.5577)"
|
||||
y1="105.1"
|
||||
x1="86.133003">
|
||||
<stop
|
||||
id="stop5130"
|
||||
style="stop-color:#e5e5e5"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5132"
|
||||
style="stop-color:#ababab"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="10.625"
|
||||
gradientTransform="matrix(1.8824,0,0,0.47059,-95.882,39.824)"
|
||||
cx="62.625"
|
||||
cy="4.625"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3094">
|
||||
<stop
|
||||
offset="0"
|
||||
id="stop8840-3" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-opacity:0"
|
||||
id="stop8842-6" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
x1="28.739"
|
||||
y1="144.12"
|
||||
gradientTransform="matrix(0.566,0,0,0.34475,22.846,-40.334)"
|
||||
x2="26.257"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient2372"
|
||||
y2="125.39"
|
||||
id="linearGradient2910" />
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0711,-0.17393,0.023379,1.0027,12.439,-4.4377)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.841"
|
||||
fx="14.758"
|
||||
id="radialGradient2907">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop3670" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop3672" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
x1="28.503"
|
||||
y1="137.53999"
|
||||
gradientTransform="matrix(0.33924,0,0,0.33977,9.2602,-34.856)"
|
||||
x2="26.257"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient2372"
|
||||
y2="125.39"
|
||||
id="linearGradient2904" />
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0173,-0.18234,0.035717,0.96941,-5.8008,1.5991)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.456001"
|
||||
fx="14.688"
|
||||
id="radialGradient2901">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop7069" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop7071" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2372">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop2374" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop2376" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2372-7">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop2374-9" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop2376-4" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0711,-0.17393,0.023379,1.0027,12.439,-4.4377)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.841"
|
||||
fx="14.758"
|
||||
id="radialGradient2907-7">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop3670-0" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop3672-8" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4366">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop4368" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop4370" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient2901-6"
|
||||
id="radialGradient4313-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.65701931,-0.11776359,0.02306769,0.62608974,-32.804054,1.418643)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
fx="14.688"
|
||||
fy="37.456001"
|
||||
r="5.7385001" />
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0173,-0.18234,0.035717,0.96941,-5.8008,1.5991)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.456001"
|
||||
fx="14.688"
|
||||
id="radialGradient2901-6">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop7069-7" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop7071-2" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2372-7-0">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop2374-9-9" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop2376-4-7" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0711,-0.17393,0.023379,1.0027,12.439,-4.4377)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.841"
|
||||
fx="14.758"
|
||||
id="radialGradient2907-7-1">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop3670-0-1" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop3672-8-8" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4534">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop4536" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop4538" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient2901-6-3"
|
||||
id="radialGradient4477-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.65701931,-0.11776359,0.02306769,0.62608974,-32.804054,1.418643)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
fx="14.688"
|
||||
fy="37.456001"
|
||||
r="5.7385001" />
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0173,-0.18234,0.035717,0.96941,-5.8008,1.5991)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.456001"
|
||||
fx="14.688"
|
||||
id="radialGradient2901-6-3">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop7069-7-0" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop7071-2-2" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2372-7-0-0">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop2374-9-9-6" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop2376-4-7-1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0711,-0.17393,0.023379,1.0027,12.439,-4.4377)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.841"
|
||||
fx="14.758"
|
||||
id="radialGradient2907-7-1-7">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop3670-0-1-0" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop3672-8-8-4" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4622">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop4624" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop4626" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
fy="37.456001"
|
||||
fx="14.688"
|
||||
cy="41.058998"
|
||||
cx="17.059"
|
||||
gradientTransform="matrix(0.65701931,-0.11776359,0.02306769,0.62608974,-32.804054,1.418643)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4550-1"
|
||||
xlink:href="#radialGradient2901-6-3-8"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0173,-0.18234,0.035717,0.96941,-5.8008,1.5991)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.456001"
|
||||
fx="14.688"
|
||||
id="radialGradient2901-6-3-8">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop7069-7-0-9" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop7071-2-2-1" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2372-7-0-2">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop2374-9-9-1" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop2376-4-7-15" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0711,-0.17393,0.023379,1.0027,12.439,-4.4377)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.841"
|
||||
fx="14.758"
|
||||
id="radialGradient2907-7-1-9">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop3670-0-1-9" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop3672-8-8-6" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4622-0">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop4624-5" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop4626-1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
fy="37.456001"
|
||||
fx="14.688"
|
||||
cy="41.058998"
|
||||
cx="17.059"
|
||||
gradientTransform="matrix(0.65701931,-0.11776359,0.02306769,0.62608974,-32.804054,1.418643)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4550-7"
|
||||
xlink:href="#radialGradient2901-6-3-1"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0173,-0.18234,0.035717,0.96941,-5.8008,1.5991)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.456001"
|
||||
fx="14.688"
|
||||
id="radialGradient2901-6-3-1">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop7069-7-0-3" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop7071-2-2-16" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient4895"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient4897"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient4899"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient4901"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient4903"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient4907"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient4909"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387" />
|
||||
<linearGradient
|
||||
id="linearGradient2372-7-0-5">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop2374-9-9-5" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop2376-4-7-4" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0711,-0.17393,0.023379,1.0027,12.439,-4.4377)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.841"
|
||||
fx="14.758"
|
||||
id="radialGradient2907-7-1-1">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop3670-0-1-90" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop3672-8-8-3" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4930">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop4932" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:.34483"
|
||||
id="stop4934" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient2901-6-3-4"
|
||||
id="radialGradient4857-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.65701931,-0.11776359,0.02306769,0.62608974,-32.804054,1.418643)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
fx="14.688"
|
||||
fy="37.456001"
|
||||
r="5.7385001" />
|
||||
<radialGradient
|
||||
r="5.7385001"
|
||||
gradientTransform="matrix(1.0173,-0.18234,0.035717,0.96941,-5.8008,1.5991)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="37.456001"
|
||||
fx="14.688"
|
||||
id="radialGradient2901-6-3-4">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#fff"
|
||||
id="stop7069-7-0-38" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#fff;stop-opacity:0"
|
||||
id="stop7071-2-2-7" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient5008"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient5010"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="199.89294"
|
||||
y1="100.19387"
|
||||
x2="322.9762"
|
||||
y2="100.19387" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2372-7-0-0"
|
||||
id="linearGradient5203"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.36554893,0,0,0.22265547,-14.302628,-25.663689)"
|
||||
x1="28.739"
|
||||
y1="144.12"
|
||||
x2="26.257"
|
||||
y2="125.39" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient2907-7-1-7"
|
||||
id="radialGradient5205"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.69176583,-0.11233202,0.01509924,0.64758995,-21.023949,-2.4802012)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
fx="14.758"
|
||||
fy="37.841"
|
||||
r="5.7385001" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2372-7-0-0"
|
||||
id="linearGradient5207"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.21909685,0,0,0.21943915,-23.076965,-22.125744)"
|
||||
x1="28.503"
|
||||
y1="137.53999"
|
||||
x2="26.257"
|
||||
y2="125.39" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient2901-6-3-8"
|
||||
id="radialGradient5209"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.65701931,-0.11776359,0.02306769,0.62608974,-32.804054,1.418643)"
|
||||
cx="17.059"
|
||||
cy="41.058998"
|
||||
fx="14.688"
|
||||
fy="37.456001"
|
||||
r="5.7385001" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient5218"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.98766169,0,0,1.0864702,-35.859333,-13.634417)"
|
||||
x1="257.69382"
|
||||
y1="97.573967"
|
||||
x2="360.56195"
|
||||
y2="97.573967" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2515"
|
||||
id="linearGradient5223"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.98766169,0,0,1.0864702,-35.859333,-13.634417)"
|
||||
x1="257.69382"
|
||||
y1="97.573967"
|
||||
x2="360.56195"
|
||||
y2="97.573967" />
|
||||
</defs>
|
||||
<g
|
||||
id="g3879"
|
||||
transform="matrix(1.0065385,0,0,0.99324553,342.07202,-7.5608658)"
|
||||
style="fill:url(#linearGradient4899);fill-opacity:1;stroke:#666666;stroke-width:2.90937853;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
|
||||
<g
|
||||
id="g3851"
|
||||
style="fill:url(#linearGradient4897);fill-opacity:1;stroke:#666666;stroke-width:2.90937853;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.0065385,0,0,0.99324553,389.97009,-7.5608658)"
|
||||
id="g3879-9"
|
||||
style="fill:url(#linearGradient4903);fill-opacity:1;stroke:#666666;stroke-width:2.90937853;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none">
|
||||
<g
|
||||
id="g3851-8"
|
||||
style="fill:url(#linearGradient4901);fill-opacity:1;stroke:#666666;stroke-width:2.90937853;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
</g>
|
||||
<g
|
||||
id="g5086"
|
||||
transform="matrix(1.0227382,0,0,1.0239163,-508.65243,94.907326)"
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none">
|
||||
<g
|
||||
transform="translate(2.2931143,-0.91383812)"
|
||||
id="g5041"
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none">
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="526.33917"
|
||||
y="-60.113762"
|
||||
rx="2.252898" />
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014-4"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="617.52295"
|
||||
y="-60.113762"
|
||||
rx="2.252898"
|
||||
inkscape:transform-center-x="-6.2577015"
|
||||
inkscape:transform-center-y="13.409394" />
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014-5"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="571.93103"
|
||||
y="-60.113762"
|
||||
rx="2.252898" />
|
||||
</g>
|
||||
<g
|
||||
id="g5041-9"
|
||||
transform="translate(2.2931144,44.606043)"
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none">
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014-7"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="526.33917"
|
||||
y="-60.113762"
|
||||
rx="2.252898" />
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014-4-0"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="617.52295"
|
||||
y="-60.113762"
|
||||
rx="2.252898"
|
||||
inkscape:transform-center-x="-6.2577015"
|
||||
inkscape:transform-center-y="13.409394" />
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014-5-5"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="571.93103"
|
||||
y="-60.113762"
|
||||
rx="2.252898" />
|
||||
</g>
|
||||
<g
|
||||
id="g5041-0"
|
||||
transform="translate(2.2931144,90.125919)"
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none">
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014-6"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="526.33917"
|
||||
y="-60.113762"
|
||||
rx="2.252898" />
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014-4-1"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="617.52295"
|
||||
y="-60.113762"
|
||||
rx="2.252898"
|
||||
inkscape:transform-center-x="-6.2577015"
|
||||
inkscape:transform-center-y="13.409394" />
|
||||
<rect
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:none"
|
||||
id="rect5014-5-8"
|
||||
width="33.970463"
|
||||
height="33.970463"
|
||||
x="571.93103"
|
||||
y="-60.113762"
|
||||
rx="2.252898" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="46.825909"
|
||||
y="180.1373"
|
||||
id="text6872"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6874"
|
||||
x="46.825909"
|
||||
y="180.1373"
|
||||
style="font-size:16px;fill:#4d4d4d">Music Library</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="193.38106"
|
||||
y="180.1373"
|
||||
id="text6872-9"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="193.38106"
|
||||
y="180.1373"
|
||||
style="font-size:16px;fill:#4d4d4d"
|
||||
id="tspan6901">Regular Playlist</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="522.20959"
|
||||
y="180.1373"
|
||||
id="text6872-9-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="522.20959"
|
||||
y="180.1373"
|
||||
style="font-size:16px;fill:#4d4d4d"
|
||||
id="tspan6901-9">Smart Playlist</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="376.3222"
|
||||
y="180.1373"
|
||||
id="text6872-9-73"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="376.3222"
|
||||
y="180.1373"
|
||||
style="font-size:16px;fill:#4d4d4d"
|
||||
id="tspan6935">Play Queue</tspan></text>
|
||||
<path
|
||||
id="path4297"
|
||||
style="fill:#4d4d4d;stroke:none"
|
||||
d="m 414.82281,91.399615 35.88562,22.428515 -35.8856,22.42851 z M 379.90625,67.65625 c -1.30309,0 -2.375,1.040658 -2.375,2.34375 l 0,87.65625 c 0,1.30309 1.07191,2.34375 2.375,2.34375 l 97.75,0 C 478.95934,160 480,158.95934 480,157.65625 L 480,70 c 0,-1.303092 -1.04066,-2.34375 -2.34375,-2.34375 l -97.75,0 z m -25.5625,-35.656252 c -1.30309,0 -2.34375,1.099725 -2.34375,2.47678 l 0,80.115582 c 0,1.37705 1.04066,2.47678 2.34375,2.47678 l 4.65625,0 0,-71.133126 c 0,-1.377055 1.04066,-2.509804 2.34375,-2.509804 l 93.125,0 0,-8.949432 c 0,-1.377055 -1.07191,-2.47678 -2.375,-2.47678 l -97.75,0 z m 12.125,18.650943 c -1.27351,0 -2.28125,1.064944 -2.28125,2.410733 l 0,85.399386 c 0,1.34579 1.00774,2.44375 2.28125,2.44375 l 6.625,0 0,-76.119711 c 0,-1.345788 1.03899,-2.410732 2.3125,-2.410732 l 88.90625,0 0,-9.312693 c 0,-1.345789 -1.00774,-2.410733 -2.28125,-2.410733 l -95.5625,0 z" />
|
||||
<path
|
||||
id="path4297-9"
|
||||
style="fill:#4d4d4d;stroke:none"
|
||||
d="m 565.26031,73.571509 35.88562,22.42852 -35.88558,22.428511 z M 568.1875,32 c -2.56538,0 -4.625,2.094515 -4.625,4.65625 l 0,9.03125 c -4.58796,1.2002 -8.99122,2.991286 -13,5.28125 l -6.53125,-6.40625 c -0.92182,-0.905806 -2.024,-1.396427 -3.21875,-1.40625 -1.19475,-0.0098 -2.40582,0.421876 -3.3125,1.3125 l -12.8125,12.5625 c -1.81426,1.782439 -1.75173,4.596425 0.0937,6.40625 l 6.5625,6.4375 c -2.33279,3.935177 -4.1839,8.215027 -5.40625,12.71875 l -9.1875,0 c -2.60995,0 -4.75,2.044225 -4.75,4.5625 l 0,17.6875 c 0,2.52125 2.14036,4.5625 4.75,4.5625 l 9.1875,0 c 1.22238,4.50343 3.07377,8.81303 5.40625,12.75 l -6.5625,6.40625 c -1.84549,1.80982 -1.90802,4.62321 -0.0937,6.40625 l 12.8125,12.5625 c 1.81426,1.78095 4.68607,1.71764 6.53125,-0.0937 l 6.53125,-6.40625 c 4.01091,2.28984 8.41234,4.08135 13,5.28125 l 0,9.03125 c 0,2.56171 2.05939,4.65625 4.625,4.65625 l 18,0 c 2.56841,0 4.65625,-2.0963 4.65625,-4.65625 l 0,-9.03125 c 4.58766,-1.19994 8.95815,-2.99158 12.96875,-5.28125 l 6.5625,6.40625 c 1.84529,1.81141 4.71699,1.87476 6.53125,0.0937 l 12.78125,-12.5625 c 1.81426,-1.78095 1.75158,-4.59494 -0.0937,-6.40625 l -6.53125,-6.4375 c 2.33188,-3.93518 4.18421,-8.21502 5.40625,-12.71875 l 9.1875,0 c 2.60961,0 4.75,-2.04398 4.75,-4.5625 l 0,-17.6875 c 0,-2.521252 -2.14217,-4.5625 -4.75,-4.5625 l -9.1875,0 c -1.22511,-4.503724 -3.07441,-8.783573 -5.4063,-12.71875 l 6.53125,-6.4375 c 1.84527,-1.811402 1.90809,-4.625299 0.0937,-6.40625 L 616.9062,44.46875 c -1.81638,-1.780951 -4.68757,-1.71786 -6.53125,0.09375 l -6.5625,6.40625 c -4.00877,-2.289964 -8.38079,-4.081348 -12.96875,-5.28125 l 0,-9.03125 C 590.8437,34.094219 588.78408,32 586.2187,32 l -18.03125,0 z" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.73549545;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 278.52756,109.88905 35.88562,22.42851 -35.8856,22.42851 z"
|
||||
id="path4447-2" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.73549545;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 197.07157,146.50326 67.28641,0 c 2.80964,0 5.07157,3.10892 5.07157,6.97069 0,3.86175 -2.26193,6.97067 -5.07157,6.97067 l -67.28641,0 c -2.80965,0 -5.07157,-3.10892 -5.07157,-6.97067 0,-3.86177 2.26192,-6.97069 5.07157,-6.97069 z"
|
||||
id="path4451-1-9-84" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.73549545;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 200.38389,89.251627 111.23222,0 c 4.64466,0 8.38389,3.10892 8.38389,6.97069 0,3.861753 -3.73923,6.970673 -8.38389,6.970673 l -111.23222,0 c -4.64467,0 -8.38389,-3.10892 -8.38389,-6.970673 0,-3.86177 3.73922,-6.97069 8.38389,-6.97069 z"
|
||||
id="path4451-1-9-84-1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.73549545;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 197.07157,117.87745 67.28641,0 c 2.80964,0 5.07157,3.10892 5.07157,6.97069 0,3.86175 -2.26193,6.97067 -5.07157,6.97067 l -67.28641,0 c -2.80965,0 -5.07157,-3.10892 -5.07157,-6.97067 0,-3.86177 2.26192,-6.97069 5.07157,-6.97069 z"
|
||||
id="path4451-1-9-84-8" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.73549545;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 200.38389,60.625819 111.23222,0 c 4.64466,0 8.38389,3.10892 8.38389,6.97069 0,3.86175 -3.73923,6.97067 -8.38389,6.97067 l -111.23222,0 c -4.64467,0 -8.38389,-3.10892 -8.38389,-6.97067 0,-3.86177 3.73922,-6.97069 8.38389,-6.97069 z"
|
||||
id="path4451-1-9-84-9" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.73549545;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 199.48329,32 112.0697,0 C 316.23262,32 320,35.10892 320,38.97069 c 0,3.86175 -3.76738,6.97067 -8.44701,6.97067 l -112.0697,0 c -4.67964,0 -8.44701,-3.10892 -8.44701,-6.97067 0,-3.86177 3.76737,-6.97069 8.44701,-6.97069 z"
|
||||
id="path4451-1-9-84-0" />
|
||||
</svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 31 KiB |
|
Depois Largura: | Altura: | Tamanho: 37 KiB |
|
Depois Largura: | Altura: | Tamanho: 45 KiB |
|
Depois Largura: | Altura: | Tamanho: 42 KiB |
@@ -0,0 +1,829 @@
|
||||
<?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://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: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="350"
|
||||
height="200"
|
||||
id="svg6462"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="arrow_up_down_darker.svg"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.1 dark/arrow_down.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.6038404"
|
||||
inkscape:cx="111.48148"
|
||||
inkscape:cy="56.488469"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="838"
|
||||
inkscape:window-x="1272"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-global="true" />
|
||||
<defs
|
||||
id="defs6464">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6364"
|
||||
id="linearGradient6370"
|
||||
x1="101.42937"
|
||||
y1="400.5535"
|
||||
x2="99.124153"
|
||||
y2="244.95164"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.340328,0,0,1.340328,-155.22114,-66.380723)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364-8">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366-5" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368-9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="244.95164"
|
||||
x2="99.124153"
|
||||
y1="400.5535"
|
||||
x1="101.42937"
|
||||
gradientTransform="matrix(1.340328,0,0,1.340328,-66.590934,-328.62237)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient6531"
|
||||
xlink:href="#linearGradient6364-8"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="244.95164"
|
||||
x2="99.124153"
|
||||
y1="400.5535"
|
||||
x1="101.42937"
|
||||
gradientTransform="matrix(1.340328,0,0,1.340328,-31.467381,555.95415)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient6460"
|
||||
xlink:href="#linearGradient6364-2"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364-2">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366-7" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368-8" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="244.95164"
|
||||
x2="99.124153"
|
||||
y1="400.5535"
|
||||
x1="101.42937"
|
||||
gradientTransform="matrix(1.340328,0,0,-1.340328,133.5722,1341.1989)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient6421-9"
|
||||
xlink:href="#linearGradient6364-5-9"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6364-5-9">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6366-4-1" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6368-6-9" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
id="filter3970"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3972"
|
||||
stdDeviation="4"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset3974"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite3976"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood3978"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend3980"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite3982"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter3984"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3986"
|
||||
stdDeviation="4"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset3988"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite3990"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood3992"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend3994"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite3996"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:label="Inner Shadow"
|
||||
id="filter3142">
|
||||
<feGaussianBlur
|
||||
result="result8"
|
||||
stdDeviation="4"
|
||||
id="feGaussianBlur3144" />
|
||||
<feOffset
|
||||
result="result11"
|
||||
dy="4"
|
||||
dx="4"
|
||||
id="feOffset3146" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
in="SourceGraphic"
|
||||
result="result6"
|
||||
in2="result11"
|
||||
id="feComposite3148" />
|
||||
<feFlood
|
||||
flood-color="rgb(0,0,0)"
|
||||
flood-opacity="1"
|
||||
in="result6"
|
||||
result="result10"
|
||||
id="feFlood3150" />
|
||||
<feBlend
|
||||
result="result12"
|
||||
in="result6"
|
||||
mode="normal"
|
||||
in2="result10"
|
||||
id="feBlend3152" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
result="result2"
|
||||
in2="SourceGraphic"
|
||||
id="feComposite3154" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:label="Inner Shadow"
|
||||
id="filter3938">
|
||||
<feGaussianBlur
|
||||
result="result8"
|
||||
stdDeviation="4"
|
||||
id="feGaussianBlur3940" />
|
||||
<feOffset
|
||||
result="result11"
|
||||
dy="4"
|
||||
dx="4"
|
||||
id="feOffset3942" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
in="SourceGraphic"
|
||||
result="result6"
|
||||
in2="result11"
|
||||
id="feComposite3944" />
|
||||
<feFlood
|
||||
flood-color="rgb(0,0,0)"
|
||||
flood-opacity="1"
|
||||
in="result6"
|
||||
result="result10"
|
||||
id="feFlood3946" />
|
||||
<feBlend
|
||||
result="result12"
|
||||
in="result6"
|
||||
mode="normal"
|
||||
in2="result10"
|
||||
id="feBlend3948" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
result="result2"
|
||||
in2="SourceGraphic"
|
||||
id="feComposite3950" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:label="Inner Shadow"
|
||||
id="filter3060">
|
||||
<feGaussianBlur
|
||||
result="result8"
|
||||
stdDeviation="4"
|
||||
id="feGaussianBlur3062" />
|
||||
<feOffset
|
||||
result="result11"
|
||||
dy="4"
|
||||
dx="4"
|
||||
id="feOffset3064" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
in="SourceGraphic"
|
||||
result="result6"
|
||||
in2="result11"
|
||||
id="feComposite3066" />
|
||||
<feFlood
|
||||
flood-color="rgb(0,0,0)"
|
||||
flood-opacity="1"
|
||||
in="result6"
|
||||
result="result10"
|
||||
id="feFlood3068" />
|
||||
<feBlend
|
||||
result="result12"
|
||||
in="result6"
|
||||
mode="normal"
|
||||
in2="result10"
|
||||
id="feBlend3070" />
|
||||
<feComposite
|
||||
operator="in"
|
||||
result="result2"
|
||||
in2="SourceGraphic"
|
||||
id="feComposite3072" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4056"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4058"
|
||||
stdDeviation="10"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4060"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4062"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4064"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4066"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4068"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4070"
|
||||
inkscape:label="Darken edges"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Darken the edges with an inner blur"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4072"
|
||||
stdDeviation="10"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4074"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4076"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4078"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4080"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4082"
|
||||
in2="SourceGraphic"
|
||||
result="fbSourceGraphic"
|
||||
operator="in" />
|
||||
<feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix3318" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3320"
|
||||
result="result6"
|
||||
stdDeviation="1.5"
|
||||
in="fbSourceGraphic" />
|
||||
<feComposite
|
||||
in2="result6"
|
||||
id="feComposite3322"
|
||||
operator="atop"
|
||||
in="fbSourceGraphic"
|
||||
result="result8" />
|
||||
<feComposite
|
||||
in2="fbSourceGraphicAlpha"
|
||||
id="feComposite3324"
|
||||
in="result8"
|
||||
operator="atop"
|
||||
result="result9" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4092"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4094"
|
||||
result="result6"
|
||||
stdDeviation="1.5" />
|
||||
<feComposite
|
||||
id="feComposite4096"
|
||||
in2="result6"
|
||||
operator="atop"
|
||||
in="SourceGraphic"
|
||||
result="result8" />
|
||||
<feComposite
|
||||
id="feComposite4098"
|
||||
in2="SourceAlpha"
|
||||
in="result8"
|
||||
operator="atop"
|
||||
result="fbSourceGraphic" />
|
||||
<feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix3076" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3078"
|
||||
stdDeviation="4"
|
||||
result="result8"
|
||||
in="fbSourceGraphic" />
|
||||
<feOffset
|
||||
id="feOffset3080"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite3082"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="fbSourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood3084"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend3086"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite3088"
|
||||
in2="fbSourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4100"
|
||||
inkscape:label="Darken edges"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Darken the edges with an inner blur"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4102"
|
||||
result="result6"
|
||||
stdDeviation="1.5" />
|
||||
<feComposite
|
||||
id="feComposite4104"
|
||||
in2="result6"
|
||||
operator="atop"
|
||||
in="SourceGraphic"
|
||||
result="result8" />
|
||||
<feComposite
|
||||
id="feComposite4106"
|
||||
in2="SourceAlpha"
|
||||
in="result8"
|
||||
operator="atop"
|
||||
result="result9" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4108"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4110"
|
||||
stdDeviation="4"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4112"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4114"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4116"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4118"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4120"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4122"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4124"
|
||||
stdDeviation="4"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4126"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4128"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4130"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4132"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4134"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4056-2"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4058-5"
|
||||
stdDeviation="10"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4060-5"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4062-7"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4064-4"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4066-6"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4068-4"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4070-0"
|
||||
inkscape:label="Darken edges"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Darken the edges with an inner blur"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4072-1"
|
||||
stdDeviation="7"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4074-2"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4076-8"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4078-2"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4080-9"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4082-1"
|
||||
in2="SourceGraphic"
|
||||
result="fbSourceGraphic"
|
||||
operator="in" />
|
||||
<feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix3318-4" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3320-2"
|
||||
result="result6"
|
||||
stdDeviation="1.5"
|
||||
in="fbSourceGraphic" />
|
||||
<feComposite
|
||||
in2="result6"
|
||||
id="feComposite3322-1"
|
||||
operator="atop"
|
||||
in="fbSourceGraphic"
|
||||
result="result8" />
|
||||
<feComposite
|
||||
in2="fbSourceGraphicAlpha"
|
||||
id="feComposite3324-7"
|
||||
in="result8"
|
||||
operator="atop"
|
||||
result="result9" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter4056-0"
|
||||
inkscape:label="Inner Shadow"
|
||||
inkscape:menu="Shadows and Glows"
|
||||
inkscape:menu-tooltip="Adds a colorizable drop shadow inside"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4058-2"
|
||||
stdDeviation="7"
|
||||
result="result8" />
|
||||
<feOffset
|
||||
id="feOffset4060-8"
|
||||
dx="4"
|
||||
dy="4"
|
||||
result="result11" />
|
||||
<feComposite
|
||||
id="feComposite4062-72"
|
||||
in2="result11"
|
||||
result="result6"
|
||||
in="SourceGraphic"
|
||||
operator="in" />
|
||||
<feFlood
|
||||
id="feFlood4064-7"
|
||||
result="result10"
|
||||
in="result6"
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(0,0,0)" />
|
||||
<feBlend
|
||||
id="feBlend4066-4"
|
||||
in2="result10"
|
||||
mode="normal"
|
||||
in="result6"
|
||||
result="result12" />
|
||||
<feComposite
|
||||
id="feComposite4068-6"
|
||||
in2="SourceGraphic"
|
||||
result="result2"
|
||||
operator="in" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter3894">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="1.6297979"
|
||||
id="feGaussianBlur3896" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:collect="always"
|
||||
id="filter3894-7">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="1.6297979"
|
||||
id="feGaussianBlur3896-1" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter3954">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="1.6259235"
|
||||
id="feGaussianBlur3956" />
|
||||
</filter>
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
inkscape:collect="always"
|
||||
id="filter3954-0">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="1.6259235"
|
||||
id="feGaussianBlur3956-0" />
|
||||
</filter>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata6467">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-852.36218)">
|
||||
<g
|
||||
id="g3167"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.1 dark/arrow_down.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<rect
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.0 New light/arrow_down.png"
|
||||
y="891.19916"
|
||||
x="14.282172"
|
||||
height="128"
|
||||
width="128"
|
||||
id="rect3927"
|
||||
style="opacity:0.54878049;color:#000000;fill:none;stroke:none;stroke-width:0.99577111;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.0 New light/arrow_down.png"
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect5581"
|
||||
d="m 43.063434,943.80829 c 0,0 21.264134,21.26406 31.896202,31.89608 2.676746,2.5683 3.929655,2.61211 6.612848,0.0322 10.64281,-10.64277 21.285616,-21.28554 31.928426,-31.92831 l -11.06099,-11.06109 -24.157746,24.1577 -24.157752,-24.1577 z"
|
||||
style="color:#000000;fill:#2c2c2c;fill-opacity:1;fill-rule:nonzero;stroke:#333333;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
id="g3171"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.1 dark/arrow_up.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<rect
|
||||
y="884.42499"
|
||||
x="191.87073"
|
||||
height="128"
|
||||
width="128"
|
||||
id="rect3987"
|
||||
style="opacity:0.54878049;color:#000000;fill:none;stroke:none;stroke-width:1.32088256;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-filename="/home/jrbastien/Ubuntu One/CoverArt/1.0 New light/arrow_down.png"
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect5581-78"
|
||||
d="m 291.08947,959.81577 c 0,0 -21.26414,-21.2641 -31.89621,-31.8961 -2.67674,-2.5683 -3.92965,-2.6121 -6.61284,-0.032 -10.64281,10.6428 -21.28562,21.2856 -31.92843,31.9284 l 11.06099,11.061 24.15775,-24.1577 24.15775,24.1577 z"
|
||||
style="color:#000000;fill:#2c2c2c;fill-opacity:1;fill-rule:nonzero;stroke:#333333;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Depois Largura: | Altura: | Tamanho: 24 KiB |
|
Depois Largura: | Altura: | Tamanho: 109 KiB |
|
Depois Largura: | Altura: | Tamanho: 43 KiB |
|
Depois Largura: | Altura: | Tamanho: 119 KiB |
|
Depois Largura: | Altura: | Tamanho: 138 KiB |
|
Depois Largura: | Altura: | Tamanho: 39 KiB |