Comparar commits

...

554 Commits

Autor SHA1 Mensagem Data
David Mohammed 0d2c984564 use $HOME rather than $USER for those users who's home is not home 2015-01-06 21:06:39 +00:00
David Mohammed 3bf1747540 Update README.md 2014-12-09 15:14:16 +00:00
fossfreedom c72e2e5ca5 add latest bg translation 2014-08-25 17:03:27 +01:00
David Mohammed ecb4d48624 release v2.0 2014-07-17 21:11:20 +01:00
fossfreedom bc46b63133 fix links icons in global installation 2014-07-16 21:58:34 +01:00
fossfreedom 37510a762c fix global darker theme install and missing css file 2014-07-15 21:49:34 +01:00
fossfreedom 2d6c2a5722 corrected call from makefile to ensure translation build does not fail 2014-07-15 21:07:28 +01:00
fossfreedom eb562ed4e9 fixed makefile install for translations 2014-07-15 20:38:15 +01:00
fossfreedom 4058056b70 adjust readme for release info 2014-07-12 00:24:48 +01:00
fossfreedom a9fe7ddd27 release info in plugin files 2014-07-12 00:21:38 +01:00
fossfreedom ac52161047 latest readme 2014-07-12 00:19:35 +01:00
fossfreedom e2803df857 Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2014-07-12 00:00:30 +01:00
fossfreedom 8aa2e7105e updated coverart_artistinfo icons as per jrbastiens recommendations - issue #317 2014-07-12 00:00:08 +01:00
fossfreedom f968221bff new majority translation - ru 2014-07-11 13:48:31 +01:00
fossfreedom 90b4bf31f3 latest translation - ms 2014-07-11 07:10:15 +01:00
fossfreedom 49b355b8cf latest ko translation and run and update_all 2014-07-08 08:12:11 +01:00
fossfreedom edfd24bbd3 some fixups when adding and deleting tracks 2014-07-06 22:59:49 +01:00
fossfreedom c5042bdc57 amend readme 2014-07-06 13:00:00 +01:00
fossfreedom e6c650d7b8 replace views label with an ellipsis - issue #328 2014-07-06 12:58:20 +01:00
fossfreedom 52e3e7e2ef latest translations 2014-07-05 22:01:41 +01:00
fossfreedom 82558792b5 latest translations and remove translations where no longer majority translated 2014-07-04 19:49:40 +01:00
fossfreedom e0e5e5b812 reduce install to a users locale or if it doesnt exist then default to en_US - issue #327 2014-07-03 21:16:33 +01:00
fossfreedom 31041fa39a rework coverart display to overcome perceived GTK scrollwindow resizing bug when policy is usually set to NEVER to hide the scrollwindow scrollbars - issue #325 2014-07-03 20:41:05 +01:00
fossfreedom 1dcbc4ce07 latest translations 2014-07-01 23:03:22 +01:00
fossfreedom 003b10afa6 change entryview compact image from AspectFrame to Frame - this gives the image better balance vertically 2014-06-30 23:06:43 +01:00
fossfreedom c1fbb27b0c latest fr_CA translation 2014-06-30 12:28:31 +01:00
fossfreedom 657abe17fb update readme to reflect localisation - issue #319 2014-06-29 19:50:34 +01:00
fossfreedom ba5d9e139a add internationalization on lastfm results - issue #319 2014-06-29 19:41:42 +01:00
fossfreedom d345e75952 latest de translation 2014-06-28 23:29:18 +01:00
fossfreedom 0f20559e2f latest pt_BR translation 2014-06-28 22:11:23 +01:00
fossfreedom 5977335253 latest translations from launchpad 2014-06-28 21:44:37 +01:00
fossfreedom 6d5be5812a delay cover_size update slightly to improve usability 2014-06-28 15:18:45 +01:00
fossfreedom 5c20b3bdcc readme update 2014-06-28 10:54:57 +01:00
fossfreedom 17c871897e cleanup unneeded icons in source base 2014-06-28 10:27:28 +01:00
fossfreedom 8947aebe48 reversed shadow cover hover icons - prefer the standard white icons 2014-06-28 10:25:44 +01:00
fossfreedom 802cd5a36a various cleanups and fix display of entry-pane coverart if artist info is displayed and the entry-view is opened for the first time 2014-06-28 10:18:58 +01:00
fossfreedom 115a652a71 use more solid hover icons when covers have shadow effect 2014-06-26 21:36:12 +01:00
fossfreedom 2148fd428a corrected hover icon calculation to take into account icon spacing and padding correctly - issue #316 2014-06-26 21:11:18 +01:00
fossfreedom 9c90b0b8bb add missing files and add the alternative hover icon set 2014-06-25 23:27:14 +01:00
fossfreedom e10a75945a revamped single click icons - issue #300 2014-06-25 23:09:33 +01:00
fossfreedom b1837365a2 add ability to see and adjust what is playing - issue #296 2014-06-25 22:53:49 +01:00
fossfreedom d9dc24447c latest es and fr_CA translations - issue #288 2014-06-22 14:45:10 +01:00
fossfreedom b35f4b5615 add missing imports - issue #288 2014-06-22 10:33:02 +01:00
fossfreedom ad04ae14dd remove bool error and regen locales to capture extra message - issue #288 2014-06-22 10:30:40 +01:00
fossfreedom 8392648ffe fix propagation issues for areas that respond to button_release events - the idea being that button_release events must have a corresponding button_press event otherwise the call is invalid and comes from somewhere else - issue #298 2014-06-20 21:08:49 +01:00
fossfreedom fd07433c87 Merge remote-tracking branch 'origin/master' 2014-06-20 17:26:45 +01:00
fossfreedom a78ad58de5 fix issue with track artist filter opening when clicking on artist info panes - issue #309 2014-06-20 17:26:12 +01:00
fossfreedom 052df42b29 add missing queued to playing notification message - issue #288 2014-06-20 13:09:04 +01:00
fossfreedom cd3847ba67 latest fr_CA from transifex 2014-06-20 09:16:42 +01:00
David Mohammed cabc112d1c Merge pull request #310 from jrbastien/master
Updated monochrome coverart browser icon and original design files
2014-06-20 08:46:57 +01:00
jrbastien cfde5a42b4 Changing the monochrome coverart browser icon for the left tool bar and adding the original design files as per discussion in issue #300. 2014-06-19 21:25:37 -04:00
fossfreedom 72710425e5 latest fr_CA and it translations - issue #299 2014-06-19 20:24:32 +01:00
fossfreedom 606bb0d065 fix blink display of single click icon if moving the mouse fast between cells 2014-06-18 23:50:36 +01:00
fossfreedom 7ec7ff72e3 stop inadvertent refresh of tile display due to setting of the display text radio button on first load - issue #308 2014-06-18 19:58:39 +01:00
fossfreedom b6dd370470 new entryview icon - issue #300 2014-06-18 19:16:35 +01:00
fossfreedom 5b23026ae8 better spacing in flow appearance dialog - issue #266 2014-06-18 19:13:28 +01:00
fossfreedom e71656aeb3 fix locale display issues with the coverart info panes - issue #299 2014-06-17 20:06:00 +01:00
fossfreedom 67b5575fb4 latest it.po translation 2014-06-16 21:14:27 +01:00
fossfreedom 0a71517161 add and remove some debug trying to track down issue #307 2014-06-15 10:34:10 +01:00
fossfreedom 5735d6d6f3 added some more translator hints and ensure that these comments are correctly extracted - issue #299 2014-06-14 23:21:33 +01:00
fossfreedom c98881b676 latest translations from release 1.1 and update config files to pull the latest translation items from the source files - issue #299 2014-06-14 12:14:33 +01:00
fossfreedom 7806c91c86 incorporated recommendations from mgratton to resolve focus crashes - issue #305 2014-06-12 23:40:28 +01:00
fossfreedom a34ebbd3db better vertical pane handles - simple gradient with a smaller size. Works with dark themes and standard themes such as adwaita and ambiance 2014-06-10 21:41:03 +01:00
fossfreedom 635afa73e5 completely rewrite single click capability - issue #288 2014-06-09 22:34:40 +01:00
fossfreedom ee5b1a19ea ignore ALT-Left key to summons the quick search - issue #305 2014-06-08 09:43:28 +01:00
fossfreedom cb3b67991b replicated auto-open capability for track artist pane for artist info pane 2014-06-07 22:40:59 +01:00
fossfreedom 1504c90b4d stop using child allocated width and just use the paned position #298 2014-06-07 17:56:37 +01:00
fossfreedom 9a8efff960 more debug info to track down issue #298 2014-06-07 09:59:58 +01:00
fossfreedom 9068149d07 Merge remote-tracking branch 'origin/master' 2014-06-07 07:17:42 +01:00
fossfreedom 4decb6c260 add notification feedback that an album has been queue when single click append has been chosen - issue #288 2014-06-07 07:17:21 +01:00
David Mohammed 8303145003 Update README.md 2014-06-06 08:44:59 +01:00
fossfreedom 039a772795 fix local genre error on playing - issue #303 2014-06-06 00:08:40 +01:00
fossfreedom 84f34bcf18 hide whatplayingicon correctly 2014-06-05 21:43:53 +01:00
fossfreedom c766a4dedc fix locale tooltip for All Genres - issue #303 2014-06-05 21:37:42 +01:00
fossfreedom 4fe43a950f make the highlight a little more stylish - issue #298 2014-06-05 20:58:28 +01:00
fossfreedom 437dc66cf7 add highlight for the vertical panes to indicate that something can be selected - issue #298 2014-06-05 20:18:17 +01:00
fossfreedom d4e172aafb add highlight for the vertical panes to indicate that something can be selected - issue #298 2014-06-05 20:17:40 +01:00
fossfreedom 28a8c346c7 remove bottom display hiding option - issue #302 2014-06-04 19:45:00 +01:00
fossfreedom a4c8d23fbb fix for preferences button from plugins - issue #301 2014-06-04 19:38:44 +01:00
fossfreedom d35f173453 prelim stuff for displaying queue tracks - issue #296 2014-06-04 19:35:27 +01:00
fossfreedom 3a9589074f run pycharms optimize imports over the python modules in the project 2014-06-03 20:04:38 +01:00
David Mohammed 8cf80c99bd Update README.md 2014-06-03 17:39:25 +01:00
David Mohammed 0bbde2077c Update README.md 2014-06-03 16:30:56 +01:00
fossfreedom 519fb78c84 general cleanup - remove old rb2 code that is no longer applicable 2014-06-02 20:31:26 +01:00
fossfreedom 2d828b4587 Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2014-06-02 00:18:31 +01:00
fossfreedom 0dd34ca8f3 missing file for entryview smallwindow support 2014-06-02 00:17:56 +01:00
fossfreedom 2d6bcd02b6 add missing file for compact view 2014-06-01 23:26:18 +01:00
fossfreedom 5fa4fd391e latest readme 2014-05-26 14:08:38 +01:00
fossfreedom 535059df62 add uninstall for coverart-browser - issue #232 2014-05-26 14:04:12 +01:00
fossfreedom 6f10706ac1 support smallwindow plugin - issue #295 2014-05-25 00:13:14 +01:00
fossfreedom a5a3d6b85c reformat code according to pycharm 2014-05-24 14:52:09 +01:00
fossfreedom cae74bf6e7 entryview add-to-playing menu item. Also have only one query model for the entire source rather than as before seperate query models for entry views and main source - issue #288 2014-05-24 00:10:19 +01:00
fossfreedom 08b979fa0a entryview add-to-playing menu item. Also have only one query model for the entire source rather than as before seperate query models for entry views and main source - issue #288 2014-05-23 23:52:40 +01:00
fossfreedom 7a20522c2f view add-to-playing menu item - issue #288 2014-05-23 19:54:11 +01:00
fossfreedom 8243b2ed34 single click queue adds to playing source - issue #288 2014-05-22 23:47:28 +01:00
fossfreedom 1ea5d3dd67 Add Views button to Play Queue and and Play Queue within the views button - issue #294 2014-05-21 21:37:05 +01:00
fossfreedom 4c2ef51454 latest README updates 2014-05-21 19:50:15 +01:00
fossfreedom c7696d412c slightly delay filter whilst typing - issue #293 2014-05-21 19:26:42 +01:00
fossfreedom 82adb4653d better spacing of the coverart - issue #291 2014-05-19 22:11:25 +01:00
fossfreedom 41e80ee47b various fixups part 2 - issue #291 2014-05-19 21:28:09 +01:00
fossfreedom 87ea90d054 various fixups - issue #291 2014-05-19 21:05:54 +01:00
fossfreedom ec24905ed0 update README with the latest information 2014-05-18 23:48:35 +01:00
fossfreedom 1758a56ef2 refactored track pane code issue #291 2014-05-18 23:32:33 +01:00
fossfreedom 934606eb2f fix for autosizing problem in compact view issue #289 2014-05-18 10:39:53 +01:00
fossfreedom 043790eda2 add follow song option to properties menu together with its implementation issue #278 2014-05-18 08:41:21 +01:00
fossfreedom eed81c45a1 complete stack conversion for artist view issue #287 2014-05-17 23:49:45 +01:00
fossfreedom edf995395a change display of cover to be a stack to give it an animation effect when changing the selection - issue #289 2014-05-10 23:49:23 +01:00
fossfreedom e12d09e52e cleanup and use scrolledwindow to display image rather than custom draw - issue #289 2014-05-10 21:23:31 +01:00
fossfreedom 0ec0cd8f75 replace notebook with GtkStack - issue #289 2014-05-09 22:36:54 +01:00
fossfreedom 473b656412 ignore pycharms idea files 2014-05-05 20:33:31 +01:00
fossfreedom 22c0b68add its not unusual to not be returned similar tracks for a given search - lets reduce the display of the info box to real errors being returned from the provider 2014-05-04 11:08:56 +01:00
fossfreedom 8edf61af6a add similar genre playlist 2014-05-04 10:54:59 +01:00
fossfreedom e8aad1c034 remember the setting of the entry view mode as well as making the menu signals unique for each entry view. We need to do this otherwise clicking on a menu option will invoke the method in the wrong entry view class - e.g. SongInfo dialog fails to display in compact view mode because the signal being invoked is the full entry view class. 2014-05-03 23:16:09 +01:00
fossfreedom 4091c9be50 fix closure of artist info where the icons confused the width calculation 2014-05-03 18:38:07 +01:00
fossfreedom d2be6895f0 some cleanup 2014-05-02 23:49:42 +01:00
fossfreedom 52b8588f3f add initial capability for compact vs full entry view mode - issue #289 2014-05-02 22:43:07 +01:00
fossfreedom e7669d3117 attempt to redraw correctly to improve appearance of icon - issue #285 2014-04-17 00:23:48 +01:00
fossfreedom 1804a55426 single click queue - issue #288 2014-04-17 00:09:00 +01:00
fossfreedom b514740e19 add similar playlist capability - issue #258 2014-04-14 22:24:44 +01:00
David Mohammed d39e964bc5 Update README.md 2014-04-04 21:57:09 +01:00
fossfreedom c7f6281e11 fix locale display of window title - issue #284 2014-04-04 21:34:37 +01:00
fossfreedom 4afc22c686 add filter by composer 2014-03-29 00:28:14 +00:00
fossfreedom fb64f74663 copy coverart_rb3compat module from release1.1 2014-03-28 21:50:44 +00:00
fossfreedom 3896c62844 fix search placement so that it correctly moves when rhythmbox window is resized 2014-03-28 21:42:38 +00:00
David Mohammed 52033cb0a9 Update README.md 2014-03-22 10:05:02 +00:00
fossfreedom 48c21be900 lets remember the last genre folder chosen - issue #215 2014-03-22 10:00:58 +00:00
fossfreedom 72a903992d Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2014-03-22 09:35:31 +00:00
fossfreedom f8351aadb4 lets save custom user icon info in the cache folder not the plugin folder so that it survives a reinstall - issue #215 2014-03-22 09:35:07 +00:00
David Mohammed 29da8eda3e Update README.md 2014-03-22 00:17:33 +00:00
fossfreedom b202684e0a boost artistinfo with echonest biography - issue #272 2014-03-21 23:50:55 +00:00
fossfreedom 873571f1ab add filter buttons to artist info to allow filtering by similar artist - issue #279 2014-03-17 21:31:41 +00:00
fossfreedom 48342cdd18 prettify export dialog - issue #266 2014-03-10 23:43:49 +00:00
fossfreedom 90e02345fb prettify the browser plugin preferences - issue #266 2014-03-10 21:57:41 +00:00
fossfreedom b48731ed6a cleanup 2014-03-09 23:10:31 +00:00
fossfreedom 870b4cdd7b rework jump to playing so that all views are correctly scrolled to - issue #278 2014-03-09 23:09:46 +00:00
fossfreedom ecfdc66706 Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2014-03-09 18:53:19 +00:00
fossfreedom aa8d23e65b fix focus issues so that we don't jump back to the plugin unless we started playing from the plugin - issue #278 2014-03-09 18:52:54 +00:00
David Mohammed 5013de9127 Update README.md 2014-03-09 11:54:10 +00:00
fossfreedom 0c0d4d6c57 add support for JumpToPlaying song shortcut - issue #278 2014-03-09 11:43:36 +00:00
fossfreedom 9da85017b9 manually apply #277 patch 2014-03-06 18:31:31 +00:00
fossfreedom 4174f71436 fix track artist filter display on startup if closed 2014-02-15 22:54:53 +00:00
fossfreedom 3088768fe6 some tidyups 2014-02-15 21:24:11 +00:00
fossfreedom acb6caaba0 wrong override caused failure to check lastfm plugin presence in artist view - issue #264 2014-02-15 00:29:54 +00:00
fossfreedom 8619d73007 fix 14.04 playlists + openfolder plugin support - issue #263 2014-02-14 22:54:33 +00:00
fossfreedom 18666de36f change some of the defaults for new users 2014-02-05 23:53:23 +00:00
fossfreedom e9af41d634 rework track artist filter to mirror the artist info pane - issue #271 2014-02-05 00:02:21 +00:00
fossfreedom 9763743a95 snap shut the artist paned if too small to visually see anything useful - issue #268 2014-02-04 19:46:58 +00:00
fossfreedom b6ffa2de70 update README 2014-02-04 00:07:51 +00:00
fossfreedom 74adbe6c3f transfer darker stuff from popups.xml to popups.xml.in so that it is not overwritten when we run the translation stuff 2014-02-04 00:06:02 +00:00
fossfreedom fd42d4e601 Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2014-02-04 00:03:11 +00:00
fossfreedom 0b97a39edc add artist-info-pane implementation - issue #268 2014-02-04 00:03:01 +00:00
David Mohammed 23e2ed5297 Merge pull request #270 from jrbastien/master
Fine tuning of the lighter theme and added new darker theme.
2014-02-03 15:17:06 -08:00
jrbastien 273841ec65 Fine tuning of the lighter theme and added new darker theme. 2014-02-02 19:29:25 -05:00
fossfreedom d128149d8d this is now a python3 only install - remove the old python2 installation stuff 2014-01-26 22:01:39 +00:00
fossfreedom 9cdf49e975 fix rb2 encoding issue with last commit - issue #262 2014-01-22 21:40:49 +00:00
fossfreedom 74319826d2 correct action_name to be valid in RB3 - issue #262 2014-01-22 21:33:16 +00:00
fossfreedom afea82eee5 use rb3compat functions - issue #257 2014-01-22 20:30:24 +00:00
fossfreedom dda323ac04 fix crash for album titles that have unicode characters - issue #257 2014-01-22 20:20:23 +00:00
fossfreedom a09a25690c fix crash for non-english locales where artist is not translated by the plugin 2014-01-22 18:10:09 +00:00
fossfreedom f27ee2464c replace tabs with spaces 2014-01-20 23:59:04 +00:00
fossfreedom 18aaf08f4b fix sorting of artist view after album information such its rating has been changed - issue #257 2014-01-20 23:14:28 +00:00
fossfreedom c03166007f fix boundary issues which caused crash when moving albums to the end of the view - issue #259 2014-01-20 23:06:56 +00:00
fossfreedom 0c66334569 latest sprite image - issue #240 2014-01-20 09:11:34 +00:00
fossfreedom 1e88bab104 latest bg translation 2014-01-19 20:23:46 +00:00
fossfreedom b2eabeb8eb fix sorting issue after restart together with scroll sync issue between artist and tile view - issue #257 2014-01-19 19:46:33 +00:00
fossfreedom d93ea16d1a fix for float issues in earlier versions of rhythmbox - issue #256 2014-01-18 21:22:22 +00:00
fossfreedom ac321f7815 update README for beta 3 release 2014-01-18 14:43:05 +00:00
fossfreedom c53e6c33f8 scale tooltip to original image dimensions - issue #256 2014-01-18 14:35:15 +00:00
fossfreedom 368dda444b latest translations 2014-01-18 14:02:54 +00:00
fossfreedom d2640cf11a latest translations 2014-01-16 22:50:23 +00:00
fossfreedom b56ec0e5d9 reorder the album when the sort keys change - issue #254 2014-01-16 21:34:45 +00:00
fossfreedom 5d0d513f93 fix trusty icon offset issue 2014-01-15 23:57:53 +00:00
fossfreedom 914098f4f4 fix trusty spacing issues 2014-01-15 22:54:43 +00:00
fossfreedom 16beb62e9c fix display of icons in trusty - issue #253 2014-01-15 22:00:29 +00:00
fossfreedom c1eb1d279e redisplay pictures in iconview 2014-01-15 21:44:13 +00:00
fossfreedom f9ab0104cd remove depreciation of dialog creation 2014-01-15 20:46:44 +00:00
fossfreedom 1a7e154f64 more depreciation this time with GObject.idle_add 2014-01-15 20:16:02 +00:00
fossfreedom 4cfe692b9e fix various depreciations in trusty 2014-01-15 19:58:19 +00:00
fossfreedom d165f5fc0c updated README for beta 2 2014-01-14 21:50:24 +00:00
fossfreedom 06a7478c70 latest translations 2014-01-14 21:23:10 +00:00
fossfreedom 7d629e5bcb add a space after labels in export dialog - issue #248 2014-01-14 21:11:19 +00:00
fossfreedom 5ddf0b306c resolve misaligned sorting issues - issue #250 2014-01-14 20:46:30 +00:00
fossfreedom ade9939053 rerun translation extraction 2014-01-13 21:50:19 +00:00
fossfreedom e6f8c887c9 Merge branch 'sort'
Conflicts:
	po/fr_CA.po
2014-01-13 21:35:58 +00:00
fossfreedom db09860d08 add new sprites, fix sorting of artists column so that we cannot become unsorted and finally, fix a bug on startup showing sort key error 2014-01-13 21:33:41 +00:00
fossfreedom 1718296e46 swap sort keys for album artist and album name so that we can use those sort keys correctly - issue #249 2014-01-12 21:56:14 +00:00
fossfreedom f5a6b56c3a latest cs translation 2014-01-12 12:37:25 +00:00
fossfreedom 53ff1990d2 add new cs translation 2014-01-11 23:18:52 +00:00
fossfreedom 4e5929237f tidied up sort actions 2014-01-11 22:52:13 +00:00
fossfreedom f1f4f451b8 Merge branch 'master' into sort
Conflicts:
	po/fr_CA.po
2014-01-11 12:03:32 +00:00
fossfreedom 581c1b6c0c work in progress - connect artist sort buttons and sort viewable albums 2014-01-11 12:01:33 +00:00
fossfreedom 2cafad60b6 use the correct translator comments for px - issue #248 2014-01-10 00:14:43 +00:00
fossfreedom 1cd75c4664 give new artist icons its own config called sort_artist 2014-01-09 23:51:38 +00:00
fossfreedom 161997c0d0 use separate sort and sort order buttons for album and artist views and connect signals for these buttons to sort independently 2014-01-08 23:26:34 +00:00
fossfreedom cc32904e80 latest fr_CA translation 2014-01-08 14:54:11 +00:00
fossfreedom c0edd4895e resolve out of synch picture popup - issue #244 2014-01-07 21:53:03 +00:00
fossfreedom f9dfa0c39d add latest fr_CA translation 2014-01-05 23:42:49 +00:00
fossfreedom 7eaeebf168 set the default sort indicator on the artist sort column to be ascending - issue #245 2014-01-05 23:08:09 +00:00
fossfreedom 290f06981e rerun translation stuff to capture new lastfm translation 2014-01-05 16:05:37 +00:00
fossfreedom 87de8b9a8b check if valid lastfm connection before searching - issue #243 2014-01-05 12:25:43 +00:00
fossfreedom 7a233c2dbb display artist albums ordered by year + their name rather than the current random order - issue #241 2014-01-05 11:18:28 +00:00
fossfreedom 931135ba70 remove secondary image update for disabled toolbar icons - issue #240 2014-01-05 10:23:31 +00:00
fossfreedom adba91d077 fix shake in treeview caused by expander lines - need to add space in next column to allow the expander lines to float into - issue #239 2014-01-05 00:13:17 +00:00
fossfreedom 466112068a encode unicode string to fix crash when clicking on artist - issue #238 2014-01-04 22:57:50 +00:00
fossfreedom 767e2791cf tidied up clicking on row actions to correct display of track & cover pane together with ensure that we show the artist cover search when clicking on artists - issue #236 2014-01-04 09:00:27 +00:00
fossfreedom f60bf048b2 latest es.po 2014-01-03 23:21:42 +00:00
fossfreedom 006d621327 add english language locales 2014-01-03 21:34:09 +00:00
fossfreedom 03b01b58f2 ensure translation of Views button works correctly 2014-01-03 21:17:54 +00:00
fossfreedom e915b353cc translation clarifications 2014-01-03 04:39:00 +00:00
fossfreedom cf8e2b383e version and help info moved to v1.0 2014-01-02 11:02:31 +00:00
fossfreedom 272127f5a3 make sure we copy the plugin3 file to allow the POSTINST script to run in the rb3 debian package 2014-01-01 21:12:55 +00:00
fossfreedom d4f0e9212a corrected version and source icon display for rb3 2014-01-01 20:40:42 +00:00
fossfreedom 78546f3643 re-run translation stuff to upload to launchpad 2014-01-01 15:31:00 +00:00
David Mohammed e1cd035095 Update README.md 2014-01-01 00:56:59 +00:00
fossfreedom 07aca0cdf6 redo deletion of artists when there is no albums - this time lets do stuff simply - just look at the iters we remembered when adding the albums to artists - issue #209 2013-12-28 22:05:30 +00:00
fossfreedom 7b96b47a6c correctly rename album artist and update the artist model - issue #209 2013-12-28 19:20:14 +00:00
fossfreedom d3654e1457 bug fix crash when modifying album in artist view 2013-12-28 17:31:04 +00:00
fossfreedom 98045cae32 blank expander column allows clicking on artist cover - issue #209 2013-12-28 15:15:26 +00:00
fossfreedom 50ae5a2a99 remove export and reduce search to just the artist - issue #209 2013-12-28 12:11:01 +00:00
fossfreedom 0ca674fb7b add right click menu for artists - issue #209 2013-12-28 11:50:47 +00:00
fossfreedom 0ed6f0e3ec tidied up permissions and reduce spacing in carousel to improve look 2013-12-27 17:09:11 +00:00
fossfreedom ed1d8899be add lighter icons to the Makefile 2013-12-27 16:27:15 +00:00
fossfreedom 0c8d408688 disable flowview if webkit support is disabled 2013-12-27 09:02:16 +00:00
fossfreedom d67a802b3d updated readme 2013-12-27 08:57:50 +00:00
fossfreedom 51c05b6202 add xingmux for accurate bitrate resampling 2013-12-27 00:40:41 +00:00
fossfreedom 2a098b1047 copy po's from release 0.9 2013-12-23 00:24:24 +00:00
fossfreedom 5effd50acd latest translation updates 2013-12-23 00:19:14 +00:00
fossfreedom 729d7f1ff0 sync artist view with the other views so that the artist last selected in the other views is scrolled to correctly 2013-12-22 23:50:40 +00:00
fossfreedom 47faf9a509 reflect album name changes back into the artist view. Also took the opportunity to fix a bug specific to RB3 to ensure all track changes are correctly updated in the album-model - issue #209 2013-12-20 18:20:24 +00:00
fossfreedom 6afe9bbed5 remove naff try except by using arrays rather than generators 2013-12-18 23:35:16 +00:00
fossfreedom 6bb5f885bb bug fix when calculating album year - ignore tracks where the year is zero ... this can cause the year to be the current date because the min value returns zero rather than the min of real track years 2013-12-18 23:10:11 +00:00
fossfreedom f763b00f3a cope with locales in markup - issue #209 2013-12-18 16:45:04 +00:00
fossfreedom 7d903e84cf format album names for artist view - issue #209 2013-12-18 16:38:59 +00:00
fossfreedom 7cbf51d168 update README for toolbar changes 2013-12-18 00:06:05 +00:00
fossfreedom 4a1443cf66 link our plugin menu in the music library up with our plugin - issue #230 2013-12-16 23:55:21 +00:00
fossfreedom 7a45d9531e switch to music library source when requested from the plugin view button - issue #230 2013-12-15 16:16:22 +00:00
fossfreedom b1544a8983 temporary fix to prevent crash for RB2.96 2013-12-15 00:12:02 +00:00
fossfreedom 1ff243df66 Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-12-14 23:59:09 +00:00
fossfreedom 9076627ca9 rework toolbars to be RB3 visually compatible with popups placed below the buttons and themed accordingly. Also taken the opportunity to redo the right toolbar to fit on one less line since this sidebar is often used with lyrics which is wider and thus offers more space. Preliminary views button created for library source although not connected as yet. issue #230 2013-12-14 23:58:21 +00:00
fossfreedom 49d9540f8c 26 languages not 22 in the README 2013-12-07 21:24:46 +00:00
fossfreedom 5d1e68c268 more readme changes 2013-12-07 21:09:20 +00:00
fossfreedom 4692c6b8ee add rb2 support for repeat one song - issue #231 2013-12-07 20:52:53 +00:00
fossfreedom f34fd79952 revert plugin loader 2013-12-07 20:16:04 +00:00
fossfreedom 295ee80351 add rb3 menu item for repeat one song - issue#231 2013-12-07 20:15:05 +00:00
fossfreedom a508e52f0d latest README for changes 2013-12-07 17:20:43 +00:00
fossfreedom 2bda0f1cb0 reduce list of target to just uris - issue #233 2013-12-07 17:12:21 +00:00
fossfreedom 74f37075e5 cleanup 2013-12-07 15:08:18 +00:00
fossfreedom 88821ef68a drag-drop support for albums in artist view 2013-12-07 14:57:13 +00:00
fossfreedom 677855e5c7 fix cancel mechanism for artist search 2013-12-07 00:24:07 +00:00
fossfreedom d593463a25 cleanup 2013-12-06 19:39:16 +00:00
fossfreedom 66070a6b0e cleanup 2013-12-03 23:06:35 +00:00
fossfreedom 66b4895458 rework to use new coverartextdb 2013-12-02 21:49:02 +00:00
fossfreedom 2f6af4fa7a use coverview for artists as well as for albums 2013-11-24 21:19:00 +00:00
fossfreedom 80eefa8737 expand or collapse artist on single click 2013-11-23 13:27:41 +00:00
fossfreedom 5fa51b6ed3 allow drag-drop from coverview and also autoexpand when clicking on artist 2013-11-22 22:54:31 +00:00
fossfreedom 4bdd1b4809 show artist cover in a enlarged tooltip 2013-11-22 18:55:48 +00:00
fossfreedom 0c65a494d6 use download covers menu option to download artist covers 2013-11-21 22:48:50 +00:00
fossfreedom f0acad9dca also support album cover update for drag and drop events 2013-11-20 23:21:40 +00:00
fossfreedom 10b4c152c4 support drag and drop of pictures onto artists 2013-11-20 20:29:33 +00:00
fossfreedom 1eab887896 fire the load of the artists after the album model has loaded so that the artists view is correctly initialised 2013-11-17 13:00:58 +00:00
fossfreedom 616ccb2d53 add standard right-click menu for albums 2013-11-17 09:42:40 +00:00
fossfreedom 8b5e234cd2 link filters to artists so that they show or hide artists in the treeview 2013-11-16 10:28:31 +00:00
fossfreedom dfc0002a2c some cleanups 2013-11-13 21:54:30 +00:00
fossfreedom 111147ca2a remove unneeded file 2013-11-13 20:52:22 +00:00
fossfreedom 297378349c change view to be an album-artists view 2013-11-13 20:51:51 +00:00
fossfreedom 0678179585 convert adding of artists as iterators to improve visual appearance when loading 2013-11-12 22:55:51 +00:00
fossfreedom a03119ef29 disable rather than hide toolbar objects 2013-11-11 23:11:51 +00:00
fossfreedom 66ddba7d78 remove unnecessary file 2013-11-11 00:10:22 +00:00
fossfreedom 4a23b78816 update toolbar signal whenever view is initialised or moved to 2013-11-11 00:09:53 +00:00
fossfreedom 07273d8351 remove obsolete file 2013-11-08 23:50:35 +00:00
fossfreedom 1dc678f31f refactor toolbar stuff into its own module 2013-11-08 23:50:09 +00:00
fossfreedom 64f7f3a978 various cleanups and use RB.search_fold for ordering of track artists 2013-11-08 21:20:04 +00:00
fossfreedom 846e995d82 add dummy column so that main column doesnt excessively expand to fill the space 2013-11-08 13:38:35 +00:00
fossfreedom 840ef0fd68 add clickable header for sorting 2013-11-08 13:00:03 +00:00
fossfreedom c562d3c4b3 ensure startup of view has a collapsed paned and is also initialised correctly when switching to it from another view 2013-11-06 23:44:27 +00:00
fossfreedom b2aec88ccf rework to use selection changed event which is similar to how the iconview is done 2013-11-06 22:53:59 +00:00
fossfreedom 7302165293 connect click and double click events 2013-11-05 00:09:36 +00:00
fossfreedom 9502bcf528 display artist and album images in tree-view 2013-11-04 23:00:24 +00:00
fossfreedom afbc8bd3b9 display albums for artists when the artist is expanded 2013-11-04 19:37:23 +00:00
fossfreedom 958e6ad6de refactor to separate data model from the view to be analagous to how album data model is done 2013-11-03 18:07:48 +00:00
fossfreedom 7027112b58 reactivate artist button ready for new artist treeview 2013-10-31 21:57:05 +00:00
fossfreedom 2c8554d79f display message if albums do not meet threshold - issue #213 2013-10-29 17:22:57 +00:00
fossfreedom 16f6055488 make sure double click and hover play use favourites - issue #213 2013-10-29 00:28:10 +00:00
fossfreedom d09ac59971 use 'New Playlist' as the default label when adding a new playlist - issue #213 2013-10-29 00:19:27 +00:00
fossfreedom 9e83e420bc its back! trick was realising calculation needs to be in widget coords - issue #84 2013-10-28 11:13:48 +00:00
fossfreedom 7e2eb1b8f9 temporarily abandon hotspot functionality - when view is scrolled it doesnt work anyway due to the way the hotspot position is calculated. Need to investigate further - issue #84 2013-10-28 09:42:38 +00:00
fossfreedom d7b7de854a rejig to delay immediate hotspot display slightly and also to force a view redraw so that hover is displayed even if the mouse is not moving - issue #84 2013-10-28 09:24:59 +00:00
fossfreedom 025cd52e3c refine hover display - displays immediately if move cursor over the hotspot region - issue #84 2013-10-27 23:42:24 +00:00
fossfreedom ab7643d7fa turn-off tooltips if cover display-text is active - issue #228 2013-10-26 23:14:54 +01:00
fossfreedom 211f4019bb slightly reduce time interval and remove print statements 2013-10-26 23:00:43 +01:00
fossfreedom 5ccd07e4b2 rework with new button images and half-second delay before display of hover - issue #84 2013-10-26 21:36:55 +01:00
fossfreedom 7b2c529228 rework to support play-pause on hover icon 2013-10-23 21:58:19 +01:00
fossfreedom 2a28592360 rejig so that iconview controls play icon 2013-10-23 20:08:33 +01:00
fossfreedom 00e0c80594 Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-10-22 21:37:27 +01:00
fossfreedom a79591f9c0 ensure play icon responds to mouse hovering over it by dimming to show it is clickable - issue #84 2013-10-22 21:37:04 +01:00
David Mohammed f32713855f Update README.md 2013-10-20 17:49:03 +01:00
fossfreedom 27fdc07f28 fix multiple progress bars appearing on loading - issue #226 2013-10-20 17:36:28 +01:00
fossfreedom 8ba870184d add rb3 monochrome icon for the browser source icon - issue #225 2013-10-20 17:08:35 +01:00
fossfreedom bd9f7c52c0 update readme and available GTK version for single click play - issue #84 2013-10-19 22:37:53 +01:00
fossfreedom 3fd7fa281e single click play on hovered play-symbol shown in cover - issue #84 2013-10-19 22:06:59 +01:00
fossfreedom cafda03761 lighten the mood 2013-10-16 22:07:00 +01:00
fossfreedom 752357ad68 removed obsolete file 2013-10-13 19:49:58 +01:00
fossfreedom 1394cedbd2 latest az translation 2013-10-13 19:47:26 +01:00
fossfreedom 5bc4d5ef31 updated missing artwork images - issue #183 2013-10-12 14:05:16 +01:00
fossfreedom 97ec1dab0a ensure that text_within option does not conflict with add-shadow option 2013-10-11 21:10:16 +01:00
fossfreedom d0e3f218e0 link up coverart-text-pos with cellrenderer 2013-10-11 20:14:36 +01:00
fossfreedom e37655d7e0 add text position option to preferences and schema 2013-10-11 00:02:50 +01:00
fossfreedom d8967fb4e1 add cellrenderer for the text embed capability 2013-10-10 22:59:46 +01:00
fossfreedom b7a5a8e023 readded jrbastiens changes in popup.xml into the translation equivalent so that we dont lose the changes when we regenerate the translation files later 2013-10-07 13:30:58 +01:00
David Mohammed 57808278d3 Update README.md 2013-10-07 13:19:27 +01:00
David Mohammed 9412ddfb29 Merge pull request #222 from jrbastien/master
Introducing a new icons theme for the coverart browser
2013-10-07 05:09:55 -07:00
jrbastien d99cab53d1 Merge branch 'master' of https://github.com/jrbastien/coverart-browser 2013-10-06 20:00:46 -04:00
jrbastien 9312c37305 Adding the documentary genre as an alternate genre for the spoken genre. 2013-10-06 19:58:23 -04:00
Jean-Rene Bastien f8eb618d84 Delete Tour_Effel.png
Custom icon. Should not have been included in the theme.
2013-10-06 19:33:55 -04:00
jrbastien 3f610a74a1 Introducing a new icons theme with the goal of having something less distracting on the eyes. All icons have been redesigned but the genre sprite. 2013-10-06 19:29:13 -04:00
fossfreedom 12826cdde6 minor mods for finnish translation 2013-10-05 23:05:01 +01:00
fossfreedom c6eb082aca ensure that columns are correctly ordered - issue #219 2013-09-30 20:39:22 +01:00
fossfreedom 58815e03a9 add progress bar if required for RB3.0 - issue #189 2013-09-29 20:14:58 +01:00
fossfreedom 1380515c63 made properties option favourites and quick artist filter persistent - issue #213 2013-09-26 21:06:59 +01:00
fossfreedom 3c18ca9052 Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-09-23 19:45:45 +01:00
fossfreedom f9422d8a19 remove all the pointless menu label changing stuff - #213 2013-09-23 19:45:23 +01:00
fossfreedom d64f1bcaf7 change labels for favourites - issue #213 2013-09-22 10:21:13 +01:00
fossfreedom 27c386e172 fix for external plugin case sensitive issue and fix wrong group name for opencontainingfolder plugin 2013-09-17 00:01:24 +01:00
fossfreedom 5e2cec619e add new translation - pt 2013-09-16 22:49:51 +01:00
fossfreedom 8ab66a192f tidied master readme 2013-09-11 21:10:42 +01:00
fossfreedom 4e480c40fe Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-09-11 20:58:12 +01:00
fossfreedom 9b58df3784 add use favourites menu option to properties menu - issue #213 2013-09-11 20:57:54 +01:00
fossfreedom 34583e0086 latest translations from launchpad 2013-09-11 16:09:58 +01:00
fossfreedom 368e582fe2 fix initial display of album info on startup - issue #214 2013-09-11 08:35:00 +01:00
fossfreedom 186977f6ef ensure the version of the coverart_search_providers plugin is correct to prevent unnecessary crashes and other confusion - issue #212 2013-09-08 21:53:22 +01:00
fossfreedom ce119120b7 connect resize art option - issue #212 2013-09-08 20:43:08 +01:00
fossfreedom 6759472a2e add optional mp3 conversion with bitrate calculation - issue #212 2013-09-08 11:47:55 +01:00
fossfreedom 58ef685380 latest spanish translation 2013-08-27 20:51:31 +01:00
fossfreedom 594feaca93 latest ro translation 2013-08-27 12:45:10 +01:00
fossfreedom edcf74f005 latest az, fr & pl translations 2013-08-26 16:38:51 +01:00
fossfreedom a6993e3d2e latest tr.po 2013-08-26 10:54:07 +01:00
fossfreedom 5ccc4c1c7d Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-08-25 23:54:33 +01:00
fossfreedom 35335da6b8 latest translations and removed those translations that are less than 50 percent translated 2013-08-25 23:54:22 +01:00
David Mohammed ba9ae93d87 Update README.md 2013-08-25 23:45:18 +01:00
David Mohammed 6b999b0099 Update README.md 2013-08-25 23:33:53 +01:00
David Mohammed 388e8faec6 Updated - ready for release 2013-08-25 23:22:52 +01:00
fossfreedom da92ed7d9a bug fix - prevent help button being continually duplicated when preferences dialog repeatedly opened 2013-08-25 10:09:01 +01:00
fossfreedom a17a32e33b latest translations 25/08/13 2013-08-25 09:43:29 +01:00
fossfreedom 17db0b98df remove obsolete icons 2013-08-22 14:09:04 +01:00
fossfreedom d500fdb0bf latest translations 22/08/13 2013-08-22 11:52:14 +01:00
fossfreedom 69fccf10f4 latest fr_CA translations - issue #202 2013-08-18 20:06:11 +01:00
David Mohammed fa2050486e remove "sh" from the running of the bash shell script install.sh - issue #211 2013-08-18 15:57:08 +01:00
fossfreedom 3f85bc1da6 updated padding description - issue #202 2013-08-18 15:42:56 +01:00
fossfreedom 9d59cb0748 remember the position of the quick artist filter handle position - issue #210 2013-08-18 15:26:46 +01:00
fossfreedom e1aa1ba082 readd previous translations that jrbastien made - issue #202 2013-08-18 10:57:58 +01:00
fossfreedom 8ac60117ac center view buttons and allow search button to expand to its full extent - issue #202 2013-08-18 10:33:18 +01:00
fossfreedom 7179b2e601 latest fr_CA translation 2013-08-17 21:58:21 +01:00
fossfreedom e93a7dd36b Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-08-17 20:38:53 +01:00
fossfreedom 85df2fa79d regenerated po's using less restrictive intltool-extract 2013-08-17 20:30:27 +01:00
fossfreedom 3e55c8daa9 changed tile to tiles, tooltip swap and added translator info for 'All' 2013-08-17 20:07:16 +01:00
David Mohammed 59f1a840ec Update README.md 2013-08-15 23:02:10 +01:00
fossfreedom 74d6a62238 add help button to preferences dialog called from coverart-browser 2013-08-13 19:36:46 +01:00
fossfreedom ef657da311 remove obsolete code when right click on source in rb2.96 2013-08-11 21:31:12 +01:00
David Mohammed 250eea8053 Update README.md 2013-08-10 21:24:59 +01:00
fossfreedom f243e2aba2 add llyrics and fileorganizer as supported plugins for rb2.99 users 2013-08-10 21:17:23 +01:00
fossfreedom e47c3dedac latest translations update 2013-08-07 14:50:31 +01:00
fossfreedom 2a2a51c1ed hook up quick artist filter to properties menu item 2013-08-06 21:54:04 +01:00
fossfreedom c27ae05e3c connect up quick artist filter to album model 2013-08-06 20:43:34 +01:00
fossfreedom 00ccb84fc3 Merge branch 'master' of https://github.com/fossfreedom/coverart-browser into quickfilter 2013-08-05 21:07:30 +01:00
fossfreedom 83e73f95d5 fix missing import of RB 2013-08-05 21:06:05 +01:00
fossfreedom 154e5df152 force the state of a stateful action - this fixes the issue where an accelerator is used to activate rather than a menu option - issue #208 2013-08-05 21:04:23 +01:00
David Mohammed 5781a67a70 Update coverart_rb3compat.py 2013-08-05 13:26:01 +01:00
David Mohammed 0322dfd248 Merge pull request #207 from dmo60/patch-1
enable passing a custom stock_id for actions
2013-08-05 05:22:29 -07:00
Timo Loewe ecd1a07026 Update coverart_rb3compat.py
enable passing a custom stock_id for actions
2013-08-04 12:48:48 +02:00
fossfreedom 3273c920ec create paned layout and connect model to library source 2013-08-04 00:20:14 +01:00
fossfreedom 7b33009e67 fixed name reference for our panedcollapsible widget 2013-08-03 21:30:29 +01:00
fossfreedom 73e218e99f update readme for iconview toggle 2013-08-03 18:10:35 +01:00
fossfreedom 30a6ebeb45 add optional track-view toggle to keep consistent with flow-view 2013-08-03 18:08:15 +01:00
fossfreedom 2e27bbd794 add rb3 install instructions - issue #194 2013-08-03 13:48:52 +01:00
fossfreedom a029c43144 add option to install RB version 3 - issue #194 2013-08-03 13:46:21 +01:00
fossfreedom 474fba83c0 fix python3 depreciation warnings in ubuntu saucy - issue #187 2013-08-02 22:23:27 +01:00
fossfreedom 491d35b581 update makefile for global installation and deb creation 2013-08-02 16:14:48 +01:00
fossfreedom e7b68f91b7 uplift source files for translation activities 2013-08-02 15:01:45 +01:00
fossfreedom c348988325 each view now remembers if the track-view should be open or closed when switching between those views - issue #206 2013-08-01 23:06:06 +01:00
fossfreedom 6c76820891 relaxed check for mouse to be over the coverflow when controlling the coverflow via keyboard - issue #206 2013-07-31 10:18:17 +01:00
fossfreedom fadb361a0c remove scrollbar 2013-07-30 23:07:05 +01:00
fossfreedom 52d6828480 remove unwanted file 2013-07-30 23:02:47 +01:00
fossfreedom 9d0666144b fix resizing issue on coverflow 2013-07-30 23:02:17 +01:00
fossfreedom c9d27129b1 some python3 fixups 2013-07-30 21:20:21 +01:00
fossfreedom 5fc8e853ad move signal update out of loop so that it always fires not just when the caption is visible 2013-07-29 22:00:52 +01:00
fossfreedom 0c072028c0 add optional argument 2013-07-29 20:46:32 +01:00
fossfreedom bc3d194920 centre view buttons correctly on top-bar - issue #206 2013-07-29 14:59:07 +01:00
fossfreedom da37365b38 display active album in trackview whilst scrolling in coverflow - issue #206 2013-07-29 14:08:34 +01:00
fossfreedom ebfc12ef15 reset on_first_use counter after it actually has been through this section of code 2013-07-29 11:38:59 +01:00
fossfreedom 017312e7c5 expand pane on very first use on coverflow - issue #206 2013-07-29 11:27:08 +01:00
fossfreedom 5302cca0a1 changed label to reflect true meaning 2013-07-29 09:50:53 +01:00
fossfreedom b9f82a794f changed filter message to be more meaningful - issue #206 2013-07-29 09:48:29 +01:00
fossfreedom b9ac6a5c8a Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-07-28 23:52:34 +01:00
fossfreedom 1e1e6481a9 move items creation to filter_changed to be consistent with the rest of the html manipulation 2013-07-28 23:52:03 +01:00
David Mohammed 6840a52d67 Update README.md 2013-07-28 19:21:02 +01:00
fossfreedom 42fb3f650b add support to disable call to webkit library via a gsettings value - issue #199 2013-07-28 19:19:02 +01:00
fossfreedom 9130f32038 focus issues on coverflow after quick search and expand descriptions of the abstract view 2013-07-28 09:15:14 +01:00
fossfreedom 6a7b7f7146 remove obsolete code and renamed methods that are really just private to the coverflow 2013-07-28 08:59:50 +01:00
fossfreedom f4f1086883 fix for reason why rating was not being recalculating - issue #204 2013-07-27 22:37:33 +01:00
fossfreedom 14b84f1a9c lets add generic support for RB2.98 and 2.99 i.e. assume something has modified on the album 2013-07-27 17:26:56 +01:00
fossfreedom 44cf1a94c6 remove some strange code causing spurious album updates whenever anything changes - now the track modified signal is only thrown when a track artist details are changed 2013-07-27 17:19:02 +01:00
fossfreedom e348ec9b45 fix locking issue due to incorrect use of threads 2013-07-27 05:51:01 +01:00
fossfreedom 0ea4d413c3 some cleanups including reducing flickering when changing album properties or changing cover as well as fixing the quick search on the flow 2013-07-26 20:15:39 +01:00
fossfreedom 69800ebb6d move separators to more logical locations 2013-07-26 12:57:20 +01:00
fossfreedom e9c869e5ad fix typos primarily in album-updated emit signal 2013-07-26 12:53:50 +01:00
fossfreedom 34367b8e85 add jrbastiens new icons and hide the artist button 2013-07-26 09:25:42 +01:00
fossfreedom 77436aca08 fix quick search on iconview if flowview was the default on startup 2013-07-25 23:51:55 +01:00
fossfreedom d72cac5424 a bit of a hack - refilter the coverflow whenever something on an album changes such as changing the picture 2013-07-25 21:50:01 +01:00
fossfreedom 10d26bb4d3 disable default drag-drop on webview and enable the active element to receive the dropped picture from the cover pane 2013-07-24 20:36:21 +01:00
fossfreedom f9cff865bf substitute properties.png with jrbastien's version 2013-07-24 13:28:46 +01:00
fossfreedom 0e43b68a73 simplify processing, link display to flow-max number, re-add slider and circular-flow 2013-07-23 21:09:25 +01:00
David Mohammed 0541665488 Update README.md 2013-07-23 13:00:57 +01:00
fossfreedom 76a9610422 add random album functionality - issue #196 2013-07-21 10:34:27 +01:00
fossfreedom 6c09a042f9 connect automatic click setting to coverflow 2013-07-20 22:09:28 +01:00
fossfreedom 844a514ccc revert toggle buttons to text only and differentiate the label colour depending upon which is active 2013-07-20 11:07:53 +01:00
fossfreedom b991fd6993 add separator in properties menu to differentiate between preferences and other view functionality 2013-07-20 09:48:36 +01:00
fossfreedom ab47c5f97d add search providers dialog to properties button 2013-07-19 20:40:05 +01:00
fossfreedom 6a5eace53d link up plugin preferences dialog to properties button menu 2013-07-19 14:57:07 +01:00
fossfreedom 639429fed1 changed my mind - lets display albums anyway - just need to add the limit when refactoring the batch processing part 2013-07-18 22:31:13 +01:00
fossfreedom 28ee9474f8 connect max albums to preferences 2013-07-18 21:55:57 +01:00
fossfreedom b98ea85bdb add max number of albums to display in coverflow 2013-07-18 21:38:47 +01:00
fossfreedom bb02cbc035 correct names for notify properties so that they sync when preferences change 2013-07-18 14:29:34 +01:00
fossfreedom 3ef9bb6afc refactor coverflow code for properties and their signals 2013-07-18 13:14:34 +01:00
fossfreedom b3ed080e09 wrong default width for coverflow 2013-07-18 12:24:30 +01:00
fossfreedom eb5014483a slight modifications to README 2013-07-17 23:54:07 +01:00
fossfreedom 8bd4799bf4 connect startup gsettings values to various values in the coverflow index.html 2013-07-17 23:35:49 +01:00
fossfreedom a3c3631ecb link prefs dialog flow items to gsettings 2013-07-17 19:27:24 +01:00
David Mohammed e4ecbb3c11 Add LICENSE file via addalicense.com 2013-07-17 01:21:38 -07:00
fossfreedom 94f7e1045e Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-07-16 21:20:08 +01:00
fossfreedom a5a9096732 add check on paned release event - temporary resolution for flow click issue 2013-07-16 21:20:00 +01:00
fossfreedom 1f3f5b7df1 add GUI options to preferences - note, these have not been linked as yet to the flow 2013-07-16 13:01:36 +01:00
fossfreedom da09955aeb add check and use path instead of pixbuf when creating Cover on drag-drop - issue #195 2013-07-14 20:03:26 +01:00
fossfreedom 1fce749c3e reinstate download all covers via properties button 2013-07-13 00:02:28 +01:00
fossfreedom 1bb5e94b1e add various flow addons 2013-07-12 11:32:09 +01:00
fossfreedom f19a5d3e75 relinked the toggle with the view on startup 2013-07-11 23:47:24 +01:00
fossfreedom e479bb2983 fix picture display on top toolbar 2013-07-11 23:05:19 +01:00
fossfreedom 2d61b6ebab fix sidebar display of new buttons 2013-07-11 21:58:32 +01:00
fossfreedom 339b25633a rework toggle buttons to be image buttons and add a dummy properties button as well as a dummy artist view button 2013-07-11 20:45:16 +01:00
fossfreedom a651ac93d4 fix right click on coverflow as well as selection issues when switching views 2013-07-10 23:13:54 +01:00
fossfreedom 44a281ff99 minor mod to use scalefactor rather than maxheight for the sizing of images 2013-07-10 22:45:39 +01:00
fossfreedom 64b900f21a minor mod to use scalefactor rather than maxheight for the sizing of images 2013-07-10 22:44:04 +01:00
fossfreedom dd84f9183c various fixes to ensure that the coverflow is loaded after all covers have been loaded as well as resolving various scroll to album issues 2013-07-09 23:24:22 +01:00
fossfreedom acb86fea37 Update coverart_browser.plugin 2013-07-08 08:19:59 +01:00
fossfreedom dcc89ed8a2 now works for RB3.00 - adjusted comment - issue #186 2013-07-08 00:05:42 +01:00
fossfreedom 100a552d56 fix some python3 issues 2013-07-07 23:59:22 +01:00
fossfreedom f96bc30716 tidyup playlist monitoring code 2013-07-07 22:51:32 +01:00
fossfreedom 727165a9d5 assume the shell display-page-model changes can be used to monitor playlist events as well - issue #192 2013-07-07 22:24:15 +01:00
fossfreedom b6bb7eaeb6 fix playlist crash in RB2.99 - issue #191 2013-07-07 21:56:56 +01:00
fossfreedom 6002454340 tie two views to clickable toolbar radio-buttons 2013-07-07 15:14:07 +01:00
fossfreedom 023ebcf1d3 must remember to at least run RB to check for crashes... 2013-07-07 08:58:11 +01:00
fossfreedom 4a3add381b fix for fedora19 crash #191 2013-07-07 08:51:23 +01:00
fossfreedom 206f574cdf delegate switching of views to themselves and better sync between views 2013-07-06 07:41:43 +01:00
fossfreedom 9789b697f0 sync selected albums when flipping between views 2013-07-05 21:48:10 +01:00
fossfreedom 0116413aa2 connect views to viewmanager via a schema key 2013-07-04 21:59:31 +01:00
fossfreedom 2b03440adc ensure new batch is passed the album identifier 2013-07-04 13:24:18 +01:00
fossfreedom d22355d29d refactor iconview specific methods from abstractview 2013-07-04 12:38:59 +01:00
fossfreedom 1ccde3b5d4 fix constant dragging issue after right-click menu is removed from the display 2013-07-03 23:09:21 +01:00
fossfreedom a10dc87ef0 add rudimentary right-click support 2013-07-03 22:26:46 +01:00
fossfreedom 828787dc8d added rudimentary response to click and double click events 2013-07-02 23:49:57 +01:00
fossfreedom bc7052f671 link coverflow with albummodel 2013-07-02 21:36:46 +01:00
fossfreedom afc4a2939c bug fix - playlists were never updated on the playlist menu 2013-07-02 21:35:59 +01:00
fossfreedom 5bad5fa5e2 various RB3 & python3 issues 2013-07-01 21:07:51 +01:00
fossfreedom 452de7f834 integrate coverflow folder structure using initial prototype code 2013-06-30 20:32:18 +01:00
fossfreedom 205fa02435 update supported external plugins 2013-06-30 12:08:48 +01:00
fossfreedom 791787559b restructure so that we have a definitive list of methods a view should have and create a ViewManager class which will eventually manage our different views 2013-06-29 23:35:24 +01:00
fossfreedom 70575fb308 add space between : to cope with french locale requirements - issue #185 2013-06-25 21:38:18 +01:00
fossfreedom 7360482c9d add space between : to cope with french locale requirements - issue #185 2013-06-25 10:41:00 +01:00
fossfreedom d05231de82 latest az translation 2013-06-22 16:04:18 +01:00
fossfreedom 8b38ae236e move cover view specific stuff from covert_album to the cover icon view module 2013-06-22 00:09:09 +01:00
fossfreedom 0ed9d54e22 regeneration of plugin and popups 2013-06-21 20:36:46 +01:00
fossfreedom e7d7efaf61 readd copyright statement 2013-06-21 20:36:14 +01:00
fossfreedom 4cac3ed47d latest translations in release-0.8 2013-06-21 20:32:50 +01:00
fossfreedom 777e78fbc4 more translations for zh_CN 2013-06-21 19:35:02 +01:00
fossfreedom e5e66a1f24 fix change selection 2013-06-21 19:33:30 +01:00
fossfreedom 6aaee47cb6 latest zh_CN translation 2013-06-21 15:57:06 +01:00
fossfreedom db028fa7c8 latest zh_CN translation 2013-06-21 09:23:13 +01:00
fossfreedom 2f50a382ea move icon notify gsetting signals to new module 2013-06-20 23:58:52 +01:00
fossfreedom 60c6cba7cf move signals for iconview to new module 2013-06-20 23:41:22 +01:00
fossfreedom 424f18799d drag drop refactoring 2013-06-20 23:25:04 +01:00
fossfreedom b12423ca63 new translations - bs, el and fi 2013-06-20 22:38:36 +01:00
fossfreedom f6c23576a0 refactored covericonview specifics into its own source module 2013-06-20 22:02:55 +01:00
fossfreedom 5c1736cb04 Update README.md 2013-06-19 21:04:52 +02:00
fossfreedom ebe6678e43 latest pl translation 2013-06-19 09:29:47 +01:00
fossfreedom 6ab0bcecd3 cherry pick 97e1f79ad5 2013-06-18 23:53:48 +01:00
fossfreedom b0b6a09100 Merge branch 'release-0.8' of https://github.com/fossfreedom/coverart-browser into release-0.8 2013-06-18 23:42:53 +01:00
fossfreedom 97e1f79ad5 fix for crash if using BPM column - issue #188 2013-06-18 23:42:19 +01:00
fossfreedom 302048e93b Update README.md 2013-06-18 22:16:05 +02:00
fossfreedom 157cc0359b added new romanian translation 2013-06-18 10:00:37 +01:00
fossfreedom 85b76af44a Merge branch 'master' of https://github.com/fossfreedom/coverart-browser 2013-06-17 22:43:45 +01:00
fossfreedom 6f29b47576 python3 fixes for git compiled version of RB running on saucy 2013-06-17 22:43:25 +01:00
fossfreedom 45aa5281e2 remove obsolete param in constructor call 2013-06-17 11:52:28 +01:00
fossfreedom 6f4ff35547 revert python3 requirement 2013-06-17 11:51:45 +01:00
fossfreedom b578d8f386 fixed some errors that prevented plugin initialisation under python3 2013-06-15 16:55:27 +01:00
fossfreedom 8d40dad422 Update README.md 2013-06-13 12:37:03 +02:00
fossfreedom c7d6dc3481 resync from release-0.8 branch 2013-06-13 11:26:37 +01:00
fossfreedom 953a159018 latest pl translation 2013-06-13 11:19:17 +01:00
fossfreedom 68aacc4f72 latest az translation 2013-06-10 15:35:24 +01:00
fossfreedom 1dad8ae6d3 sync with lastfmqueue changes 2013-06-08 11:32:32 +01:00
fossfreedom 6860b4d4a3 latest polish translation 2013-06-06 20:05:08 +01:00
fossfreedom 28e6ad9a04 pull in changes whilst working on lastfm_queue 2013-06-05 18:00:25 +01:00
fossfreedom c2260d6806 fix display of accelerators in rb299 2013-05-31 16:30:25 +01:00
fossfreedom 6ffdc361b3 add support for RB2.99 view app menu as well as the default tools app menu 2013-05-31 00:01:06 +01:00
fossfreedom 4e8a081cad added API to associate accelerators with actions 2013-05-30 17:32:55 +01:00
fossfreedom 193bd37572 Update README.md 2013-05-28 21:05:23 +02:00
fossfreedom e666803e2d Update README.md 2013-05-28 21:04:36 +02:00
fossfreedom d6128831c4 remove spurious .orig files 2013-05-28 19:50:03 +01:00
fossfreedom 3277635a97 merge 2013-05-28 19:47:20 +01:00
fossfreedom cd1a6d1f91 add header to compat module 2013-05-28 19:20:34 +01:00
fossfreedom ce452dbba5 add app action toggle 2013-05-26 08:51:15 +01:00
fossfreedom cf0b264062 fix rb299 action_name vs label override issue 2013-05-25 21:32:15 +01:00
fossfreedom e95e4a0af7 fix tabs vs spaces and oops with send-first action name 2013-05-25 20:17:31 +01:00
fossfreedom c851f3d913 fix some cleanup issues 2013-05-25 16:48:36 +01:00
fossfreedom 83168a14bd bug fix to display browser menu items enabled in rb299 2013-05-25 16:07:40 +01:00
fossfreedom b792a42371 finalised RB299 functionality and completed code definitions - issue #171 2013-05-25 11:15:44 +01:00
fossfreedom dc0b9a113b fix menu crash in rb299 2013-05-25 00:04:40 +01:00
fossfreedom 77a3867152 bug fixes for rb296 after rework of Action object 2013-05-24 22:38:04 +01:00
fossfreedom 6fb90792af add new ast translation 2013-05-22 10:10:20 +01:00
Agustin Carrasco dabb80dc65 Merge branch 'order-keys'
Added support for multiple ordering on some order types (to allow a
better subordering inside each type).

closes #138
Conflicts:
	coverart_album.py
	coverart_browser_source.py
	coverart_utils.py
2013-05-22 00:46:25 -03:00
Agustin Carrasco 8855b85653 Merge branch 'refactor-statusbar' into order-keys 2013-05-22 00:20:26 -03:00
fossfreedom ccff276ab0 fixed app menu support for rb299 2013-05-21 23:50:06 +01:00
fossfreedom 8f42a9ea71 add label support for rb296 actions 2013-05-21 20:57:17 +01:00
fossfreedom c094a8f445 made menu more generic by removing the dependency on the source for the Menu creation 2013-05-20 23:56:30 +01:00
fossfreedom ae44b76a41 bug fixes for rb299 support 2013-05-20 23:02:16 +01:00
fossfreedom 263df5c62c finish restructuring for rb296 2013-05-19 23:39:56 +01:00
fossfreedom c7f8fe0ded fixed activation events for rb296 2013-05-19 21:03:19 +01:00
fossfreedom 3bd947bf16 preliminary rework to external plugins to support rb299 2013-05-18 23:51:34 +01:00
Agustin Carrasco 65de81ebc0 statusbar: removed extra space on status text 2013-05-16 22:52:35 -03:00
Agustin Carrasco a4c8cc4258 statusbar: finished refactoring statusbar (issue #123) 2013-05-16 22:39:48 -03:00
fossfreedom bc59cd85a2 rework external plugin support to use XML datafile instead of python classes 2013-05-15 19:34:38 +01:00
fossfreedom 08dc4ee2e1 config file used to describe external plugins 2013-05-14 20:08:11 +01:00
fossfreedom c098d0a5ac latest changes made by coverart-search-providers 2013-05-14 20:07:28 +01:00
fossfreedom 419b95d49c Update README.md 2013-05-13 00:52:46 +02:00
fossfreedom 8f3c66b726 Update README.md 2013-05-13 00:51:40 +02:00
Agustin Carrasco 35b2bda943 statusbar: start isolating statusbar behavior in a couple of classes 2013-05-11 23:46:57 -03:00
fossfreedom 7c584aa1e3 working playlists - issue #171 2013-05-10 23:15:43 +01:00
fossfreedom d1583f78f5 latest translations from launchpad 2013-05-10 13:57:01 +01:00
fossfreedom fd4f1a86fd add structure around playlist support - need to debug playlist creation and test against older versions of rhythmbox to ensure restructuring hasnt broken extant capabilities - issue #171 2013-05-08 23:26:38 +01:00
fossfreedom 8d58c448e8 converted entry-view menu - issue #171 2013-05-06 09:07:59 +01:00
fossfreedom 83f0194f2f first cut of rb2.99 support - lots of stuff still not working such as playlists, external plugins and track-view still to be converted - issue #171 2013-05-05 17:12:32 +01:00
fossfreedom 6347abcd2f fixed typos 2013-04-28 22:58:40 +01:00
fossfreedom 09c73972a5 fix missing merge 2013-04-28 11:52:41 +01:00
fossfreedom e9f16ab6b3 merge from master 2013-04-28 11:43:47 +01:00
fossfreedom 0a012d97bc convert pure list-map items to loops to prevent wasteful list generation - issue #179 2013-04-27 23:29:54 +01:00
Agustin Carrasco d674618904 albums: fix dumb name collision on sort_keys 2013-04-27 17:00:37 -03:00
Agustin Carrasco 9349e965c3 albums: added internal support for multiple propery sorting (issue #138)
Had to do some little changes to make this work on the AlbumModel:
- The album_sort and album_sort_artist were returning a redundant list
  that made ordering kinda quirky. Used the uniqyfy function to make
  them return a more sane result.
- Added a sort_keys dictionary to translate the different sort keys into
  a group of properties to sort by. This may have to change in the
  future to make it more mantianable.
- Changed the sort method to use the sort_keys when creating the sort
  fuction for the sorted collection.
2013-04-27 16:47:22 -03:00
Agustin Carrasco 0a6dc5620b utils: added a uniqyfy_and_sort function that removes duplicates and sorts an iterable 2013-04-27 16:40:01 -03:00
fossfreedom f78c77c98d Update README.md 2013-04-25 15:36:52 +02:00
fossfreedom 2550d46f15 necessary changes to allow plugin to work in global install location 2013-04-24 23:06:05 +01:00
fossfreedom c868c1a44e rework specific python2 to 3 function issues - issue #179 2013-04-24 20:55:46 +01:00
Agustin Carrasco aa44101ed5 albums: Added a check to save_to_disk property before adding entry
Doing this prevents that a "trancient" entry gets added to an Album.
This kind of entries usually come from external devices, which generally
generates duplicates on the album track list. (issue #169)
2013-04-21 23:29:22 -03:00
fossfreedom c6099bb89d a quick 2to3 run to see what breaks when running under python2.7 - this will give a better idea of how to keep both python 2.7 and python3 compatibility - issue #179 2013-04-21 20:43:03 +01:00
fossfreedom c0a5d2566f updated readme for v0.9 2013-04-21 18:14:04 +01:00
fossfreedom 9f4b104322 Merge branch 'viewadvanceoptions' 2013-04-21 17:45:56 +01:00
fossfreedom 522cdb25f8 add advance options for iconview spacing and padding 2013-04-20 21:44:55 +01:00
223 arquivos alterados com 101160 adições e 7817 exclusões
+1
Ver Arquivo
@@ -7,6 +7,7 @@ dist
build
eggs
parts
.idea
bin
var
sdist
+621
Ver Arquivo
@@ -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.
+18 -2
Ver Arquivo
@@ -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)
+57 -37
Ver Arquivo
@@ -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.
![Imgur](http://i.imgur.com/yXYmcOt.png)
![Imgur](http://i.imgur.com/sUgX7d7.png)
-----------
@@ -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
[![Flattr Button](http://api.flattr.com/button/button-compact-static-100x17.png "Flattr This!")](https://flattr.com/thing/1238849/fossfreedom-at-Flattr "fossfreedom") [![paypaldonate](https://www.paypalobjects.com/en_GB/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBV682WJ3BDGL)
[![Flattr Button](http://api.flattr.com/button/button-compact-static-100x17.png "Flattr This!")](http://flattr.com/thing/1811704/ "fossfreedom") [![paypaldonate](https://www.paypalobjects.com/en_GB/i/btn/btn_donate_SM.gif)](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
+12 -5
Ver Arquivo
@@ -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
+597 -500
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+19 -3
Ver Arquivo
@@ -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
+3 -3
Ver Arquivo
@@ -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
+184 -36
Ver Arquivo
@@ -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)
+304 -71
Ver Arquivo
@@ -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())
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+331 -98
Ver Arquivo
@@ -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]
+436
Ver Arquivo
@@ -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
+690
Ver Arquivo
@@ -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()
+704 -108
Ver Arquivo
@@ -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)
+197 -54
Ver Arquivo
@@ -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)
+137 -158
Ver Arquivo
@@ -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)
+80
Ver Arquivo
@@ -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 []
+184
Ver Arquivo
@@ -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)
+377
Ver Arquivo
@@ -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.)
+80
Ver Arquivo
@@ -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 []
+80
Ver Arquivo
@@ -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 []
+880
Ver Arquivo
@@ -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)
+82 -48
Ver Arquivo
@@ -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('&', '&amp;'),
'utf-8')
album_name = rb3compat.unicodestr(album_name.replace('&', '&amp;'), '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('&', '&amp;'),
'utf-8')
self.render_artist_art_search(artist)
if not(album_name == "" and artist == ""):
artist = unicode(artist.replace('&', '&amp;'),
'utf-8')
album_name = unicode(album_name.replace('&', '&amp;'), '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)
+241
Ver Arquivo
@@ -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
+184 -77
Ver Arquivo
@@ -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())
+594 -94
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+81
Ver Arquivo
@@ -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;
}
/* ================================= */
+19
Ver Arquivo
@@ -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
}
});
+65
Ver Arquivo
@@ -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;
}
/* ================================= */
+131
Ver Arquivo
@@ -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};
}
}
});
+52
Ver Arquivo
@@ -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};
}
}
});
+31
Ver Arquivo
@@ -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};
}
}
});
+80
Ver Arquivo
@@ -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;
}
/* ================================= */
+19
Ver Arquivo
@@ -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
}
});
+19
Ver Arquivo
@@ -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.
+250
Ver Arquivo
@@ -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 */
}
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+44
Ver Arquivo
@@ -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>
Arquivo binário não exibido.
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 82 B

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 82 B

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 43 B

+241
Ver Arquivo
@@ -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

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 8.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 8.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 8.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 2.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 3.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 1.9 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 3.0 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 82 B

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 82 B

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 175 B

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 178 B

+55
Ver Arquivo
@@ -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>
+231
Ver Arquivo
@@ -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
Ver Arquivo
@@ -1,6 +1,7 @@
import gi
from gi.repository import Pango
from gi.repository import Gtk
gi.require_version("Gtk", "3.0")
import logging
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 14 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 9.6 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 7.2 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 8.5 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 7.6 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 9.0 KiB

Antes

Largura:  |  Altura:  |  Tamanho: 60 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 60 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 541 B

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 3.7 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 3.4 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 13 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 1.3 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 1.2 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 54 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 2.7 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 68 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 19 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 3.8 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 17 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 22 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 2.7 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 3.9 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 368 B

BIN
Ver Arquivo
Arquivo binário não exibido.
+202
Ver Arquivo
@@ -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

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

Depois

Largura:  |  Altura:  |  Tamanho: 84 KiB

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

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

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

Depois

Largura:  |  Altura:  |  Tamanho: 37 KiB

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

Depois

Largura:  |  Altura:  |  Tamanho: 45 KiB

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

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

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

Depois

Largura:  |  Altura:  |  Tamanho: 109 KiB

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

Depois

Largura:  |  Altura:  |  Tamanho: 43 KiB

Diff do arquivo suprimido porque uma ou mais linhas são muito longas

Depois

Largura:  |  Altura:  |  Tamanho: 119 KiB

Diff do arquivo suprimido porque uma ou mais linhas são muito longas

Depois

Largura:  |  Altura:  |  Tamanho: 138 KiB

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

Depois

Largura:  |  Altura:  |  Tamanho: 39 KiB

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais