1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-09-06 20:20:41 +02:00

Compare commits

...

180 Commits
qt4 ... 0.3.3

Author SHA1 Message Date
Christian Muehlhaeuser
98416fab64 * Added german, spanish and polish translations. 2011-12-07 08:54:40 +01:00
Christian Muehlhaeuser
0917269b55 * Fixed button label. 2011-12-07 07:56:52 +01:00
Christian Muehlhaeuser
9321369194 * Merged from master. 2011-12-07 07:22:36 +01:00
Christian Muehlhaeuser
3b55336f69 * Query's toString() supports fulltext search queries, now. 2011-12-05 21:15:48 +01:00
Christian Muehlhaeuser
a35a2f371b * Slight optimation. 2011-12-05 21:14:16 +01:00
Christian Muehlhaeuser
2b6bc8f8d3 * Don't prioritize album-less tracks in edge cases. 2011-12-05 21:14:03 +01:00
Christian Muehlhaeuser
c20ebbb8bd * In Collection view with filter set: Don't jump to the selected item when expanding an artist. 2011-12-05 21:13:46 +01:00
Christian Muehlhaeuser
93245923d8 * Moved Attica to port 80. 2011-12-05 21:13:03 +01:00
Christian Muehlhaeuser
96dc260e4b * Fixed another sidebar issue with gtk styles. 2011-12-05 21:12:47 +01:00
Christian Muehlhaeuser
9fdfb3aad6 * Fixed sidebar issues with gtk styles. 2011-12-05 21:12:40 +01:00
Christian Muehlhaeuser
fafd8158cc * Upped version to 0.3.3. 2011-12-04 09:07:16 +01:00
Christian Muehlhaeuser
bd90f292e5 * URL encode the mpris2 ArtUrl. 2011-12-04 08:09:27 +01:00
Christian Muehlhaeuser
88f59aafb8 * Potential fix for TWK-618: ArtUrl not properly encoded. 2011-12-04 08:09:27 +01:00
Christian Muehlhaeuser
41f3521042 * Remove nonsense. 2011-12-04 07:34:24 +01:00
Christian Muehlhaeuser
a11c2d1bd5 * Give instant user feedback when scanner gets kicked off. 2011-12-04 07:34:14 +01:00
Christian Muehlhaeuser
797412efa5 * Updated ChangeLog. 2011-12-04 06:41:58 +01:00
Christian Muehlhaeuser
f6156786c6 * Fixed merging error. 2011-12-04 06:40:34 +01:00
Christian Muehlhaeuser
b8f57db684 * Renamed Tomahawk / Music Player menu to Controls. Let's see how that feels cross-platform. 2011-12-04 06:21:15 +01:00
Leo Franchi
da4527b0b6 More regression hunting: fix dynamic playlist spinner disappearing prematurely 2011-12-04 06:21:09 +01:00
Leo Franchi
0bf61e05fd Fix regression from model refactor that changed function name 2011-12-04 06:21:02 +01:00
Christian Muehlhaeuser
b5f57d6baa * Fixed tomahawk:// protocol handler on Windows (Firefox related). 2011-12-04 06:20:54 +01:00
Christian Muehlhaeuser
a628fad2f4 * Merged from master. 2011-12-04 06:20:43 +01:00
Christian Muehlhaeuser
0c496937d7 * Merged from master. 2011-12-04 06:19:54 +01:00
Christian Muehlhaeuser
a69f40aac1 * Show an error dialog when a playback problem occurred. 2011-12-04 06:18:25 +01:00
Christian Muehlhaeuser
cb9b11a39a * Merged from master. 2011-12-04 06:18:11 +01:00
Dominik Schmidt
8a83f642b1 Fix opening URLs with gvfs-open, why does firefox ignore it? why does epiphany ignore it? ... 2011-12-04 06:17:30 +01:00
Dominik Schmidt
a812be4200 Boo for too pedantic desktop-file-validate 2011-12-04 06:17:08 +01:00
Dominik Schmidt
97755e1dcb Remove now unneeded files from windows installer 2011-12-04 06:16:34 +01:00
Dominik Schmidt
9109047460 Use new phonon(-vlc) builds in update-vlc.sh, yay for umlauts and no-track-skipping (hopefully) 2011-12-04 06:16:25 +01:00
Christian Muehlhaeuser
6ae58e15dd * Don't accept 0.0.0.0 as a visible / valid address. 2011-12-04 06:16:12 +01:00
Christian Muehlhaeuser
e1acbbe769 * Proper fix for TWK-422. 2011-12-04 06:16:05 +01:00
Christian Muehlhaeuser
c03abede4a * Potential fix for TWK-422: Disappearing (white on white) sidebar items for some styles (e.g. gtk/gnome). 2011-12-04 06:15:58 +01:00
Christian Muehlhaeuser
a4d1dd4ffa * Updated German translation. 2011-12-04 06:15:32 +01:00
Christian Muehlhaeuser
91a6e737dd * Updated German translation. 2011-12-04 06:15:25 +01:00
Leo Franchi
bf9af4d350 remove unneeded debug 2011-12-04 06:15:17 +01:00
Christian Muehlhaeuser
05e2b95984 * Fixing assert in JobStatusModel. 2011-12-04 06:15:08 +01:00
Christian Muehlhaeuser
604a84b8ba * Merged from master. 2011-12-04 06:14:51 +01:00
Christian Muehlhaeuser
2bdb2c3edb * More natural job view order. 2011-12-04 06:13:22 +01:00
Christian Muehlhaeuser
0a44e0c24a * Animate the JobStatusView when it changes its size. 2011-12-04 06:13:10 +01:00
Christian Muehlhaeuser
5ab40b2d17 * Merged from master. 2011-12-04 06:12:57 +01:00
Christian Muehlhaeuser
dd2d82729d * Added a splitter to SourceInfoWidget. 2011-12-04 06:12:06 +01:00
Christian Muehlhaeuser
88e8a62770 * Merged from master. 2011-12-04 06:11:55 +01:00
Christian Muehlhaeuser
d15bc8a082 * Fixed TWK-556: Auto switch to super collection mode if we don't have any 'offical' information available. 2011-12-04 06:09:51 +01:00
Christian Muehlhaeuser
7513ea123b * Fixed TWK-559: Be more consistent with our GUI text. 2011-12-04 06:09:38 +01:00
Christian Muehlhaeuser
a34dc1ae4e * Support Footnotes in TreeViews. 2011-12-04 06:08:44 +01:00
Christian Muehlhaeuser
7b8f6cea3a * Center overlay widgets before showing them the first time. 2011-12-04 06:08:30 +01:00
Christian Muehlhaeuser
c08de32713 * Added a few overlay info messages. 2011-12-04 06:08:20 +01:00
Christian Muehlhaeuser
5cd69c4a2a * Merged from master. 2011-12-04 06:07:40 +01:00
Leo Franchi
5a2ea98bce Remove upcoming tracks not from selected but from playing item 2011-12-04 06:06:45 +01:00
Leo Franchi
e231a13066 Update the tree on mac after /Volumes is shown to avoid a race condition 2011-12-04 06:06:33 +01:00
Christian Muehlhaeuser
06f597ab1f * Merged from master. 2011-12-04 06:05:38 +01:00
Christian Muehlhaeuser
c8ce81bdb0 * Merged from master. 2011-12-04 06:02:18 +01:00
Christian Muehlhaeuser
f1cc16be15 * Updated german and english translations. 2011-12-04 06:00:48 +01:00
Dominik Schmidt
d42eb6d364 Add MimeType=x-scheme-handler/tomahawk to tomahawk.desktop 2011-11-29 13:45:56 +01:00
Christian Muehlhaeuser
ba4fa88a65 * Fixed a few more translations. Could fix TWK-591. 2011-11-24 08:28:48 +01:00
Frank Osterfeld
caa64f9e89 * Merge warning fixes. 2011-11-24 08:27:40 +01:00
Christian Muehlhaeuser
a05972e9ce * Fixed merge. 2011-11-24 02:47:15 +01:00
Christian Muehlhaeuser
5157e13ba1 * Updated ChangeLog. 2011-11-24 01:48:58 +01:00
Christian Muehlhaeuser
9f97afc148 * Updated ChangeLog. 2011-11-24 01:47:48 +01:00
Christian Muehlhaeuser
8b1b0091c6 * Updated ChangeLog. 2011-11-24 01:46:42 +01:00
Christian Muehlhaeuser
3e9aee3687 * Use default locale if translation can't be found. 2011-11-24 01:35:10 +01:00
Christian Muehlhaeuser
48bb0a82f9 * Disable UbuntuUnityHack until it's working properly. 2011-11-24 01:35:03 +01:00
Christian Muehlhaeuser
1efdf38085 * Disable german translation for 0.3.2 release. Needs be updated. 2011-11-24 01:20:01 +01:00
Christian Muehlhaeuser
3e4f4d2f38 * Updated verison to 0.3.2. 2011-11-23 23:31:02 +01:00
Jason Herskowitz
a2f870f2b8 Update changelog 2011-11-23 23:26:35 +01:00
Christian Muehlhaeuser
2ac167d438 * Support .oga files (ogg mimetype). 2011-11-23 23:26:21 +01:00
Christian Muehlhaeuser
c218695a3d * Prevent stuck now playing indicator. 2011-11-23 23:26:13 +01:00
Christian Muehlhaeuser
fae5f1dbbe * Should hopefully fix Windows SettingsDialog. 2011-11-23 23:25:57 +01:00
Christian Muehlhaeuser
54d29cc05d * Try fixing SettingsDialog on Windows. 2011-11-23 23:25:45 +01:00
Christian Muehlhaeuser
5aea02def2 * Forgot to rename crash reporter in one more place. 2011-11-23 23:25:35 +01:00
Christian Muehlhaeuser
368aa20b75 * Updated new crash reporter binary name in release scripts. 2011-11-23 23:25:26 +01:00
Christian Muehlhaeuser
d2a07f2b6c * Call ensurePolished before creating buttons in SettingsDialog. 2011-11-23 23:25:08 +01:00
Christian Muehlhaeuser
14253a9c66 * DRY: Cleaned up DropJob / ShortenedLinkParser & handling spoti.fi urls now. 2011-11-23 23:25:02 +01:00
Christian Muehlhaeuser
6881f4218a * Moved charts & spotify parser to port 80. 2011-11-23 23:23:57 +01:00
Christian Muehlhaeuser
17badb972e * Prevented over-zealous assert in PlaylistModel. 2011-11-23 23:23:50 +01:00
Christian Muehlhaeuser
2ea09dd60d * Merged version check. 2011-11-23 23:22:00 +01:00
Christian Muehlhaeuser
87f7b6b2c6 * Made sure we don't duplicate connections in WelcomeWidget. 2011-11-23 23:15:52 +01:00
Christian Muehlhaeuser
01986a4129 * Use the proper color for selected playlist items on the Dashboard. 2011-11-23 23:15:43 +01:00
Christian Muehlhaeuser
2b404b517f * Use the proper highlight color for painting hovered artist names in the AlbumItemDelegate. 2011-11-23 23:15:32 +01:00
Christian Muehlhaeuser
b21b2d10f7 * Update SourceInfoWidget when collection changes. 2011-11-23 23:15:22 +01:00
Christian Muehlhaeuser
04deaba788 * Less furious logging. 2011-11-23 23:15:10 +01:00
Christian Muehlhaeuser
5cabc62733 * Update recent additions on welcome page whenever a collection changes. 2011-11-23 23:15:02 +01:00
Kuba Serafinowski
01c6c3f0b6 moar strings to translate! 2011-11-23 23:14:42 +01:00
Kuba Serafinowski
b1a5cd4dcb remove unneeded strings 2011-11-23 23:14:28 +01:00
Kuba Serafinowski
58f78725db tiny typo fix 2011-11-23 23:14:11 +01:00
Jeff Mitchell
4210e8eab8 Hopefully fix a case where the seek slider travels on when Phonon is
buffering
2011-11-23 23:13:49 +01:00
Thierry Goeckel
115492d1cc Enhance version upgrading to include a third point. 2011-11-23 23:13:21 +01:00
Leo Franchi
edadbb0c95 Fix loading XSPFs with spaces in their name. 2011-11-23 23:13:11 +01:00
Christian Muehlhaeuser
6c67dfcab7 * Revert back to using system locale. 2011-11-23 23:12:50 +01:00
Christian Muehlhaeuser
b9453ab77b * Add a default english translation. Fallback to 'en' if locale is set to 'C'. 2011-11-23 23:12:39 +01:00
Christian Muehlhaeuser
9507ffdd86 * Fixed translation issue in TomahawkUtils. 2011-11-23 23:12:26 +01:00
Christian Muehlhaeuser
ff768954f6 * Fixed window title in AudioControls. 2011-11-23 23:12:17 +01:00
Christian Muehlhaeuser
15729bb66a * Increased size of Get-New-Resolvers dialog. 2011-11-23 23:12:01 +01:00
Christian Muehlhaeuser
41f46aaeea * Cleanup scanner if there were no new and no obsolete tracks found. 2011-11-23 23:11:53 +01:00
Christian Muehlhaeuser
9e0d884f80 * Merge musicscanner changes into stable. 2011-11-23 23:11:16 +01:00
Christian Muehlhaeuser
d34491b85f * Re-enable grouping of dynamic playlist revisions. 2011-11-23 23:10:34 +01:00
Christian Muehlhaeuser
45070fb4e1 * Remove bottom label of steering controls. Changes now take effect on clicking the apply button. 2011-11-23 23:10:27 +01:00
Christian Muehlhaeuser
18612b48d3 * Don't remove current index when restarting a track by activating it directly.
* Don't create new playlist revisions for a list that doesn't belong to you.
2011-11-23 23:10:18 +01:00
Christian Muehlhaeuser
a38c0a544d * Fixed crashing on playing from queue. 2011-11-23 23:10:06 +01:00
Christian Muehlhaeuser
d38c9730fb * Merge into stable. 2011-11-23 23:09:32 +01:00
Christian Muehlhaeuser
d25320833c * Merged into stable. 2011-11-23 23:06:02 +01:00
Christian Muehlhaeuser
d38600dd6a * Don't overwrite friendlyname with an empty one. 2011-11-23 23:05:23 +01:00
Christian Muehlhaeuser
6fa48587e1 * Assert on empty friendlynames. 2011-11-23 23:05:12 +01:00
Leo Franchi
8da0f3e9a3 * Merged into stable. 2011-11-23 23:04:58 +01:00
Kilian Lackhove
ab402c0867 fix xspf import QFileDialog filter 2011-11-23 23:00:43 +01:00
Kuba Serafinowski
545a915439 fix TWK-583 for jabber too 2011-11-23 23:00:31 +01:00
Kuba Serafinowski
d026902d91 fix for TWK-583 2011-11-23 23:00:25 +01:00
Hugo Lindström
ff72157c5f Fix for broken compile 2011-11-23 23:00:05 +01:00
Christian Muehlhaeuser
faab306dbe * Merged friendlyname fixes. 2011-11-23 22:59:57 +01:00
Christian Muehlhaeuser
57fef9f3f2 * Fixed WelcomeWidget. 2011-11-23 22:57:44 +01:00
Leo Franchi
89fac77951 Fix one compile error 2011-11-23 22:57:36 +01:00
Christian Muehlhaeuser
ef02e9b4ac * Refactored Track-, Collection-, PlaylistModel. 2011-11-23 22:57:24 +01:00
Leo Franchi
99b09c1faa Increment job count when creating a new xspf job 2011-11-23 22:55:17 +01:00
Kuba Serafinowski
d66e86f5c6 make the string extract with lupdate 2011-11-23 22:54:59 +01:00
Kuba Serafinowski
9bd46984e0 match the text with buttons in the dialog 2011-11-23 22:54:51 +01:00
Hugo Lindström
3992392245 * Merge appending XSPFs. 2011-11-23 22:54:32 +01:00
Hugo Lindström
198e92bc2c Fix for local xspf dropjob, also allow remotes 2011-11-23 22:53:22 +01:00
Kuba Serafinowski
2f899eed2a fix misleading cmake message 2011-11-23 22:52:49 +01:00
Jeff Mitchell
8cdd4bdea3 Do the connection name fixing in a different way; always end up with a
QHostAddress.
2011-11-23 22:52:39 +01:00
Jeff Mitchell
3d53b0c251 Remove some debugging 2011-11-23 22:52:23 +01:00
Jeff Mitchell
0ac9512eb9 Lots of debug and half the fixes for fixing hostnames 2011-11-23 22:52:15 +01:00
Jeff Mitchell
3f0ac7c666 * Merge application proxy factory. 2011-11-23 22:52:13 +01:00
Christian Muehlhaeuser
faf7d00fdd * Fixed TWK-579: Proper default width for the sidebar. 2011-11-23 22:50:32 +01:00
Christian Muehlhaeuser
b31abb0979 * This should fix sources being stuck in 'Parsing'. 2011-11-23 22:50:25 +01:00
Thierry Göckel
f2009cf99b Fix returning of external IP address for some routers. 2011-11-23 22:49:29 +01:00
Hugo Lindström
0d97a47cc5 Add cache for all charts. Later on move spotify and hypem to charts api. 2011-11-23 22:49:17 +01:00
Hugo Lindström
7db6beb896 Adding cache for charts 2011-11-23 22:48:54 +01:00
Christian Muehlhaeuser
e56a629ad7 * Fixed negative time values showing up in GUI. 2011-11-23 22:48:28 +01:00
Christian Muehlhaeuser
ef918bbbcf * Make SetPlaylistRevision DBCmds groupable. 2011-11-23 22:48:13 +01:00
Christian Muehlhaeuser
60911ab887 * Set stats for the right collection. 2011-11-23 22:47:49 +01:00
Christian Muehlhaeuser
e10a96ecd5 * Merged groupable db-commands. 2011-11-23 22:47:17 +01:00
Christian Muehlhaeuser
e99973925a * Merged improved collection syncing. 2011-11-23 22:45:52 +01:00
Dominik Schmidt
949c6f6341 Unbreak FindCLucene for Fedora 16 and openSUSE Factory. 2011-11-23 06:35:39 +01:00
Dominik Schmidt
e041723ffc Install CrashReporter 2011-11-23 06:07:54 +01:00
Christian Muehlhaeuser
89919928da * Look for CrashReporter in local and global dirs. 2011-11-23 05:49:34 +01:00
Leo Franchi
d4fc504f3d Add a 0.3.2 changelog 2011-11-20 22:52:11 -05:00
Leo Franchi
05924b8deb TWK-531: Show (-) on new item after deleting an item 2011-11-20 22:43:20 -05:00
Leo Franchi
6d4aa50596 Clear upcoming station tracks when steering, and re-fetch two 2011-11-20 22:43:08 -05:00
Leo Franchi
7ee2755617 use QFileSystemModel instead of deprecated QDirModel, and show /Volumes on mac 2011-11-20 22:43:00 -05:00
Leo Franchi
35406ceb5a Use plugins/ instead of PlugIns/ as vlc hard-codes it internally. 2011-11-20 22:42:52 -05:00
Leo Franchi
9efb536e55 Show tooltip with full text in job view 2011-11-20 22:42:30 -05:00
Leo Franchi
b8d27f1811 Make clicking back to current track work on dashboard, charts, and artist/album pages 2011-11-20 22:42:23 -05:00
Leo Franchi
0939ba0705 Don't show speaker next to a playlist if not paused or playing 2011-11-20 22:42:03 -05:00
Leo Franchi
3788bc7cbf Always clear spinner when no albums found to load in albumview 2011-11-20 22:41:52 -05:00
Leo Franchi
54723abc07 Only show JS errors in tomahawk debug builds 2011-11-20 22:41:36 -05:00
Leo Franchi
900f57437f Put delcaration in ifdef 2011-11-20 22:40:51 -05:00
Leo Franchi
300c9d5d68 Automatically upgrade resolvers 2011-11-20 22:40:44 -05:00
Leo Franchi
96c9996284 Set the timer with track duration calculated in 2011-11-17 09:49:43 -05:00
Leo Franchi
8a15bcaa66 fix rdio track loading 2011-11-17 09:49:16 -05:00
Leo Franchi
d17d67869c Add an "apply steering" button to make it clearer how to steer
Remove some super spammy debug
2011-11-17 09:49:11 -05:00
Leo Franchi
c491f33ce4 Manually replace + with " " as QUrl::queryItems doesn't do it for us... 2011-11-17 09:49:06 -05:00
Leo Franchi
1dee5c809c Don't hook up signals twice for loading xspf 2011-11-17 09:49:00 -05:00
Leo Franchi
924ede61b4 Make surer to show playlist once loaded 2011-11-17 09:48:52 -05:00
Leo Franchi
0d64d9c42d Don't show drop indicator for playlists in sidebar and always create new ones 2011-11-17 09:48:44 -05:00
Leo Franchi
6b6fb909cd Make source visible in audiocontrols on os x 2011-11-17 09:48:35 -05:00
Leo Franchi
b51ff46085 Don't create QNRs for null urls, let audioengine handle it properly 2011-11-17 09:48:07 -05:00
Leo Franchi
46ec23990f Revert "Skip to next track if we have a QNR and it emits a failed signal"
This reverts commit 9418fd0fb8.
2011-11-17 09:47:59 -05:00
Jeff Mitchell
eb46feac2c Handle the worker/cache threads better in InfoSystem, and re-enable
deletion on shutdown, so we can test in windows nightlies.
2011-11-16 20:19:13 -05:00
Leo Franchi
2c206f4193 Shrink font for playlist author 2011-11-14 18:07:56 -05:00
Leo Franchi
c1bd19b35b Don't accept button press events as well as release when handling latches 2011-11-14 18:06:58 -05:00
Jeff Mitchell
370154cc46 hacky fix for Jreen needing the application proxy set. Really we need to
get them to accept their own QNAM
2011-11-14 18:06:50 -05:00
Leo Franchi
9a81ce8b89 Add 0.3.1 fixes to Changelog 2011-11-13 14:07:37 -05:00
Christian Muehlhaeuser
c805d283d4 * Updated ChangeLog and bumped version to 0.3.1. 2011-11-13 19:25:53 +01:00
Christian Muehlhaeuser
03379f361c * Force an index update after 0.3.1 upgrade. 2011-11-13 19:19:36 +01:00
Christian Muehlhaeuser
c671c0e898 * 'Fixed' Windows shutdown crash. 2011-11-13 19:19:25 +01:00
Christian Muehlhaeuser
edaf49b4c5 * Fixed creating index when there is only a local source. 2011-11-13 19:19:02 +01:00
Christian Muehlhaeuser
682903b0cb * Prevent watch for changes interfering with running scan. 2011-11-13 19:18:49 +01:00
Dominik Schmidt
53f7f599d5 Update ChangeLog 2011-11-13 17:31:16 +01:00
Dominik Schmidt
cc669fc20f Remove unneccessary toString conversion 2011-11-13 17:26:43 +01:00
Dominik Schmidt
4e7496a38a Search for *_tomahawkresolver in CMAKE_INSTALL_LIBEXECDIR 2011-11-13 15:40:39 +01:00
Leo Franchi
5842cdceee Only do setenv on linux, that's theonly time we'll have unity anyway
(cherry picked from commit 09a7d790ad)
2011-11-12 10:04:31 -05:00
Leo Franchi
b7e0be8d9d Hide red latch headphones on local source if the source you are latched on to goes offline
(cherry picked from commit d49a43709d)
2011-11-12 10:04:25 -05:00
Leo Franchi
a203b60cbb Add Unity systray hack from Clementine.
(cherry picked from commit 96fe10cc9f)
2011-11-12 10:04:20 -05:00
Leo Franchi
2be08af321 Draw the author name as well as avatar in recent playlists
(cherry picked from commit 2a27cbde0d)
2011-11-12 10:04:12 -05:00
Leo Franchi
ad4c229a6b Don't show in global menu in unity. Thanks davidsansome :)
(cherry picked from commit 1f10444d5c)
2011-11-12 10:04:06 -05:00
Leo Franchi
b2e0206e34 Be a bit more resilient in setting the playlist to rename after creating
(cherry picked from commit 1bb8ff97d4)
2011-11-12 10:04:00 -05:00
Leo Franchi
743ae013ea Don't select a temp item when deleting it
(cherry picked from commit 518546b525)
2011-11-12 10:03:54 -05:00
Leo Franchi
767cf7c1b9 Hide warning
(cherry picked from commit 17e1003714)
2011-11-12 10:03:47 -05:00
Leo Franchi
6be94ab81c Stop the timer on new track starting
(cherry picked from commit 3c024ab7ac)
2011-11-12 10:02:03 -05:00
Leo Franchi
b1ed304a61 Fix crash on Sparkle update when binary is replaced.
(cherry picked from commit f9b5bda925)
2011-11-11 11:04:30 -05:00
217 changed files with 15400 additions and 2579 deletions

View File

@@ -16,7 +16,7 @@ SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
SET( TOMAHAWK_VERSION_MAJOR 0 )
SET( TOMAHAWK_VERSION_MINOR 3 )
SET( TOMAHAWK_VERSION_PATCH 0 )
SET( TOMAHAWK_VERSION_PATCH 3 )
#SET( TOMAHAWK_VERSION_RC 0 )
@@ -108,7 +108,7 @@ macro_optional_find_package(LibAttica)
macro_log_feature(LIBATTICA_FOUND "libattica" "Provides support for automatic fetching and managing of resolvers from the tomahawk website" "https://projects.kde.org/projects/kdesupport/attica" FALSE "" "")
macro_optional_find_package(QuaZip)
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers autmatically. Will build internal copy instead." "http://quazip.sourceforge.net/" FALSE "" "")
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically." "http://quazip.sourceforge.net/" FALSE "" "")
IF( NOT QuaZip_FOUND )
add_subdirectory( ${CMAKE_SOURCE_DIR}/src/libtomahawk/thirdparty/quazip )
@@ -116,6 +116,7 @@ IF( NOT QuaZip_FOUND )
SET( QuaZip_LIBRARY quazip )
SET( QuaZip_LIBRARIES ${QuaZip_LIBRARY} )
SET( QuaZip_FOUND true )
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically. Building internal copy" "http://quazip.sourceforge.net/" FALSE "" "")
# copy headers to build/quazip so we can use proper includes inside the code
FILE( COPY ${CMAKE_SOURCE_DIR}/src/libtomahawk/thirdparty/quazip/quazip/ DESTINATION ${CMAKE_BINARY_DIR}/libtomahawk/thirdparty/quazip )
@@ -211,4 +212,7 @@ ADD_SUBDIRECTORY( src/libtomahawk )
SET( TOMAHAWK_LIBRARIES tomahawklib )
ADD_SUBDIRECTORY( src )
ADD_SUBDIRECTORY( admin )
ADD_SUBDIRECTORY( src/breakpad/CrashReporter )
IF( NOT DISABLE_CRASHREPORTER )
ADD_SUBDIRECTORY( src/breakpad/CrashReporter )
ENDIF()

View File

@@ -2,6 +2,7 @@
# This module looks for clucene (http://clucene.sf.net) support
# It will define the following values
#
# CLUCENE_INCLUDE_DIRS = CLUCENE_INCLUDE_DIR + CLUCENE_LIBRARY_DIR
# CLUCENE_INCLUDE_DIR = where CLucene/StdHeader.h can be found
# CLUCENE_LIBRARY_DIR = where CLucene/clucene-config.h can be found
# CLUCENE_LIBRARIES = the libraries to link against CLucene
@@ -17,6 +18,7 @@ FIND_PACKAGE(CLuceneUnstable)
IF(CLUCENEUNSTABLE_FOUND)
SET(CLucene_FOUND TRUE)
SET(CLUCENE_INCLUDE_DIR ${CLUCENE_UNSTABLE_INCLUDE_DIRS})
SET(CLUCENE_INCLUDE_DIRS ${CLUCENE_INCLUDE_DIR})
SET(CLUCENE_LIBRARIES ${CLUCENE_UNSTABLE_LIBS})
#MESSAGE(FATAL_ERROR NARF)
@@ -106,7 +108,9 @@ ENDIF (CLUCENE_LIBRARY_DIR)
IF(CLUCENE_INCLUDE_DIR AND CLUCENE_LIBRARIES AND CLUCENE_LIBRARY_DIR AND CLUCENE_GOOD_VERSION)
SET(CLucene_FOUND TRUE)
SET(CLUCENE_INCLUDE_DIRS ${CLUCENE_LIBRARY_DIR} ${CLUCENE_INCLUDE_DIR})
ENDIF(CLUCENE_INCLUDE_DIR AND CLUCENE_LIBRARIES AND CLUCENE_LIBRARY_DIR AND CLUCENE_GOOD_VERSION)
ENDIF(CLUCENEUNSTABLE_FOUND)
IF(CLucene_FOUND)
@@ -120,6 +124,7 @@ ELSE(CLucene_FOUND)
ENDIF(CLucene_FOUND)
MARK_AS_ADVANCED(
CLUCENE_INCLUDE_DIRS
CLUCENE_INCLUDE_DIR
CLUCENE_LIBRARY_DIR
CLUCENE_LIBRARIES

View File

@@ -0,0 +1,182 @@
# - Define GNU standard installation directories
# Provides install directory variables as defined for GNU software:
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
# Inclusion of this module defines the following variables:
# CMAKE_INSTALL_<dir> - destination for files of a given type
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
# where <dir> is one of:
# BINDIR - user executables (bin)
# SBINDIR - system admin executables (sbin)
# LIBEXECDIR - program executables (libexec)
# SYSCONFDIR - read-only single-machine data (etc)
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
# LOCALSTATEDIR - modifiable single-machine data (var)
# LIBDIR - object code libraries (lib or lib64)
# INCLUDEDIR - C header files (include)
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
# DATAROOTDIR - read-only architecture-independent data root (share)
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
# INFODIR - info documentation (DATAROOTDIR/info)
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
# MANDIR - man documentation (DATAROOTDIR/man)
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION options of
# install() commands for the corresponding file type. If the includer does
# not define a value the above-shown default will be used and the value will
# appear in the cache for editing by the user.
# Each CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
# from the corresponding destination by prepending (if necessary) the value
# of CMAKE_INSTALL_PREFIX.
#=============================================================================
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
# Copyright 2011 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# Installation directories
#
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(_LIBDIR_DEFAULT "lib")
# Override this default 'lib' with 'lib64' iff:
# - we are on Linux system but NOT cross-compiling
# - we are NOT on debian
# - we are on a 64 bits system
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
# Note that the future of multi-arch handling may be even
# more complicated than that: http://wiki.debian.org/Multiarch
if(CMAKE_SYSTEM_NAME MATCHES "Linux"
AND NOT CMAKE_CROSSCOMPILING
AND NOT EXISTS "/etc/debian_version")
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
message(AUTHOR_WARNING
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
"Please enable at least one language before including GNUInstallDirs.")
else()
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(_LIBDIR_DEFAULT "lib64")
endif()
endif()
endif()
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
endif()
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
endif()
#-----------------------------------------------------------------------------
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
# the cache and store the defaults in local variables if the cache values are
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
if(NOT CMAKE_INSTALL_DATADIR)
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
endif()
if(NOT CMAKE_INSTALL_INFODIR)
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
endif()
if(NOT CMAKE_INSTALL_LOCALEDIR)
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
endif()
if(NOT CMAKE_INSTALL_MANDIR)
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
endif()
if(NOT CMAKE_INSTALL_DOCDIR)
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
endif()
#-----------------------------------------------------------------------------
mark_as_advanced(
CMAKE_INSTALL_BINDIR
CMAKE_INSTALL_SBINDIR
CMAKE_INSTALL_LIBEXECDIR
CMAKE_INSTALL_SYSCONFDIR
CMAKE_INSTALL_SHAREDSTATEDIR
CMAKE_INSTALL_LOCALSTATEDIR
CMAKE_INSTALL_LIBDIR
CMAKE_INSTALL_INCLUDEDIR
CMAKE_INSTALL_OLDINCLUDEDIR
CMAKE_INSTALL_DATAROOTDIR
CMAKE_INSTALL_DATADIR
CMAKE_INSTALL_INFODIR
CMAKE_INSTALL_LOCALEDIR
CMAKE_INSTALL_MANDIR
CMAKE_INSTALL_DOCDIR
)
# Result directories
#
foreach(dir
BINDIR
SBINDIR
LIBEXECDIR
SYSCONFDIR
SHAREDSTATEDIR
LOCALSTATEDIR
LIBDIR
INCLUDEDIR
OLDINCLUDEDIR
DATAROOTDIR
DATADIR
INFODIR
LOCALEDIR
MANDIR
DOCDIR
)
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
else()
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
endif()
endforeach()

View File

@@ -273,7 +273,7 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
;Main executable.
File "${INSTALL_PATH}\bin\tomahawk.exe"
File "${INSTALL_PATH}\bin\CrashReporter.exe"
File "${INSTALL_PATH}\bin\tomahawk_crash_reporter.exe"
File "${INSTALL_PATH}\bin\libtomahawk_breakpad.dll"
File "${INSTALL_PATH}\bin\libqxtweb-standalone.dll"
@@ -287,7 +287,7 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
;Main executable.
File "${BUILD_PATH}\tomahawk.exe"
File "${BUILD_PATH}\CrashReporter.exe"
File "${BUILD_PATH}\tomahawk_crash_reporter.exe"
File "${BUILD_PATH}\libtomahawk_breakpad.dll"
File "${BUILD_PATH}\libtomahawklib.dll"
@@ -329,12 +329,6 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
File "${MING_BIN}\libstdc++-6.dll"
;Phonon stuff
;Fix the phonon build to not use Dbus
File "${QT_DLL_PATH}\QtDbus4.dll"
File "${MING_BIN}\libdbus-1-3.dll"
File "${MING_BIN}\dbus-daemon.exe"
File "${VLC_BIN}\libphonon.dll"
SetOutPath "$INSTDIR\phonon_backend"
File "${VLC_BIN}\phonon_backend\phonon_vlc.dll"
@@ -347,12 +341,6 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
SetOutPath "$INSTDIR\plugins"
File /r "${VLC_PLUGIN_PATH}\*.dll"
SetOutPath "$INSTDIR"
File "${MING_BIN}\libmad-0.dll" ; MP3
File "${MING_BIN}\libFLAC-8.dll" ; FLAC
File "${MING_BIN}\libogg-0.dll" ; OGG, FLAC
File "${MING_BIN}\libvorbis-0.dll" ; OGG
File "${MING_BIN}\libvorbisenc-2.dll" ; OGG
; Other
File "${MING_BIN}\libqjson.dll"
@@ -467,7 +455,8 @@ Section -post
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "NoRepair" "1"
; Register tomahawk:// protocol handler
WriteRegStr HKCR "tomahawk" "" "URL: Tomahawk Protocol"
WriteRegStr HKCR "tomahawk" "" "URL:Tomahawk Protocol"
WriteRegStr HKCR "tomahawk" "URL Protocol" ""
WriteRegStr HKCR "tomahawk\DefaultIcon" "" $INSTDIR\tomahawk.exe,1
WriteRegStr HKCR "tomahawk\shell" "" "open"
WriteRegStr HKCR "tomahawk\shell\open\command" "" '"$INSTDIR\tomahawk.exe" "%1"'

View File

@@ -1,3 +1,54 @@
Version 0.3.3:
* Automatically load Super Collection tracks when no official release
information is available.
* Fixed stations not fetching new tracks under certain circumstances.
* Fixed Footnotes not always updating when selecting a new track.
* Added support for ow.ly, fb.me, itun.es and tinyurl.com URL shorteners.
* Fixed playback issues with non-latin filenames on Windows.
* Fixed tomahawk:// protocol not working properly on Windows.
* Fixed dupe menu entry appearing on OS X.
* Fixed invisible sidebar items on Linux.
Version 0.3.2:
* Improved syncing process, it's faster and more reliable now.
* Fixed UPnP issues.
* Fixed not updating collections and views after a collection changes.
* Fixed not showing a source's proper name at all times.
* Improved music scanner reliability.
* Fixed various labels not being painted in the right color when selected.
* Support .oga (ogg mimetype) files.
* Fixed stuck Now Playing indicator icon.
* Fixed sidebar width of settings dialog on Windows.
* Fixed not always showing delete icon on hovered temporary pages.
* Fixed inability to select externally mounted drives.
* Fixed bug where speaker would be stuck next to a playlist.
* Fixed bug where first startup would show a loading spinner in the
Dashboard's "Recent Additions" forever.
* Automatically upgrade resolvers when an update is found.
* Fixed last played track of a friend never expiring.
* Fixed parsing of rdio tracks.
* Changed steering mechanism in stations to be user-friendlier.
* Fixed loading biographies of artist names with special characters.
* Fixed behaviour of dropping Spotify playlists on the sidebar.
* Fixed hard to read source-name in the audio control area on OS X.
* Fixed crashes when playing Grooveshark tracks.
* Fixed bug where clicking the latch button would flicker and unlatch.
* Fixed Jabber accounts not connecting properly when proxy is in use.
Version 0.3.1:
* Fixed not resolving to local files.
* Fixed shutdown crash on Windows.
* Support more widget types in Javascript resolver configs.
* Fixed bug where red headphone would be visible on My Collection
when listened along to source went offline.
* Draw author name as well as avatar in recently played playlists.
* Fixed Tomahawk integration in Unity.
* Fixed incorrect item selected in source tree when deleting temporary
pages.
* Fixed currently played label disappearing after 10 minutes regardless
of length of track.
* Fixed crash on Sparkle upgrade on OS X.
Version 0.3.0:
* Make artist names in the album view clickable.
* Don't start playing if a tomahawk:// link was clicked while Tomahawk
@@ -28,7 +79,7 @@ Version 0.3.0:
* Added new job status view in the bottom of the source list that displays
current jobs such as resolving, parsing playlists, and loading from
database.
* Parse and convert a Spotify playlist url when dropped anywhere on the
* Parse and convert a Spotify playlist URL when dropped anywhere on the
sidebar.
* Convert resolvers to use asynchronous calls to avoid blocking Tomahawk's
UI, greatly increasing responsiveness of Tomahawk while resolving.

View File

@@ -250,7 +250,7 @@ frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks')
commands.append(['mkdir', '-p', frameworks_dir])
resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
commands.append(['mkdir', '-p', resources_dir])
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns')
plugins_dir = os.path.join(bundle_dir, 'Contents', 'plugins')
binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name)
fixed_libraries = []
@@ -502,9 +502,9 @@ except:
print 'Failed to find spotify resolver'
try:
FixPlugin('CrashReporter', '../MacOS')
FixPlugin('tomahawk_crash_reporter', '../MacOS')
except:
print 'Failed to find CrashReporter'
print 'Failed to find tomahawk_crash_reporter'
for plugin in QT_PLUGINS:
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))

View File

@@ -4,8 +4,9 @@ Version=1.0
Name=Tomahawk
GenericName=Music Player
TryExec=tomahawk
Exec=tomahawk
Exec=tomahawk %u
Comment=Tomahawk - Social Music Player
Icon=tomahawk
Terminal=false
Categories=Qt;AudioVideo;Audio;Player;
MimeType=x-scheme-handler/tomahawk;

View File

@@ -1,22 +1,31 @@
#!/bin/bash
echo "Remove old vlc dir..."
mkdir -p vlc/
if [ "$1" = "-c" ] ; then
echo "Continuing last download.."
rm -rvf vlc/prefix/
else
echo "Remove old vlc dir..."
rm -rvf vlc/*
fi
cd vlc/
#rm -vf vlc-*.7z
#rm -rf vlc/
echo "Download specified binary..."
echo "Download phonon archive..."
#wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb"
#wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip"
wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
#wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
wget -c http://people.videolan.org/~jb/phonon/phonon_phonon-vlc_20111128.7z
echo "Extract binary..."
7z x phonon-vlc-last.7z
7z x phonon*.7z
#mv -v vlc-*/ vlc/
#unzip tomahawk-vlc-0.1.zip
echo "Download phonon_vlc_no_video.dll..."
wget -c http://people.videolan.org/~jb/phonon/phonon_vlc_no_video.dll
cp -v phonon_vlc_no_video.dll prefix/bin/phonon_backend/phonon_vlc.dll
echo "Strip unneeded plugins from vlc/plugins..."
cd prefix/bin/plugins
rm -rvf libold* libvcd* libdvd* liblibass* libx264* libschroe* liblibmpeg2* \

BIN
data/images/apply-check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load Diff

3180
lang/tomahawk_en.ts Normal file

File diff suppressed because it is too large Load Diff

3017
lang/tomahawk_es.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,8 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/lang">
<file>tomahawk_en.qm</file>
<file>tomahawk_es.qm</file>
<file>tomahawk_de.qm</file>
<file>tomahawk_pl.qm</file>
</qresource>
</RCC>

3218
lang/tomahawk_pl.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -98,6 +98,7 @@
<file>data/images/track-icon-22x22.png</file>
<file>data/images/track-icon-32x32.png</file>
<file>data/images/track-icon-16x16.png</file>
<file>data/images/apply-check.png</file>
<file>data/stylesheets/topbar-radiobuttons.css</file>
<file>data/icons/tomahawk-icon-16x16.png</file>
<file>data/icons/tomahawk-icon-32x32.png</file>

View File

@@ -40,6 +40,7 @@ SET( tomahawkSources ${tomahawkSources}
musicscanner.cpp
shortcuthandler.cpp
scanmanager.cpp
ubuntuunityhack.cpp
tomahawkapp.cpp
main.cpp
)
@@ -85,6 +86,7 @@ SET( tomahawkHeaders ${tomahawkHeaders}
musicscanner.h
scanmanager.h
ubuntuunityhack.h
shortcuthandler.h
)

View File

@@ -22,7 +22,7 @@
#include "GetNewStuffDelegate.h"
#include "GetNewStuffModel.h"
GetNewStuffDialog::GetNewStuffDialog( QWidget *parent, Qt::WindowFlags f )
GetNewStuffDialog::GetNewStuffDialog( QWidget* parent, Qt::WindowFlags f )
: QDialog( parent, f )
, ui( new Ui::GetNewStuffDialog )
, m_model( new GetNewStuffModel( this ) )
@@ -37,16 +37,17 @@ GetNewStuffDialog::GetNewStuffDialog( QWidget *parent, Qt::WindowFlags f )
ui->listView->setMouseTracking( true );
setMinimumSize( 560, 350 );
#ifdef Q_WS_MAC
setMinimumSize( 510, 350 );
setMaximumSize( 510, 350 );
setMaximumSize( 560, 350 );
setSizeGripEnabled( false );
ui->listView->setAttribute( Qt::WA_MacShowFocusRect, false );
#endif
}
GetNewStuffDialog::~GetNewStuffDialog()
{
delete ui;

View File

@@ -34,9 +34,6 @@ LoadXSPFDialog::LoadXSPFDialog( QWidget* parent, Qt::WindowFlags f )
m_ui->verticalLayout->setSpacing( 0 );
#endif
connect( m_ui->buttonBox, SIGNAL( accepted() ), SLOT( accept() ) );
connect( m_ui->buttonBox, SIGNAL( rejected() ), SLOT( reject() ) );
connect( m_ui->navigateButton, SIGNAL( clicked( bool ) ), this, SLOT( getLocalFile() ) );
}
@@ -47,7 +44,7 @@ LoadXSPFDialog::~LoadXSPFDialog()
void
LoadXSPFDialog::getLocalFile()
{
QString url = QFileDialog::getOpenFileName( this, tr( "Load XSPF File" ), QDir::homePath(), ".xspf" );
QString url = QFileDialog::getOpenFileName( this, tr( "Load XSPF File" ), QDir::homePath(), tr( "XSPF Files (*.xspf)" ) );
m_ui->lineEdit->setText( url );
}

View File

@@ -19,9 +19,9 @@
#include "audiocontrols.h"
#include "ui_audiocontrols.h"
#include <QNetworkReply>
#include <QDropEvent>
#include <QMouseEvent>
#include <QtNetwork/QNetworkReply>
#include <QtGui/QDropEvent>
#include <QtGui/QMouseEvent>
#include "audio/audioengine.h"
#include "playlist/playlistview.h"
@@ -45,6 +45,7 @@ AudioControls::AudioControls( QWidget* parent )
, ui( new Ui::AudioControls )
, m_repeatMode( PlaylistInterface::NoRepeat )
, m_shuffled( false )
, m_lastSliderCheck( 0 )
{
ui->setupUi( this );
setAcceptDrops( true );
@@ -86,7 +87,11 @@ AudioControls::AudioControls( QWidget* parent )
ui->loveButton->setPixmap( RESPATH "images/not-loved.png" );
ui->loveButton->setCheckable( true );
#ifdef Q_WS_MAC
ui->ownerLabel->setForegroundRole( QPalette::Text );
#else
ui->ownerLabel->setForegroundRole( QPalette::Dark );
#endif
ui->metaDataArea->setStyleSheet( "QWidget#metaDataArea {\nborder-width: 4px;\nborder-image: url(" RESPATH "images/now-playing-panel.png) 4 4 4 4 stretch stretch; }" );
ui->seekSlider->setEnabled( true );
@@ -107,8 +112,8 @@ AudioControls::AudioControls( QWidget* parent )
connect( ui->volumeLowButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( lowerVolume() ) );
connect( ui->volumeHighButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( raiseVolume() ) );
connect( ui->playPauseButton, SIGNAL( clicked() ), this, SIGNAL( playPressed() ) );
connect( ui->pauseButton, SIGNAL( clicked() ), this, SIGNAL( pausePressed() ) );
connect( ui->playPauseButton, SIGNAL( clicked() ), SIGNAL( playPressed() ) );
connect( ui->pauseButton, SIGNAL( clicked() ), SIGNAL( pausePressed() ) );
connect( ui->repeatButton, SIGNAL( clicked() ), SLOT( onRepeatClicked() ) );
connect( ui->shuffleButton, SIGNAL( clicked() ), SLOT( onShuffleClicked() ) );
@@ -207,6 +212,9 @@ AudioControls::onPlaybackStarted( const Tomahawk::result_ptr& result )
ui->seekSlider->setVisible( true );
m_noTimeChange = false;
m_lastSliderCheck = 0;
Tomahawk::InfoSystem::InfoStringHash trackInfo;
trackInfo["artist"] = result->artist()->name();
trackInfo["album"] = result->album()->name();
@@ -285,9 +293,10 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
result->loadSocialActions();
connect( result.data(), SIGNAL( socialActionsLoaded() ), this, SLOT( socialActionsLoaded() ) );
connect( result.data(), SIGNAL( socialActionsLoaded() ), SLOT( socialActionsLoaded() ) );
}
void
AudioControls::socialActionsLoaded()
{
@@ -318,6 +327,7 @@ AudioControls::onPlaybackPaused()
m_sliderTimeLine.setPaused( true );
}
void
AudioControls::onPlaybackResumed()
{
@@ -363,7 +373,11 @@ AudioControls::onPlaybackStopped()
void
AudioControls::onPlaybackTimer( qint64 msElapsed )
{
//tDebug( LOGEXTRA ) << Q_FUNC_INFO << " msElapsed = " << msElapsed << " and timer current time = " << m_sliderTimeLine.currentTime() << " and m_seekMsecs = " << m_seekMsecs;
// tDebug( LOGEXTRA ) << Q_FUNC_INFO << "msElapsed =" << msElapsed << "and timer current time =" << m_sliderTimeLine.currentTime() << "and m_seekMsecs =" << m_seekMsecs;
if ( msElapsed > 0 && msElapsed - 500 < m_lastSliderCheck )
return;
m_lastSliderCheck = msElapsed;
if ( m_currentTrack.isNull() )
return;
@@ -373,9 +387,22 @@ AudioControls::onPlaybackTimer( qint64 msElapsed )
ui->timeLabel->setText( TomahawkUtils::timeToString( seconds ) );
ui->timeLeftLabel->setText( "-" + TomahawkUtils::timeToString( m_currentTrack->duration() - seconds ) );
if ( m_sliderTimeLine.currentTime() > msElapsed || m_seekMsecs != -1 )
if ( m_noTimeChange )
{
if ( m_sliderTimeLine.currentTime() != msElapsed )
{
m_noTimeChange = false;
m_sliderTimeLine.resume();
}
}
else if ( m_sliderTimeLine.currentTime() >= msElapsed || m_seekMsecs != -1 )
{
m_sliderTimeLine.setPaused( true );
m_noTimeChange = false;
if ( m_sliderTimeLine.currentTime() == msElapsed )
m_noTimeChange = true;
m_sliderTimeLine.setCurrentTime( msElapsed );
m_seekMsecs = -1;
if ( AudioEngine::instance()->state() != AudioEngine::Paused )
@@ -384,7 +411,7 @@ AudioControls::onPlaybackTimer( qint64 msElapsed )
else if ( m_sliderTimeLine.duration() > msElapsed && m_sliderTimeLine.state() == QTimeLine::NotRunning )
{
ui->seekSlider->setEnabled( AudioEngine::instance()->canSeek() );
m_sliderTimeLine.resume();
m_sliderTimeLine.start();
}
else if ( m_sliderTimeLine.state() == QTimeLine::Paused && AudioEngine::instance()->state() != AudioEngine::Paused )
{

View File

@@ -19,8 +19,8 @@
#ifndef AUDIOCONTROLS_H
#define AUDIOCONTROLS_H
#include <QWidget>
#include <QTimeLine>
#include <QtGui/QWidget>
#include <QtCore/QTimeLine>
#include "result.h"
#include "playlistinterface.h"
@@ -95,6 +95,8 @@ private:
QTimeLine m_sliderTimeLine;
qint64 m_seekMsecs;
qint64 m_lastSliderCheck;
bool m_noTimeChange;
};
#endif // AUDIOCONTROLS_H

View File

@@ -28,9 +28,6 @@
<height>80</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="topMargin">
<number>0</number>
@@ -164,9 +161,6 @@
<height>58</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>

View File

@@ -18,11 +18,17 @@
#include "BreakPad.h"
#include "config.h"
#include "utils/logger.h"
#include <QCoreApplication>
#include <QString>
#include <QFileInfo>
#include <string.h>
#define CRASH_REPORTER_BINARY "CrashReporter"
#define CRASH_REPORTER_BINARY "tomahawk_crash_reporter"
bool s_active = true;
#ifndef WIN32
#include <unistd.h>
@@ -38,8 +44,10 @@ LaunchUploader( const char* dump_dir, const char* minidump_id, void* that, bool
return false;
const char* crashReporter = static_cast<BreakPad*>(that)->crashReporter();
pid_t pid = fork();
if ( !s_active || strlen( crashReporter ) == 0 )
return false;
pid_t pid = fork();
if ( pid == -1 ) // fork failed
return false;
if ( pid == 0 )
@@ -63,14 +71,25 @@ LaunchUploader( const char* dump_dir, const char* minidump_id, void* that, bool
}
BreakPad::BreakPad( const QString& path )
BreakPad::BreakPad( const QString& path, bool active )
#ifdef Q_OS_LINUX
: google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true )
#else
: google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true, 0 )
#endif
{
QString reporter = QString( "%1/%2" ).arg( qApp->applicationDirPath() ).arg( CRASH_REPORTER_BINARY );
s_active = active;
QString reporter;
QString localReporter = QString( "%1/%2" ).arg( qApp->applicationDirPath() ).arg( CRASH_REPORTER_BINARY );
QString globalReporter = QString( "%1/%2" ).arg( CMAKE_INSTALL_PREFIX "/" CMAKE_INSTALL_LIBEXECDIR ).arg( CRASH_REPORTER_BINARY );
if ( QFileInfo( localReporter ).exists() )
reporter = localReporter;
else if ( QFileInfo( globalReporter ).exists() )
reporter = globalReporter;
else
tLog() << "Could not find \"" CRASH_REPORTER_BINARY "\" in \"" CMAKE_INSTALL_PREFIX "/" CMAKE_INSTALL_LIBEXECDIR "\" or application path";
char* creporter;
std::string sreporter = reporter.toStdString();
@@ -126,7 +145,7 @@ LaunchUploader( const wchar_t* dump_dir, const wchar_t* minidump_id, void* that,
si.wShowWindow = SW_SHOWNORMAL;
ZeroMemory( &pi, sizeof(pi) );
if (CreateProcess( NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
if ( CreateProcess( NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) )
{
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
@@ -137,9 +156,24 @@ LaunchUploader( const wchar_t* dump_dir, const wchar_t* minidump_id, void* that,
}
BreakPad::BreakPad( const QString& path )
BreakPad::BreakPad( const QString& path, bool active )
: google_breakpad::ExceptionHandler( path.toStdWString(), 0, LaunchUploader, this, true )
{
s_active = active;
}
#endif // WIN32
void
BreakPad::setActive( bool enabled )
{
s_active = enabled;
}
bool
BreakPad::isActive()
{
return s_active;
}

View File

@@ -32,11 +32,14 @@ class BreakPad : public google_breakpad::ExceptionHandler
const char* m_crashReporter; // again, const char[]
public:
BreakPad( const QString &dump_write_dirpath );
BreakPad( const QString& dump_write_dirpath, bool active );
~BreakPad()
{}
static void setActive( bool enabled );
static bool isActive();
void setProductName( const char* s ) { m_productName = s; };
const char* productName() const { return m_productName; }

View File

@@ -1,8 +1,10 @@
PROJECT( CrashReporter )
FIND_PACKAGE( Qt4 REQUIRED )
SET( QT_USE_QTNETWORK TRUE )
SET( crashreporter_SOURCES main.cpp CrashReporter.cpp )
SET( crashreporter_HEADERS CrashReporter.h )
SET( crashreporter_UI CrashReporter.ui )
@@ -16,5 +18,8 @@ INCLUDE( ${QT_USE_FILE} )
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src ../../libtomahawk )
ADD_DEFINITIONS( ${QT_DEFINITIONS} )
ADD_EXECUTABLE( CrashReporter WIN32 ${crashreporter_SOURCES} ${crashreporter_HEADERS_MOC} ${crashreporter_UI_HEADERS} ${crashreporter_RC_RCC} )
TARGET_LINK_LIBRARIES( CrashReporter ${QT_LIBRARIES} tomahawklib )
ADD_EXECUTABLE( tomahawk_crash_reporter WIN32 ${crashreporter_SOURCES} ${crashreporter_HEADERS_MOC} ${crashreporter_UI_HEADERS} ${crashreporter_RC_RCC} )
TARGET_LINK_LIBRARIES( tomahawk_crash_reporter ${QT_LIBRARIES} tomahawklib )
INCLUDE(GNUInstallDirs)
install(TARGETS tomahawk_crash_reporter RUNTIME DESTINATION ${CMAKE_INSTALL_LIBEXECDIR})

View File

@@ -9,6 +9,7 @@
#cmakedefine DEBUG_BUILD
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#define CMAKE_INSTALL_LIBEXECDIR "${CMAKE_INSTALL_LIBEXECDIR}"
#define CMAKE_SYSTEM "${CMAKE_SYSTEM}"
#cmakedefine LION

View File

@@ -44,7 +44,9 @@ AtticaManager::AtticaManager( QObject* parent )
connect( &m_manager, SIGNAL( providerAdded( Attica::Provider ) ), this, SLOT( providerAdded( Attica::Provider ) ) );
// resolvers
m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org:10480/resolvers/providers.xml" ) );
m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
qRegisterMetaType< Attica::Content >( "Attica::Content" );
}
@@ -149,6 +151,7 @@ AtticaManager::pathFromId( const QString& resolverId ) const
return m_resolverStates.value( resolverId ).scriptPath;
}
void
AtticaManager::uploadRating( const Content& c )
{
@@ -175,6 +178,7 @@ AtticaManager::uploadRating( const Content& c )
emit resolverStateChanged( c.id() );
}
bool
AtticaManager::userHasRated( const Content& c ) const
{
@@ -245,6 +249,7 @@ AtticaManager::resolverIconFetched()
m_resolverStates[ resolverId ].pixmap = icon;
}
void
AtticaManager::syncServerData()
{
@@ -271,62 +276,16 @@ AtticaManager::syncServerData()
if ( ( r.state == Installed || r.state == NeedsUpgrade ) &&
!upstream.version().isEmpty() )
{
if ( newerVersion( r.version, upstream.version() ) )
if ( TomahawkUtils::newerVersion( r.version, upstream.version() ) )
{
m_resolverStates[ id ].state = NeedsUpgrade;
QMetaObject::invokeMethod( this, "upgradeResolver", Qt::QueuedConnection, Q_ARG( Attica::Content, upstream ) );
}
}
}
}
}
bool
AtticaManager::newerVersion( const QString& older, const QString& newer ) const
{
// Dumb version comparison. Expects two strings, X.Y and Z.V. Returns true if Z > v || Z == V && V > Y
// DOES NOT support X.Y.Z version strings
if ( older.isEmpty() || newer.isEmpty() )
return false;
QPair<int, int> oldVer, newVer;
QStringList parts = older.split( "." );
if ( parts.size() == 1 )
{
oldVer.first = parts[ 0 ].toInt();
oldVer.second = 0;
}
else if ( parts.size() == 2 )
{
oldVer.first = parts[ 0 ].toInt();
oldVer.second = parts[ 1 ].toInt();;
}
else
return false;
parts = newer.split( "." );
if ( parts.size() == 1 )
{
newVer.first = parts[ 0 ].toInt();
newVer.second = 0;
}
else if ( parts.size() == 2 )
{
newVer.first = parts[ 0 ].toInt();
newVer.second = parts[ 1 ].toInt();;
}
else
return false;
// Do the comparison
if ( newVer.first > oldVer.first )
return true;
if ( newVer.first == oldVer.first &&
newVer.second > oldVer.second )
return true;
return false;
}
void
AtticaManager::installResolver( const Content& resolver )
@@ -347,6 +306,7 @@ AtticaManager::installResolver( const Content& resolver )
job->start();
}
void
AtticaManager::upgradeResolver( const Content& resolver )
{

View File

@@ -83,8 +83,6 @@ public:
ResolverState resolverState( const Attica::Content& resolver ) const;
QPixmap iconForResolver( const Attica::Content& id ); // Looks up in icon cache
void installResolver( const Attica::Content& resolver );
void upgradeResolver( const Attica::Content& resolver );
void uninstallResolver( const Attica::Content& resolver );
void uninstallResolver( const QString& pathToResolver );
QString pathFromId( const QString& resolverId ) const;
@@ -92,6 +90,9 @@ public:
void uploadRating( const Attica::Content& c );
bool userHasRated( const Attica::Content& c ) const;
public slots:
void installResolver( const Attica::Content& resolver );
void upgradeResolver( const Attica::Content& resolver );
signals:
void resolversReloaded( const Attica::Content::List& resolvers );
@@ -111,7 +112,6 @@ private slots:
void resolverIconFetched();
void syncServerData();
bool newerVersion( const QString& older, const QString& newer ) const;
private:
QString extractPayload( const QString& filename, const QString& resolverId ) const;
@@ -127,4 +127,8 @@ private:
static AtticaManager* s_instance;
};
#ifdef LIBATTICA_FOUND
Q_DECLARE_METATYPE( Attica::Content );
#endif
#endif // ATTICAMANAGER_H

View File

@@ -440,6 +440,7 @@ set( libHeaders
widgets/playlisttypeselectordlg.h
widgets/welcomewidget.h
widgets/whatshotwidget.h
widgets/whatshotwidget_p.h
widgets/RecentlyPlayedPlaylistsModel.h
widgets/RecentPlaylistsModel.h
widgets/OverlayButton.h
@@ -501,7 +502,7 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
${QJSON_INCLUDE_DIR}
${LIBECHONEST_INCLUDE_DIR}
${LIBECHONEST_INCLUDE_DIR}/..
${CLUCENE_INCLUDE_DIR}
${CLUCENE_INCLUDE_DIRS}
${PHONON_INCLUDES}
${CMAKE_BINARY_DIR}/thirdparty/liblastfm2/src

View File

@@ -342,7 +342,6 @@ EchonestCatalogSynchronizer::tracksRemoved( const QList< unsigned int >& trackId
foreach ( unsigned int id, trackIds )
{
tDebug() << "Deleting item with id:" << id;
Echonest::CatalogUpdateEntry e( Echonest::CatalogTypes::Delete );
e.setItemId( QString::number( id ).toLatin1() );
entries.append( e );

View File

@@ -42,7 +42,7 @@ ActionCollection::initActions()
m_actionCollection[ "latchOff" ] = new QAction( tr( "&Stop Listening Along" ), this );
bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening;
QAction *privacyToggle = new QAction( tr( QString( isPublic ? "&Listen Privately" : "&Listen Publicly" ).toAscii().constData() ), this );
QAction *privacyToggle = new QAction( ( isPublic ? tr( "&Listen Privately" ) : tr( "&Listen Publicly" ) ), this );
privacyToggle->setIcon( QIcon( RESPATH "images/private-listening.png" ) );
privacyToggle->setIconVisibleInMenu( isPublic );
m_actionCollection[ "togglePrivacy" ] = privacyToggle;

View File

@@ -167,6 +167,8 @@ void
AudioEngine::stop()
{
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
emit stopped();
if ( isStopped() )
return;
@@ -178,7 +180,6 @@ AudioEngine::stop()
if ( !m_currentTrack.isNull() )
emit timerPercentage( ( (double)m_timeElapsed / (double)m_currentTrack->duration() ) * 100.0 );
emit stopped();
setCurrentTrack( Tomahawk::result_ptr() );
Tomahawk::InfoSystem::InfoTypeMap map;
@@ -191,7 +192,7 @@ AudioEngine::stop()
else if ( TomahawkSettings::instance()->verboseNotifications() )
{
QVariantMap stopInfo;
stopInfo["message"] = QString( "Tomahawk is stopped." );
stopInfo["message"] = tr( "Tomahawk is stopped." );
map[ Tomahawk::InfoSystem::InfoNotifyUser ] = QVariant::fromValue< QVariantMap >( stopInfo );
}
@@ -413,7 +414,7 @@ AudioEngine::togglePrivateListeningMode()
#ifndef TOMAHAWK_HEADLESS
QAction *privacyToggle = ActionCollection::instance()->getAction( "togglePrivacy" );
bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening;
privacyToggle->setText( tr( QString( isPublic ? "&Listen Privately" : "&Listen Publicly" ).toAscii().constData() ) );
privacyToggle->setText( ( isPublic ? tr( "&Listen Privately" ) : tr( "&Listen Publicly" ) ) );
privacyToggle->setIconVisibleInMenu( isPublic );
#endif
}
@@ -450,9 +451,6 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
tLog() << "Starting new song:" << m_currentTrack->url();
emit loading( m_currentTrack );
if ( QNetworkReply* qnr_io = qobject_cast< QNetworkReply* >( io.data() ) )
connect( qnr_io, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( ioStreamError( QNetworkReply::NetworkError ) ) );
if ( !isHttpResult( m_currentTrack->url() ) && !isLocalResult( m_currentTrack->url() ) )
{
if ( QNetworkReply* qnr_io = qobject_cast< QNetworkReply* >( io.data() ) )
@@ -605,16 +603,6 @@ AudioEngine::playItem( Tomahawk::PlaylistInterface* playlist, const Tomahawk::re
}
}
void
AudioEngine::ioStreamError( QNetworkReply::NetworkError error )
{
if ( error != QNetworkReply::NoError )
{
if ( canGoNext() )
loadNextTrack();
}
}
void
AudioEngine::playlistNextTrackReady()
@@ -643,6 +631,9 @@ AudioEngine::onStateChanged( Phonon::State newState, Phonon::State oldState )
if ( newState == Phonon::ErrorState )
{
tLog() << "Phonon Error:" << m_mediaObject->errorString() << m_mediaObject->errorType();
emit error( UnknownError );
stop();
return;
}
if ( newState == Phonon::PlayingState )

View File

@@ -21,7 +21,6 @@
#include <QObject>
#include <QTimer>
#include <QNetworkReply>
#include <phonon/MediaObject>
#include <phonon/AudioOutput>
@@ -46,7 +45,7 @@ class DLLEXPORT AudioEngine : public QObject
Q_OBJECT
public:
enum AudioErrorCode { StreamReadError, AudioDeviceError, DecodeError };
enum AudioErrorCode { StreamReadError, AudioDeviceError, DecodeError, UnknownError };
enum AudioState { Stopped, Playing, Paused };
static AudioEngine* instance();
@@ -124,7 +123,7 @@ signals:
void playlistChanged( Tomahawk::PlaylistInterface* playlist );
void error( AudioErrorCode errorCode );
void error( AudioEngine::AudioErrorCode errorCode );
private slots:
bool loadTrack( const Tomahawk::result_ptr& result );
@@ -137,7 +136,6 @@ private slots:
void setCurrentTrack( const Tomahawk::result_ptr& result );
void ioStreamError( QNetworkReply::NetworkError );
private:
void setState( AudioState state );

View File

@@ -33,10 +33,12 @@ Collection::Collection( const source_ptr& source, const QString& name, QObject*
: QObject( parent )
, m_name( name )
, m_lastmodified( 0 )
, m_isLoaded( false )
, m_changed( false )
, m_source( source )
{
qDebug() << Q_FUNC_INFO << name << source->friendlyName();
connect( source.data(), SIGNAL( synced() ), SLOT( onSynced() ) );
}
@@ -209,20 +211,32 @@ Collection::setStations( const QList< dynplaylist_ptr >& stations )
void
Collection::setTracks( const QList<unsigned int>& ids )
{
qDebug() << Q_FUNC_INFO << ids.count() << name();
tDebug() << Q_FUNC_INFO << ids.count() << name();
m_changed = true;
emit tracksAdded( ids );
emit changed();
}
void
Collection::delTracks( const QList<unsigned int>& ids )
{
qDebug() << Q_FUNC_INFO << ids.count() << name();
tDebug() << Q_FUNC_INFO << ids.count() << name();
m_changed = true;
emit tracksRemoved( ids );
}
void
Collection::onSynced()
{
tDebug() << Q_FUNC_INFO << m_changed;
if ( m_changed )
{
m_changed = false;
emit changed();
}
}

View File

@@ -49,8 +49,6 @@ public:
Collection( const source_ptr& source, const QString& name, QObject* parent = 0 );
virtual ~Collection();
virtual void setLoaded() { m_isLoaded = true; }
virtual bool isLoaded() const { return m_isLoaded; }
virtual QString name() const;
virtual void loadPlaylists() { qDebug() << Q_FUNC_INFO; }
@@ -107,8 +105,11 @@ protected:
QString m_name;
unsigned int m_lastmodified; // unix time of last change to collection
private slots:
void onSynced();
private:
bool m_isLoaded;
bool m_changed;
source_ptr m_source;
QHash< QString, Tomahawk::playlist_ptr > m_playlists;

View File

@@ -52,7 +52,9 @@ public:
virtual bool jumpToCurrentTrack() = 0;
public slots:
virtual void setQuery( const Tomahawk::query_ptr& query ) = 0;
virtual void setArtist( const Tomahawk::artist_ptr& artist ) { Q_UNUSED( artist ); }
virtual void setAlbum( const Tomahawk::album_ptr& album ) { Q_UNUSED( album ); }
virtual void setQuery( const Tomahawk::query_ptr& query ) { Q_UNUSED( query ); }
signals:
void nameChanged( const QString& );

View File

@@ -93,6 +93,7 @@ ContextWidget::ContextWidget( QWidget* parent )
setAutoFillBackground( true );
setFixedHeight( m_minHeight );
ensurePolished();
QPalette pal = palette();
pal.setBrush( QPalette::Window, StyleHelper::headerLowerColor() );
setPalette( pal );
@@ -113,6 +114,22 @@ ContextWidget::~ContextWidget()
}
void
ContextWidget::changeEvent( QEvent* e )
{
QWidget::changeEvent( e );
switch ( e->type() )
{
case QEvent::LanguageChange:
ui->retranslateUi( this );
break;
default:
break;
}
}
void
ContextWidget::layoutViews( bool animate )
{
@@ -212,6 +229,44 @@ ContextWidget::fadeOut( bool animate )
}
void
ContextWidget::setArtist( const Tomahawk::artist_ptr& artist )
{
if ( artist.isNull() )
return;
m_artist = artist;
if ( height() > m_minHeight )
{
foreach ( ContextProxyPage* proxy, m_pages )
{
proxy->page()->setArtist( artist );
}
layoutViews( true );
}
}
void
ContextWidget::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
m_album = album;
if ( height() > m_minHeight )
{
foreach ( ContextProxyPage* proxy, m_pages )
{
proxy->page()->setAlbum( album );
}
layoutViews( true );
}
}
void
ContextWidget::setQuery( const Tomahawk::query_ptr& query, bool force )
{
@@ -275,6 +330,8 @@ ContextWidget::onAnimationFinished()
fadeOut( false );
m_scene->setSceneRect( ui->contextView->viewport()->rect() );
layoutViews( false );
setArtist( m_artist );
setAlbum( m_album );
setQuery( m_query, true );
ui->toggleButton->setText( tr( "Hide Footnotes" ) );

View File

@@ -50,6 +50,8 @@ public:
~ContextWidget();
public slots:
void setArtist( const Tomahawk::artist_ptr& artist );
void setAlbum( const Tomahawk::album_ptr& album );
void setQuery( const Tomahawk::query_ptr& query, bool force = false );
void toggleSize();
@@ -63,6 +65,7 @@ private slots:
protected:
void paintEvent( QPaintEvent* e );
void resizeEvent( QResizeEvent* e );
void changeEvent( QEvent* e );
private:
void fadeOut( bool animate );
@@ -81,6 +84,8 @@ private:
int m_currentView;
Tomahawk::artist_ptr m_artist;
Tomahawk::album_ptr m_album;
Tomahawk::query_ptr m_query;
bool m_visible;
};

View File

@@ -32,6 +32,7 @@ RelatedArtistsContext::RelatedArtistsContext()
{
m_relatedView = new ArtistView();
m_relatedView->setGuid( "RelatedArtistsContext" );
m_relatedView->setUpdatesContextView( false );
m_relatedModel = new TreeModel( m_relatedView );
m_relatedModel->setColumnStyle( TreeModel::TrackOnly );
m_relatedView->setTreeModel( m_relatedModel );
@@ -58,15 +59,17 @@ RelatedArtistsContext::~RelatedArtistsContext()
void
RelatedArtistsContext::setQuery( const Tomahawk::query_ptr& query )
RelatedArtistsContext::setArtist( const Tomahawk::artist_ptr& artist )
{
if ( !m_query.isNull() && query->artist() == m_query->artist() )
if ( artist.isNull() )
return;
if ( !m_artist.isNull() && m_artist->name() == artist->name() )
return;
m_query = query;
m_artist = artist;
Tomahawk::InfoSystem::InfoStringHash artistInfo;
artistInfo["artist"] = query->artist();
artistInfo["artist"] = artist->name();
Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = m_infoId;
@@ -78,6 +81,26 @@ RelatedArtistsContext::setQuery( const Tomahawk::query_ptr& query )
}
void
RelatedArtistsContext::setQuery( const Tomahawk::query_ptr& query )
{
if ( query.isNull() )
return;
setArtist( Artist::get( query->artist(), false ) );
}
void
RelatedArtistsContext::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
setArtist( album->artist() );
}
void
RelatedArtistsContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
@@ -89,9 +112,9 @@ RelatedArtistsContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData req
if ( output.canConvert< QVariantMap >() )
{
if ( trackInfo["artist"] != m_query->artist() )
if ( trackInfo["artist"] != m_artist->name() )
{
qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_query->artist();
qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_artist->name();
return;
}
}

View File

@@ -23,6 +23,8 @@
#include "dllmacro.h"
#include "artist.h"
#include "album.h"
#include "query.h"
#include "context/ContextPage.h"
#include "infosystem/infosystem.h"
@@ -48,6 +50,8 @@ public:
virtual bool jumpToCurrentTrack() { return false; }
public slots:
virtual void setArtist( const Tomahawk::artist_ptr& artist );
virtual void setAlbum( const Tomahawk::album_ptr& album );
virtual void setQuery( const Tomahawk::query_ptr& query );
private slots:
@@ -61,7 +65,7 @@ private:
QGraphicsProxyWidget* m_proxy;
QString m_infoId;
Tomahawk::query_ptr m_query;
Tomahawk::artist_ptr m_artist;
};
#endif // RELATEDARTISTSCONTEXT_H

View File

@@ -58,15 +58,17 @@ TopTracksContext::~TopTracksContext()
void
TopTracksContext::setQuery( const Tomahawk::query_ptr& query )
TopTracksContext::setArtist( const Tomahawk::artist_ptr& artist )
{
if ( !m_query.isNull() && query->artist() == m_query->artist() )
if ( artist.isNull() )
return;
if ( !m_artist.isNull() && m_artist->name() == artist->name() )
return;
m_query = query;
m_artist = artist;
Tomahawk::InfoSystem::InfoStringHash artistInfo;
artistInfo["artist"] = query->artist();
artistInfo["artist"] = artist->name();
Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = m_infoId;
@@ -78,6 +80,26 @@ TopTracksContext::setQuery( const Tomahawk::query_ptr& query )
}
void
TopTracksContext::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
setArtist( album->artist() );
}
void
TopTracksContext::setQuery( const Tomahawk::query_ptr& query )
{
if ( query.isNull() )
return;
setArtist( Artist::get( query->artist(), false ) );
}
void
TopTracksContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
@@ -89,9 +111,9 @@ TopTracksContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestD
if ( output.canConvert< QVariantMap >() )
{
if ( trackInfo["artist"] != m_query->artist() )
if ( trackInfo["artist"] != m_artist->name() )
{
qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_query->artist();
qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_artist->name();
return;
}
}
@@ -107,7 +129,7 @@ TopTracksContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestD
int i = 0;
foreach ( const QString& track, tracks )
{
query_ptr query = Query::get( m_query->artist(), track, QString(), uuid() );
query_ptr query = Query::get( m_artist->name(), track, QString(), uuid() );
m_topHitsModel->append( query );
if ( ++i == 15 )

View File

@@ -23,6 +23,8 @@
#include "dllmacro.h"
#include "artist.h"
#include "album.h"
#include "query.h"
#include "context/ContextPage.h"
#include "infosystem/infosystem.h"
@@ -48,6 +50,8 @@ public:
virtual bool jumpToCurrentTrack() { return false; }
public slots:
virtual void setArtist( const Tomahawk::artist_ptr& artist );
virtual void setAlbum( const Tomahawk::album_ptr& album );
virtual void setQuery( const Tomahawk::query_ptr& query );
private slots:
@@ -61,7 +65,7 @@ private:
QGraphicsProxyWidget* m_proxy;
QString m_infoId;
Tomahawk::query_ptr m_query;
Tomahawk::artist_ptr m_artist;
};
#endif // TOPTRACKSCONTEXT_H

View File

@@ -22,22 +22,68 @@ using namespace Tomahawk;
void
WikipediaContext::setQuery( const Tomahawk::query_ptr& query )
WikipediaContext::setArtist( const Tomahawk::artist_ptr& artist )
{
if ( !m_query.isNull() && query->artist() == m_query->artist() )
if ( artist.isNull() )
return;
if ( !m_artist.isNull() && m_artist->name() == artist->name() )
return;
m_query = query;
webView()->load( QString( "http://en.wikipedia.org/w/index.php?useformat=mobile&title=%1" ).arg( query->artist() ) );
m_artist = artist;
webView()->load( QString( "http://en.wikipedia.org/w/index.php?useformat=mobile&title=%1" ).arg( m_artist->name() ) );
}
void
WikipediaContext::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
setArtist( album->artist() );
}
void
WikipediaContext::setQuery( const Tomahawk::query_ptr& query )
{
if ( query.isNull() )
return;
setArtist( Artist::get( query->artist(), false ) );
}
void
LastfmContext::setArtist( const Tomahawk::artist_ptr& artist )
{
if ( artist.isNull() )
return;
if ( !m_artist.isNull() && m_artist->name() == artist->name() )
return;
m_artist = artist;
webView()->load( QString( "http://last.fm/music/%1" ).arg( m_artist->name() ) );
}
void
LastfmContext::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
setArtist( album->artist() );
}
void
LastfmContext::setQuery( const Tomahawk::query_ptr& query )
{
if ( !m_query.isNull() && query->artist() == m_query->artist() )
if ( query.isNull() )
return;
m_query = query;
webView()->load( QString( "http://last.fm/music/%1" ).arg( query->artist() ) );
setArtist( Artist::get( query->artist(), false ) );
}

View File

@@ -23,6 +23,8 @@
#include "dllmacro.h"
#include "artist.h"
#include "album.h"
#include "query.h"
#include "WebContext.h"
@@ -42,10 +44,12 @@ public:
virtual bool jumpToCurrentTrack() { return false; }
public slots:
virtual void setArtist( const Tomahawk::artist_ptr& artist );
virtual void setAlbum( const Tomahawk::album_ptr& album );
virtual void setQuery( const Tomahawk::query_ptr& query );
private:
Tomahawk::query_ptr m_query;
Tomahawk::artist_ptr m_artist;
};
@@ -65,10 +69,12 @@ public:
virtual bool jumpToCurrentTrack() { return false; }
public slots:
virtual void setArtist( const Tomahawk::artist_ptr& artist );
virtual void setAlbum( const Tomahawk::album_ptr& album );
virtual void setQuery( const Tomahawk::query_ptr& query );
private:
Tomahawk::query_ptr m_query;
Tomahawk::artist_ptr m_artist;
};
#endif // WIKIPEDIACONTEXT_H

View File

@@ -39,8 +39,11 @@ ContextMenu::ContextMenu( QWidget* parent )
m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink;
}
ContextMenu::~ContextMenu()
{}
{
}
void
ContextMenu::clear()
@@ -50,23 +53,22 @@ ContextMenu::clear()
m_queries.clear();
m_albums.clear();
m_artists.clear();
}
unsigned int
ContextMenu::itemCount() const
{
return m_queries.count() + m_artists.count() + m_albums.count();
}
void
ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
{
if ( queries.isEmpty() )
return;
QMenu::clear();
m_queries.clear();
m_queries << queries;
@@ -87,11 +89,8 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
if ( m_supportedActions & ActionDelete )
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) ), ActionDelete );
foreach ( QAction* action, actions() )
{
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
}
}
@@ -107,7 +106,6 @@ ContextMenu::setQuery( const Tomahawk::query_ptr& query )
}
void
ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
{
@@ -185,6 +183,7 @@ ContextMenu::setArtist( const Tomahawk::artist_ptr& artist )
setArtists( artists );
}
void
ContextMenu::onTriggered( int action )
{
@@ -205,7 +204,8 @@ ContextMenu::onTriggered( int action )
void ContextMenu::addToQueue()
void
ContextMenu::addToQueue()
{
foreach ( const query_ptr& query, m_queries )
{

View File

@@ -39,7 +39,6 @@ public:
ActionQueue = 2,
ActionDelete = 4,
ActionCopyLink = 8
};
explicit ContextMenu( QWidget* parent = 0 );

View File

@@ -73,7 +73,15 @@ Database::loadIndex()
void
Database::enqueue( QSharedPointer<DatabaseCommand> lc )
Database::enqueue( const QList< QSharedPointer<DatabaseCommand> >& lc )
{
qDebug() << "Enqueueing" << lc.count() << "commands to rw thread";
m_workerRW->enqueue( lc );
}
void
Database::enqueue( const QSharedPointer<DatabaseCommand>& lc )
{
if ( lc->doesMutates() )
{

View File

@@ -66,7 +66,8 @@ signals:
void newJobRW( QSharedPointer<DatabaseCommand> );
public slots:
void enqueue( QSharedPointer<DatabaseCommand> lc );
void enqueue( const QSharedPointer<DatabaseCommand>& lc );
void enqueue( const QList< QSharedPointer<DatabaseCommand> >& lc );
private slots:
void setIsReadyTrue() { m_ready = true; }

View File

@@ -69,22 +69,8 @@ DatabaseCollection::loadStations()
connect( cmd, SIGNAL( stationLoaded( Tomahawk::source_ptr, QVariantList ) ),
SLOT( stationCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );}
/*void
DatabaseCollection::loadTracks()
{
qDebug() << Q_FUNC_INFO << source()->userName();
setLoaded();
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( source()->collection() );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
SLOT( setTracks( QList<Tomahawk::query_ptr> ) ) );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}*/
}
void
@@ -143,19 +129,8 @@ DatabaseCollection::stations()
}
/*QList< Tomahawk::query_ptr >
DatabaseCollection::tracks()
{
if ( !isLoaded() )
{
loadTracks();
}
return Collection::tracks();
}*/
void DatabaseCollection::autoPlaylistCreated( const source_ptr& source, const QVariantList& data )
void
DatabaseCollection::autoPlaylistCreated( const source_ptr& source, const QVariantList& data )
{
dynplaylist_ptr p( new DynamicPlaylist( source, //src
data[0].toString(), //current rev
@@ -172,7 +147,8 @@ void DatabaseCollection::autoPlaylistCreated( const source_ptr& source, const QV
}
void DatabaseCollection::stationCreated( const source_ptr& source, const QVariantList& data )
void
DatabaseCollection::stationCreated( const source_ptr& source, const QVariantList& data )
{
dynplaylist_ptr p( new DynamicPlaylist( source, //src
data[0].toString(), //current rev

View File

@@ -80,12 +80,14 @@ DatabaseCommand::setSource( const Tomahawk::source_ptr& s )
m_source = s;
}
const Tomahawk::source_ptr&
DatabaseCommand::source() const
{
return m_source;
}
DatabaseCommand*
DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
{
@@ -139,7 +141,8 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
cmd->setSource( source );
QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
return cmd;
} else if( name == "createdynamicplaylist" )
}
else if( name == "createdynamicplaylist" )
{
DatabaseCommand_CreateDynamicPlaylist * cmd = new DatabaseCommand_CreateDynamicPlaylist;
cmd->setSource( source );
@@ -183,7 +186,7 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
return cmd;
}
qDebug() << "ERROR in" << Q_FUNC_INFO << name;
qDebug() << "Unknown database command" << name;
// Q_ASSERT( false );
return NULL;
}

View File

@@ -70,6 +70,7 @@ public:
const Tomahawk::source_ptr& source() const;
virtual bool loggable() const { return false; }
virtual bool groupable() const { return false; }
virtual bool singletonCmd() const { return false; }
virtual bool localOnly() const { return false; }

View File

@@ -24,7 +24,6 @@
#include "album.h"
#include "collection.h"
#include "database/database.h"
#include "databasecommand_collectionstats.h"
#include "databaseimpl.h"
#include "network/dbsyncconnection.h"
#include "network/servent.h"
@@ -56,32 +55,17 @@ DatabaseCommand_AddFiles::files() const
void
DatabaseCommand_AddFiles::postCommitHook()
{
if ( source().isNull() || source()->collection().isNull() )
{
qDebug() << "Source has gone offline, not emitting to GUI.";
return;
}
// make the collection object emit its tracksAdded signal, so the
// collection browser will update/fade in etc.
Collection* coll = source()->collection().data();
connect( this, SIGNAL( notify( QList<unsigned int> ) ),
coll, SLOT( setTracks( QList<unsigned int> ) ),
Qt::QueuedConnection );
coll, SLOT( setTracks( QList<unsigned int> ) ), Qt::QueuedConnection );
emit notify( m_ids );
if ( source()->isLocal() )
{
Servent::instance()->triggerDBSync();
// Re-calculate local db stats
DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() );
connect( cmd, SIGNAL( done( QVariantMap ) ),
SourceList::instance()->getLocal().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
}
@@ -94,23 +78,21 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
TomahawkSqlQuery query_file = dbi->newquery();
TomahawkSqlQuery query_filejoin = dbi->newquery();
TomahawkSqlQuery query_trackattr = dbi->newquery();
TomahawkSqlQuery query_file_del = dbi->newquery();
query_file.prepare( "INSERT INTO file(source, url, size, mtime, md5, mimetype, duration, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" );
query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos) VALUES (?, ?, ?, ?, ?)" );
query_trackattr.prepare( "INSERT INTO track_attributes(id, k, v) VALUES (?, ?, ?)" );
query_file_del.prepare( QString( "DELETE FROM file WHERE source %1 AND url = ?" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
int added = 0;
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
qDebug() << "Adding" << m_files.length() << "files to db for source" << srcid;
QList<QVariant>::iterator it;
for( it = m_files.begin(); it != m_files.end(); ++it )
for ( it = m_files.begin(); it != m_files.end(); ++it )
{
QVariant& v = *it;
QVariantMap m = v.toMap();
int fileid = 0, artistid = 0, albumid = 0, trackid = 0;
QString url = m.value( "url" ).toString();
int mtime = m.value( "mtime" ).toInt();
@@ -125,10 +107,6 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
uint albumpos = m.value( "albumpos" ).toUInt();
int year = m.value( "year" ).toInt();
int fileid = 0, artistid = 0, albumid = 0, trackid = 0;
query_file_del.bindValue( 0, url );
query_file_del.exec();
query_file.bindValue( 0, srcid );
query_file.bindValue( 1, url );
query_file.bindValue( 2, size );
@@ -137,28 +115,17 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
query_file.bindValue( 5, mimetype );
query_file.bindValue( 6, duration );
query_file.bindValue( 7, bitrate );
if( !query_file.exec() )
{
qDebug() << "Failed to insert to file:"
<< query_file.lastError().databaseText()
<< query_file.lastError().driverText()
<< query_file.boundValues();
continue;
}
else
{
if( added % 1000 == 0 )
query_file.exec();
if ( added % 1000 == 0 )
qDebug() << "Inserted" << added;
}
// get internal IDs for art/alb/trk
fileid = query_file.lastInsertId().toInt();
m.insert( "id", fileid );
// this is the qvariant(map) the remote will get
v = m;
if( !source()->isLocal() )
url = QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( url );
artistid = dbi->artistId( artist, true );
if ( artistid < 1 )
continue;
@@ -173,44 +140,13 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
query_filejoin.bindValue( 2, albumid > 0 ? albumid : QVariant( QVariant::Int ) );
query_filejoin.bindValue( 3, trackid );
query_filejoin.bindValue( 4, albumpos );
if ( !query_filejoin.exec() )
{
qDebug() << "Error inserting into file_join table";
continue;
}
query_filejoin.exec();
query_trackattr.bindValue( 0, trackid );
query_trackattr.bindValue( 1, "releaseyear" );
query_trackattr.bindValue( 2, year );
query_trackattr.exec();
/* QVariantMap attr;
Tomahawk::query_ptr query = Tomahawk::Query::get( artist, track, album );
attr["releaseyear"] = m.value( "year" );
Tomahawk::artist_ptr artistptr = Tomahawk::Artist::get( artistid, artist );
Tomahawk::album_ptr albumptr = Tomahawk::Album::get( albumid, album, artistptr );
Tomahawk::result_ptr result = Tomahawk::Result::get( url );
result->setModificationTime( mtime );
result->setSize( size );
result->setMimetype( mimetype );
result->setDuration( duration );
result->setBitrate( bitrate );
result->setArtist( artistptr );
result->setAlbum( albumptr );
result->setTrack( track );
result->setAlbumPos( albumpos );
result->setAttributes( attr );
result->setCollection( source()->collection() );
result->setScore( 1.0 );
result->setId( trackid );
QList<Tomahawk::result_ptr> results;
results << result;
query->addResults( results );
m_queries << query;*/
m_ids << fileid;
added++;
}
@@ -219,6 +155,6 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
if ( added )
source()->updateIndexWhenSynced();
qDebug() << "Committing" << added << "tracks...";
tDebug() << "Committing" << added << "tracks...";
emit done( m_files, source()->collection() );
}

View File

@@ -35,20 +35,21 @@ DatabaseCommand_addSource::DatabaseCommand_addSource( const QString& username, c
void
DatabaseCommand_addSource::exec( DatabaseImpl* dbi )
{
Q_ASSERT( !m_fname.isEmpty() );
TomahawkSqlQuery query = dbi->newquery();
query.prepare( "SELECT id, friendlyname FROM source WHERE name = ?" );
query.prepare( "SELECT id FROM source WHERE name = ?" );
query.addBindValue( m_username );
query.exec();
if ( query.next() )
{
unsigned int id = query.value( 0 ).toInt();
QString fname = query.value( 1 ).toString();
query.prepare( "UPDATE source SET isonline = 'true', friendlyname = ? WHERE id = ?" );
query.addBindValue( m_fname );
query.addBindValue( id );
query.exec();
emit done( id, fname );
emit done( id, m_fname );
return;
}

View File

@@ -23,6 +23,7 @@
#include <QVariantMap>
#include "artist.h"
#include "collection.h"
#include "typedefs.h"
#include "databasecommand.h"

View File

@@ -25,7 +25,6 @@
#include "collection.h"
#include "source.h"
#include "database/database.h"
#include "databasecommand_collectionstats.h"
#include "databaseimpl.h"
#include "network/servent.h"
#include "utils/logger.h"
@@ -38,7 +37,7 @@ using namespace Tomahawk;
void
DatabaseCommand_DeleteFiles::postCommitHook()
{
if ( !m_files.count() )
if ( !m_idList.count() )
return;
// make the collection object emit its tracksAdded signal, so the
@@ -48,13 +47,10 @@ DatabaseCommand_DeleteFiles::postCommitHook()
connect( this, SIGNAL( notify( QList<unsigned int> ) ),
coll, SLOT( delTracks( QList<unsigned int> ) ), Qt::QueuedConnection );
tDebug() << "Notifying of deleted tracks:" << m_ids.size() << "from source" << source()->id();
QList<unsigned int> ids;
foreach ( QVariant id, m_ids )
ids << id.toUInt();
emit notify( ids );
tDebug() << "Notifying of deleted tracks:" << m_idList.size() << "from source" << source()->id();
emit notify( m_idList );
if( source()->isLocal() )
if ( source()->isLocal() )
Servent::instance()->triggerDBSync();
}
@@ -66,111 +62,78 @@ DatabaseCommand_DeleteFiles::exec( DatabaseImpl* dbi )
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
TomahawkSqlQuery delquery = dbi->newquery();
QString lastPath;
if ( source()->isLocal() )
if ( m_deleteAll )
{
TomahawkSqlQuery dirquery = dbi->newquery();
dirquery.prepare( QString( "SELECT id FROM file WHERE source %1" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
dirquery.exec();
while ( dirquery.next() )
m_idList << dirquery.value( 0 ).toUInt();
}
else if ( source()->isLocal() )
{
if ( m_dir.path() != QString( "." ) )
{
tDebug() << "Deleting" << m_dir.path() << "from db for localsource" << srcid;
TomahawkSqlQuery dirquery = dbi->newquery();
QString path( "file://" + m_dir.canonicalPath() + "/%" );
dirquery.prepare( QString( "SELECT id, url FROM file WHERE source IS NULL AND url LIKE '%1'" ).arg( TomahawkUtils::sqlEscape( path ) ) );
dirquery.prepare( QString( "SELECT id FROM file WHERE source IS NULL AND url LIKE '%1'" ).arg( TomahawkUtils::sqlEscape( path ) ) );
dirquery.exec();
while ( dirquery.next() )
{
QFileInfo fi( dirquery.value( 1 ).toString().mid( 7 ) ); // remove file://
if ( fi.canonicalPath() != m_dir.canonicalPath() )
{
if ( lastPath != fi.canonicalPath() )
tDebug() << "Skipping subdir:" << fi.canonicalPath();
lastPath = fi.canonicalPath();
continue;
}
m_files << dirquery.value( 1 ).toString();
m_ids << dirquery.value( 0 ).toUInt();
m_ids << dirquery.value( 0 );
m_idList << dirquery.value( 0 ).toUInt();
}
}
else if ( !m_ids.isEmpty() )
{
tDebug() << Q_FUNC_INFO << "deleting given ids";
TomahawkSqlQuery dirquery = dbi->newquery();
QString idstring;
foreach( const QVariant& id, m_ids )
idstring.append( id.toString() + ", " );
idstring.chop( 2 ); //remove the trailing ", "
dirquery.prepare( QString( "SELECT id, url FROM file WHERE source IS NULL AND id IN ( %1 )" ).arg( idstring ) );
dirquery.exec();
while ( dirquery.next() )
{
m_files << dirquery.value( 1 ).toString();
foreach ( const QVariant& id, m_ids )
m_idList << id.toUInt();
}
}
else if ( m_deleteAll )
{
TomahawkSqlQuery dirquery = dbi->newquery();
dirquery.prepare( QString( "SELECT id, url FROM file WHERE source IS NULL" ) );
dirquery.exec();
while ( dirquery.next() )
{
m_ids << dirquery.value( 0 ).toString();
m_files << dirquery.value( 1 ).toString();
}
}
}
else
{
if ( m_deleteAll )
{
TomahawkSqlQuery dirquery = dbi->newquery();
dirquery.prepare( QString( "SELECT url FROM file WHERE source = %1" ).arg( source()->id() ) );
dirquery.exec();
while ( dirquery.next() )
m_ids << dirquery.value( 0 ).toString();
}
foreach( const QVariant& id, m_ids )
m_files << QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( id.toString() );
}
if ( m_deleteAll )
{
if ( !m_ids.isEmpty() )
{
delquery.prepare( QString( "DELETE FROM file WHERE source %1" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
delquery.exec();
}
}
else if ( !m_ids.isEmpty() )
{
delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND %2 IN ( ? )" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) )
.arg( source()->isLocal() ? "id" : "url" ) );
QString idstring;
foreach( const QVariant& id, m_ids )
foreach ( const QVariant& id, m_ids )
idstring.append( id.toString() + ", " );
idstring.chop( 2 ); //remove the trailing ", "
delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND %2 IN ( %3 )" )
if ( !source()->isLocal() )
{
delquery.prepare( QString( "SELECT id FROM file WHERE source = %1 AND url IN ( %2 )" )
.arg( source()->id() )
.arg( idstring ) );
idstring = QString();
while ( delquery.next() )
{
idstring.append( delquery.value( 0 ).toString() + ", " );
m_idList << delquery.value( 0 ).toUInt();
}
idstring.chop( 2 ); //remove the trailing ", "
}
delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND id IN ( %2 )" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) )
.arg( source()->isLocal() ? "id" : "url" )
.arg( idstring ) );
delquery.exec();
}
emit done( m_files, source()->collection() );
if ( m_idList.count() )
source()->updateIndexWhenSynced();
emit done( m_idList, source()->collection() );
}

View File

@@ -64,6 +64,7 @@ public:
virtual void exec( DatabaseImpl* );
virtual bool doesMutates() const { return true; }
virtual bool localOnly() const { return false; }
virtual bool groupable() const { return true; }
virtual void postCommitHook();
QVariantList ids() const { return m_ids; }
@@ -73,13 +74,13 @@ public:
void setDeleteAll( const bool deleteAll ) { m_deleteAll = deleteAll; }
signals:
void done( const QStringList&, const Tomahawk::collection_ptr& );
void done( const QList<unsigned int>&, const Tomahawk::collection_ptr& );
void notify( const QList<unsigned int>& ids );
private:
QStringList m_files;
QDir m_dir;
QVariantList m_ids;
QList<unsigned int> m_idList;
bool m_deleteAll;
};

View File

@@ -40,8 +40,8 @@ DatabaseCommand_FileMtimes::execSelect( DatabaseImpl* dbi )
TomahawkSqlQuery query = dbi->newquery();
if( m_prefix.isEmpty() && m_prefixes.isEmpty() )
{
QString limit( m_checkonly ? QString( " LIMIT 1" ) : QString() );
query.exec( QString( "SELECT url, id, mtime FROM file WHERE source IS NULL%1" ).arg( limit ) );
QString limit( m_checkonly ? QString( "LIMIT 1" ) : QString() );
query.exec( QString( "SELECT url, id, mtime FROM file WHERE source IS NULL %1" ).arg( limit ) );
while( query.next() )
{
QMap< unsigned int, unsigned int > map;

View File

@@ -19,10 +19,11 @@
#include "databasecommand_genericselect.h"
#include "databaseimpl.h"
#include "sourcelist.h"
#include "artist.h"
#include "album.h"
#include "pipeline.h"
#include "utils/logger.h"
#include <sourcelist.h>
#include <artist.h>
#include <album.h>
using namespace Tomahawk;
@@ -63,7 +64,6 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
while( query.next() )
{
QStringList rawRow;
int count = 0;
while ( query.value( count ).isValid() )
@@ -90,15 +90,16 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
track = query.value( 0 ).toString();
artist = query.value( 1 ).toString();
qry = Tomahawk::Query::get( artist, track, QString(), uuid(), true ); // Only auto-resolve non-local results
} else if ( m_queryType == Artist )
qry = Tomahawk::Query::get( artist, track, QString() );
}
else if ( m_queryType == Artist )
{
int artistId = query.value( 0 ).toInt();
QString artistName = query.value( 1 ).toString();
artist = Tomahawk::Artist::get( artistId, artistName );
} else if ( m_queryType == Album )
}
else if ( m_queryType == Album )
{
int albumId = query.value( 0 ).toInt();
QString albumName = query.value( 1 ).toString();
@@ -122,12 +123,14 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
if ( !extraData.isEmpty() )
qry->setProperty( "data", extraData );
queries << qry;
} else if ( m_queryType == Artist )
}
else if ( m_queryType == Artist )
{
if ( !extraData.isEmpty() )
artist->setProperty( "data", extraData );
arts << artist;
} else if ( m_queryType == Album )
}
else if ( m_queryType == Album )
{
if ( !extraData.isEmpty() )
album->setProperty( "data", extraData );

View File

@@ -94,23 +94,13 @@ DatabaseCommand_LoadDynamicPlaylistEntries::exec( DatabaseImpl* dbi )
}
else
{
// No controls, lets load the info we need directly from the playlist table
TomahawkSqlQuery info = dbi->newquery();
info.prepare( QString( "SELECT dynamic_playlist.pltype, dynamic_playlist.plmode FROM playlist, dynamic_playlist WHERE playlist.guid = \"%1\" AND playlist.guid = dynamic_playlist.guid" ).arg( playlist_guid ) );
if( !info.exec() ) {
qWarning() << "Failed to load dynplaylist info..";
// No controls or plguid is null, but that's okay. We'll get a setdynrevision command with a proper revision some point later
return;
} else if( !info.first() ) {
qWarning() << "Noo results for queryL:" << info.lastQuery();
return;
}
type = info.value( 0 ).toString();
mode = static_cast<GeneratorMode>( info.value( 1 ).toInt() );
}
if( mode == OnDemand )
{
Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry
// Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry
emit done( revisionGuid(), m_islatest, type, controls, true );
}

View File

@@ -31,7 +31,6 @@ using namespace Tomahawk;
void
DatabaseCommand_LoadPlaylistEntries::exec( DatabaseImpl* dbi )
{
// qDebug() << "Loading playlist entries for revision" << m_revguid;
generateEntries( dbi );
emit done( m_revguid, m_guids, m_oldentries, m_islatest, m_entrymap, true );
@@ -42,40 +41,38 @@ void
DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
{
TomahawkSqlQuery query_entries = dbi->newquery();
query_entries.prepare("SELECT entries, playlist, author, timestamp, previous_revision "
query_entries.prepare( "SELECT entries, playlist, author, timestamp, previous_revision "
"FROM playlist_revision "
"WHERE guid = :guid");
"WHERE guid = :guid" );
query_entries.bindValue( ":guid", m_revguid );
query_entries.exec();
// qDebug() << "trying to load entries:" << m_revguid;
tLog( LOGVERBOSE ) << "trying to load playlist entries for guid:" << m_revguid;
QString prevrev;
QJson::Parser parser; bool ok;
if( query_entries.next() )
if ( query_entries.next() )
{
// entries should be a list of strings:
QVariant v = parser.parse( query_entries.value(0).toByteArray(), &ok );
QVariant v = parser.parse( query_entries.value( 0 ).toByteArray(), &ok );
Q_ASSERT( ok && v.type() == QVariant::List ); //TODO
m_guids = v.toStringList();
QString inclause = QString("('%1')").arg(m_guids.join("', '"));
QString inclause = QString( "('%1')" ).arg( m_guids.join( "', '" ) );
TomahawkSqlQuery query = dbi->newquery();
QString sql = QString("SELECT guid, trackname, artistname, albumname, annotation, "
QString sql = QString( "SELECT guid, trackname, artistname, albumname, annotation, "
"duration, addedon, addedby, result_hint "
"FROM playlist_item "
"WHERE guid IN %1").arg( inclause );
//qDebug() << sql;
"WHERE guid IN %1" ).arg( inclause );
query.exec( sql );
while( query.next() )
while ( query.next() )
{
plentry_ptr e( new PlaylistEntry );
e->setGuid( query.value( 0 ).toString() );
e->setAnnotation( query.value( 4 ).toString() );
e->setDuration( query.value( 5 ).toUInt() );
e->setLastmodified( 0 ); // TODO e->lastmodified = query.value(6).toInt();
e->setLastmodified( 0 ); // TODO e->lastmodified = query.value( 6 ).toInt();
e->setResultHint( query.value( 8 ).toString() );
Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString() );
@@ -86,14 +83,13 @@ DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
}
prevrev = query_entries.value( 4 ).toString();
}
else
{
// qDebug() << "Playlist has no current revision data";
}
if( prevrev.length() )
if ( prevrev.length() )
{
TomahawkSqlQuery query_entries_old = dbi->newquery();
query_entries_old.prepare( "SELECT entries, "
@@ -105,7 +101,7 @@ DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
query_entries_old.addBindValue( prevrev );
query_entries_old.exec();
if( !query_entries_old.next() )
if ( !query_entries_old.next() )
{
return;
Q_ASSERT( false );

View File

@@ -36,8 +36,8 @@ using namespace Tomahawk;
void
DatabaseCommand_LogPlayback::postCommitHook()
{
connect( this, SIGNAL( trackPlaying( Tomahawk::query_ptr ) ),
source().data(), SLOT( onPlaybackStarted( Tomahawk::query_ptr ) ), Qt::QueuedConnection );
connect( this, SIGNAL( trackPlaying( Tomahawk::query_ptr, unsigned int ) ),
source().data(), SLOT( onPlaybackStarted( Tomahawk::query_ptr, unsigned int ) ), Qt::QueuedConnection );
connect( this, SIGNAL( trackPlayed( Tomahawk::query_ptr ) ),
source().data(), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ), Qt::QueuedConnection );
@@ -60,7 +60,7 @@ DatabaseCommand_LogPlayback::postCommitHook()
// if the play time is more than 10 minutes in the past, ignore
else if ( m_action == Started && QDateTime::fromTime_t( playtime() ).secsTo( QDateTime::currentDateTime() ) < STARTED_THRESHOLD )
{
emit trackPlaying( q );
emit trackPlaying( q, m_trackDuration );
}
if ( source()->isLocal() )

View File

@@ -37,6 +37,7 @@ Q_PROPERTY( QString artist READ artist WRITE setArtist )
Q_PROPERTY( QString track READ track WRITE setTrack )
Q_PROPERTY( unsigned int playtime READ playtime WRITE setPlaytime )
Q_PROPERTY( unsigned int secsPlayed READ secsPlayed WRITE setSecsPlayed )
Q_PROPERTY( unsigned int trackDuration READ trackDuration WRITE setTrackDuration )
Q_PROPERTY( int action READ action WRITE setAction )
public:
@@ -47,13 +48,14 @@ public:
};
explicit DatabaseCommand_LogPlayback( QObject* parent = 0 )
: DatabaseCommandLoggable( parent )
: DatabaseCommandLoggable( parent ), m_playtime( 0 ), m_secsPlayed( 0 ), m_trackDuration( 0 )
{}
explicit DatabaseCommand_LogPlayback( const Tomahawk::result_ptr& result, Action action, unsigned int secsPlayed = 0, QObject* parent = 0 )
: DatabaseCommandLoggable( parent ), m_result( result ), m_secsPlayed( secsPlayed ), m_action( action )
{
m_playtime = QDateTime::currentDateTimeUtc().toTime_t();
m_trackDuration = result->duration();
setSource( SourceList::instance()->getLocal() );
setArtist( result->artist()->name() );
@@ -68,6 +70,7 @@ public:
virtual bool doesMutates() const { return true; }
virtual bool singletonCmd() const { return ( m_action == Started ); }
virtual bool localOnly() const;
virtual bool groupable() const { return true; }
QString artist() const { return m_artist; }
void setArtist( const QString& s ) { m_artist = s; }
@@ -81,11 +84,14 @@ public:
unsigned int secsPlayed() const { return m_secsPlayed; }
void setSecsPlayed( unsigned int i ) { m_secsPlayed = i; }
unsigned int trackDuration() const { return m_trackDuration; }
void setTrackDuration( unsigned int trackDuration ) { m_trackDuration = trackDuration; }
int action() const { return m_action; }
void setAction( int a ) { m_action = (Action)a; }
signals:
void trackPlaying( const Tomahawk::query_ptr& query );
void trackPlaying( const Tomahawk::query_ptr& query, unsigned int duration );
void trackPlayed( const Tomahawk::query_ptr& query );
private:
@@ -95,6 +101,7 @@ private:
QString m_track;
unsigned int m_playtime;
unsigned int m_secsPlayed;
unsigned int m_trackDuration;
Action m_action;
};

View File

@@ -65,7 +65,7 @@ DatabaseCommand_PlaybackHistory::exec( DatabaseImpl* dbi )
if ( query_track.next() )
{
Tomahawk::query_ptr q = Tomahawk::Query::get( query_track.value( 1 ).toString(), query_track.value( 0 ).toString(), QString(), uuid() );
Tomahawk::query_ptr q = Tomahawk::Query::get( query_track.value( 1 ).toString(), query_track.value( 0 ).toString(), QString() );
if ( query.value( 3 ).toUInt() == 0 )
{
@@ -80,8 +80,6 @@ DatabaseCommand_PlaybackHistory::exec( DatabaseImpl* dbi )
}
}
qDebug() << Q_FUNC_INFO << ql.length();
if ( ql.count() )
emit tracks( ql );
}

View File

@@ -157,7 +157,6 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
result->setRID( uuid() );
result->setAlbumPos( files_query.value( 14 ).toUInt() );
result->setTrackId( files_query.value( 9 ).toUInt() );
result->setYear( files_query.value( 17 ).toUInt() );
TomahawkSqlQuery attrQuery = lib->newquery();
QVariantMap attr;

View File

@@ -249,8 +249,8 @@ DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib )
controlsQuery.exec();
}
}
if ( m_applied )
{
tLog() << "updating dynamic playlist, optimistic locking okay";

View File

@@ -60,6 +60,7 @@ public:
virtual void exec( DatabaseImpl* lib );
virtual void postCommitHook();
virtual bool doesMutates() const { return true; }
virtual bool groupable() const { return true; }
void setControlsV( const QVariantList& vlist )
{

View File

@@ -104,6 +104,7 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
}
else
{
tDebug() << "Playlist:" << m_playlistguid << m_currentRevision << source()->friendlyName() << source()->id();
throw "No such playlist, WTF?";
return;
}
@@ -212,6 +213,6 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
else if ( !m_oldrev.isEmpty() )
{
tDebug() << "Not updating current revision, optimistic locking fail";
Q_ASSERT( false );
// Q_ASSERT( false );
}
}

View File

@@ -58,6 +58,7 @@ public:
virtual bool doesMutates() const { return true; }
virtual bool localOnly() const { return m_localOnly; }
virtual bool groupable() const { return true; }
void setAddedentriesV( const QVariantList& vlist )
{

View File

@@ -170,6 +170,7 @@ public:
void setTimestamp( const int ts ) { m_timestamp = ts; }
virtual bool doesMutates() const { return true; }
virtual bool groupable() const { return true; }
private:
Tomahawk::result_ptr m_result;

View File

@@ -26,6 +26,7 @@
DatabaseCommand_UpdateSearchIndex::DatabaseCommand_UpdateSearchIndex()
: DatabaseCommand()
{
tLog() << Q_FUNC_INFO << "Updating index.";
}

View File

@@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -72,16 +72,21 @@ DatabaseWorker::run()
}
void
DatabaseWorker::enqueue( const QList< QSharedPointer<DatabaseCommand> >& cmds )
{
QMutexLocker lock( &m_mut );
m_outstanding += cmds.count();
m_commands << cmds;
if ( m_outstanding == cmds.count() )
QTimer::singleShot( 0, this, SLOT( doWork() ) );
}
void
DatabaseWorker::enqueue( const QSharedPointer<DatabaseCommand>& cmd )
{
if ( QThread::currentThread() != thread() )
{
// qDebug() << Q_FUNC_INFO << "Reinvoking in correct thread.";
QMetaObject::invokeMethod( this, "enqueue", Qt::QueuedConnection, Q_ARG( QSharedPointer<DatabaseCommand>, cmd ) );
return;
}
QMutexLocker lock( &m_mut );
m_outstanding++;
m_commands << cmd;
@@ -107,6 +112,7 @@ DatabaseWorker::doWork()
timer.start();
#endif
QList< QSharedPointer<DatabaseCommand> > cmdGroup;
QSharedPointer<DatabaseCommand> cmd;
{
QMutexLocker lock( &m_mut );
@@ -119,10 +125,15 @@ DatabaseWorker::doWork()
Q_ASSERT( transok );
Q_UNUSED( transok );
}
unsigned int completed = 0;
try
{
bool finished = false;
{
// tDebug() << "Executing cmd:" << cmd->guid();
while ( !finished )
{
completed++;
cmd->_exec( m_dbimpl ); // runs actual SQL stuff
if ( cmd->loggable() )
@@ -146,8 +157,6 @@ DatabaseWorker::doWork()
//
if ( !cmd->singletonCmd() )
{
// qDebug() << "Setting lastop for source" << cmd->source()->id() << "to" << cmd->guid();
TomahawkSqlQuery query = m_dbimpl->newquery();
query.prepare( "UPDATE source SET lastop = ? WHERE id = ?" );
query.addBindValue( cmd->guid() );
@@ -155,20 +164,35 @@ DatabaseWorker::doWork()
if ( !query.exec() )
{
qDebug() << "Failed to set lastop";
throw "Failed to set lastop";
}
}
}
}
cmdGroup << cmd;
if ( cmd->groupable() && !m_commands.isEmpty() )
{
QMutexLocker lock( &m_mut );
if ( m_commands.first()->groupable() )
{
cmd = m_commands.takeFirst();
}
else
{
finished = true;
}
}
else
finished = true;
}
if ( cmd->doesMutates() )
{
qDebug() << "Committing" << cmd->commandname() << cmd->guid();
if ( !m_dbimpl->database().commit() )
{
qDebug() << "*FAILED TO COMMIT TRANSACTION*";
tDebug() << "FAILED TO COMMIT TRANSACTION*";
throw "commit failed";
}
}
@@ -178,7 +202,8 @@ DatabaseWorker::doWork()
tDebug() << "DBCmd Duration:" << duration << "ms, now running postcommit for" << cmd->commandname();
#endif
cmd->postCommit();
foreach ( QSharedPointer<DatabaseCommand> c, cmdGroup )
c->postCommit();
#ifdef DEBUG_TIMING
tDebug() << "Post commit finished in" << timer.elapsed() - duration << "ms for" << cmd->commandname();
@@ -195,7 +220,7 @@ DatabaseWorker::doWork()
<< m_dbimpl->database().lastError().driverText()
<< endl;
if( cmd->doesMutates() )
if ( cmd->doesMutates() )
m_dbimpl->database().rollback();
Q_ASSERT( false );
@@ -203,17 +228,19 @@ DatabaseWorker::doWork()
catch(...)
{
qDebug() << "Uncaught exception processing dbcmd";
if( cmd->doesMutates() )
if ( cmd->doesMutates() )
m_dbimpl->database().rollback();
Q_ASSERT( false );
throw;
}
cmd->emitFinished();
foreach ( QSharedPointer<DatabaseCommand> c, cmdGroup )
c->emitFinished();
QMutexLocker lock( &m_mut );
if ( --m_outstanding > 0 )
m_outstanding -= completed;
if ( m_outstanding > 0 )
QTimer::singleShot( 0, this, SLOT( doWork() ) );
}

View File

@@ -47,6 +47,7 @@ public:
public slots:
void enqueue( const QSharedPointer<DatabaseCommand>& );
void enqueue( const QList< QSharedPointer<DatabaseCommand> >& );
protected:
void run();

View File

@@ -266,6 +266,7 @@ CREATE TABLE IF NOT EXISTS playback_log (
playtime INTEGER NOT NULL, -- when playback finished (timestamp)
secs_played INTEGER NOT NULL
);
CREATE INDEX playback_log_source ON playback_log(source);
CREATE INDEX playback_log_track ON playback_log(track);

View File

@@ -1,5 +1,5 @@
/*
This file was automatically generated from schema.sql on Thu Sep 29 17:28:17 EDT 2011.
This file was automatically generated from schema.sql on Wed Nov 16 22:47:16 EST 2011.
*/
static const char * tomahawk_schema_sql =

View File

@@ -34,10 +34,12 @@
#include "utils/xspfloader.h"
#include "jobview/JobStatusView.h"
#include "jobview/JobStatusModel.h"
using namespace Tomahawk;
bool DropJob::s_canParseSpotifyPlaylists = false;
DropJob::DropJob( QObject *parent )
: QObject( parent )
, m_queryCount( 0 )
@@ -50,11 +52,13 @@ DropJob::DropJob( QObject *parent )
{
}
DropJob::~DropJob()
{
qDebug() << "destryong DropJob";
}
/// QMIMEDATA HANDLING
QStringList
@@ -68,15 +72,18 @@ DropJob::mimeTypes()
<< "application/tomahawk.metadata.artist"
<< "application/tomahawk.metadata.album"
<< "application/tomahawk.mixed"
<< "text/plain";
<< "text/plain"
<< "text/uri-list";
return mimeTypes;
}
bool
DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType, DropJob::DropAction acceptedAction )
{
Q_UNUSED( acceptedAction );
if ( data->hasFormat( "application/tomahawk.query.list" )
|| data->hasFormat( "application/tomahawk.plentry.list" )
|| data->hasFormat( "application/tomahawk.result.list" )
@@ -90,6 +97,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
// check plain text url types
if ( !data->hasFormat( "text/plain" ) )
if ( !data->hasFormat( "text/uri-list" ) )
return false;
const QString url = data->data( "text/plain" );
@@ -99,6 +107,9 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
if( url.contains( "xspf" ) )
return true;
if( data->data( "text/uri-list" ).contains( "xspf" ) )
return true;
// Not the most elegant
if ( url.contains( "spotify" ) && url.contains( "playlist" ) && s_canParseSpotifyPlaylists )
return true;
@@ -137,21 +148,22 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
return true;
}
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
// We whitelist certain url-shorteners since they do some link checking. Often playable (e.g. spotify) links hide behind them,
// so we do an extra level of lookup
if ( url.contains( "bit.ly" ) || url.contains( "j.mp" ) || url.contains( "t.co" ) || url.contains( "rd.io" ) )
if ( ShortenedLinkParser::handlesUrl( url ) )
return true;
return false;
}
bool
DropJob::isDropType( DropJob::DropType desired, const QMimeData* data )
{
const QString url = data->data( "text/plain" );
if ( desired == Playlist )
{
if( url.contains( "xspf" ) )
if( url.contains( "xspf" ) || data->data( "text/uri-list").contains( "xspf" ) )
return true;
// Not the most elegant
@@ -161,11 +173,7 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data )
if ( url.contains( "rdio.com" ) && url.contains( "people" ) && url.contains( "playlist" ) )
return true;
// we don't know about these.. gotta say yes for now
if ( url.contains( "bit.ly" ) ||
url.contains( "j.mp" ) ||
url.contains( "t.co" ) ||
url.contains( "rd.io" ) )
if ( ShortenedLinkParser::handlesUrl( url ) )
return true;
}
@@ -179,6 +187,7 @@ DropJob::setGetWholeArtists( bool getWholeArtists )
m_getWholeArtists = getWholeArtists;
}
void
DropJob::setGetWholeAlbums( bool getWholeAlbums )
{
@@ -208,10 +217,12 @@ DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates, bool o
}
}
void
DropJob::parseMimeData( const QMimeData *data )
{
QList< query_ptr > results;
if ( data->hasFormat( "application/tomahawk.query.list" ) )
results = tracksFromQueryList( data );
else if ( data->hasFormat( "application/tomahawk.result.list" ) )
@@ -222,15 +233,22 @@ DropJob::parseMimeData( const QMimeData *data )
results = tracksFromArtistMetaData( data );
else if ( data->hasFormat( "application/tomahawk.mixed" ) )
tracksFromMixedData( data );
else if ( data->hasFormat( "text/plain" ) )
else if ( data->hasFormat( "text/plain" ) && !data->data( "text/plain" ).isEmpty() )
{
const QString plainData = QString::fromUtf8( data->data( "text/plain" ) );
handleAllUrls( plainData );
}
else if ( data->hasFormat( "text/uri-list" ) )
{
const QString plainData = QString::fromUtf8( data->data( "text/uri-list" ).trimmed() );
handleAllUrls( plainData );
}
m_resultList.append( results );
}
QList< query_ptr >
DropJob::tracksFromQueryList( const QMimeData* data )
{
@@ -270,6 +288,7 @@ DropJob::tracksFromQueryList( const QMimeData* data )
return queries;
}
QList< query_ptr >
DropJob::tracksFromResultList( const QMimeData* data )
{
@@ -311,6 +330,7 @@ DropJob::tracksFromResultList( const QMimeData* data )
return queries;
}
QList< query_ptr >
DropJob::tracksFromAlbumMetaData( const QMimeData *data )
{
@@ -332,9 +352,11 @@ DropJob::tracksFromAlbumMetaData( const QMimeData *data )
else
queries << getAlbum( artist, album );
}
return queries;
}
QList< query_ptr >
DropJob::tracksFromArtistMetaData( const QMimeData *data )
{
@@ -359,6 +381,7 @@ DropJob::tracksFromArtistMetaData( const QMimeData *data )
return queries;
}
QList< query_ptr >
DropJob::tracksFromMixedData( const QMimeData *data )
{
@@ -404,40 +427,59 @@ DropJob::tracksFromMixedData( const QMimeData *data )
singleMimeData.setData( mimeType, singleData );
parseMimeData( &singleMimeData );
}
return queries;
}
void
DropJob::handleXspfs( const QString& fileUrls )
{
tDebug() << Q_FUNC_INFO << "Got xspf playlist!!" << fileUrls;
QStringList urls = fileUrls.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
tDebug() << Q_FUNC_INFO << "Got XSPF playlist!" << fileUrls;
bool error = false;
QStringList urls = fileUrls.split( QRegExp( "\n" ), QString::SkipEmptyParts );
if ( dropAction() == Default )
setDropAction( Create );
foreach ( const QString& url, urls )
{
XSPFLoader* l = 0;
QFile xspfFile( QUrl::fromUserInput( url ).toLocalFile() );
if ( xspfFile.exists() )
{
XSPFLoader* l = new XSPFLoader( true, this );
tDebug( LOGINFO ) << "Loading local xspf " << xspfFile.fileName();
l = new XSPFLoader( dropAction() == Create, this );
tDebug( LOGINFO ) << "Loading local XSPF" << xspfFile.fileName();
l->load( xspfFile );
}
else if ( QUrl( url ).isValid() )
{
l = new XSPFLoader( dropAction() == Create, this );
tDebug( LOGINFO ) << "Loading remote XSPF" << url;
l->load( QUrl( url ) );
}
else
tLog( LOGINFO ) << "Error Loading local xspf " << xspfFile.fileName();
{
error = true;
tLog() << "Failed to load or parse dropped XSPF";
}
if ( dropAction() == Append && !error && l )
{
qDebug() << Q_FUNC_INFO << "Trying to append XSPF";
connect( l, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
m_queryCount++;
}
}
}
void
DropJob::handleSpotifyUrls( const QString& urlsRaw )
{
QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
qDebug() << "Got spotify browse uris!!" << urls;
qDebug() << "Got spotify browse uris!" << urls;
/// Lets allow parsing all spotify uris here, if parse server is not available
/// fallback to spotify metadata for tracks /hugo
@@ -458,11 +500,12 @@ DropJob::handleSpotifyUrls( const QString& urlsRaw )
m_queryCount++;
}
void
DropJob::handleRdioUrls( const QString& urlsRaw )
{
QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
qDebug() << "Got Rdio urls!!" << urls;
qDebug() << "Got Rdio urls!" << urls;
if ( dropAction() == Default )
setDropAction( Create );
@@ -470,10 +513,10 @@ DropJob::handleRdioUrls( const QString& urlsRaw )
RdioParser* rdio = new RdioParser( this );
connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
m_queryCount++;
rdio->setCreatePlaylist( dropAction() == Create );
rdio->parse( urls );
m_queryCount++;
}
@@ -524,10 +567,8 @@ DropJob::handleTrackUrls( const QString& urls )
m_queryCount++;
rdio->parse( tracks );
} else if ( urls.contains( "bit.ly" ) ||
urls.contains( "j.mp" ) ||
urls.contains( "t.co" ) ||
urls.contains( "rd.io" ) )
}
else if ( ShortenedLinkParser::handlesUrl( urls ) )
{
QStringList tracks = urls.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
@@ -538,6 +579,7 @@ DropJob::handleTrackUrls( const QString& urls )
}
}
void
DropJob::expandedUrls( QStringList urls )
{
@@ -545,6 +587,7 @@ DropJob::expandedUrls( QStringList urls )
handleAllUrls( urls.join( "\n" ) );
}
void
DropJob::onTracksAdded( const QList<Tomahawk::query_ptr>& tracksList )
{
@@ -569,6 +612,7 @@ DropJob::onTracksAdded( const QList<Tomahawk::query_ptr>& tracksList )
}
}
void
DropJob::removeDuplicates()
{
@@ -584,9 +628,11 @@ DropJob::removeDuplicates()
if ( !contains )
list.append( item );
}
m_resultList = list;
}
void
DropJob::removeRemoteSources()
{
@@ -605,6 +651,7 @@ DropJob::removeRemoteSources()
m_resultList = list;
}
void
DropJob::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
@@ -634,6 +681,7 @@ DropJob::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVar
}
}
QList< query_ptr >
DropJob::getArtist( const QString &artist )
{
@@ -649,6 +697,7 @@ DropJob::getArtist( const QString &artist )
return artistPtr->tracks();
}
QList< query_ptr >
DropJob::getAlbum(const QString &artist, const QString &album)
{
@@ -672,6 +721,7 @@ DropJob::getAlbum(const QString &artist, const QString &album)
return albumPtr->tracks();
}
void
DropJob::getTopTen( const QString &artist )
{

View File

@@ -62,7 +62,8 @@ public:
enum DropAction {
Default = 0,
Append,
Create
Create,
Move
};
/**
@@ -108,6 +109,7 @@ public:
static bool canParseSpotifyPlaylists() { return s_canParseSpotifyPlaylists; }
static void setCanParseSpotifyPlaylists( bool parseable ) { s_canParseSpotifyPlaylists = parseable; }
signals:
/// QMimeData parsing results
void tracks( const QList< Tomahawk::query_ptr >& tracks );

View File

@@ -297,12 +297,12 @@ GlobalActionManager::handlePlaylistCommand( const QUrl& url )
tDebug() << "No xspf to load...";
return false;
}
QUrl xspf = QUrl( url.queryItemValue( "xspf" ) );
QUrl xspf = QUrl::fromUserInput( url.queryItemValue( "xspf" ) );
QString title = url.hasQueryItem( "title" ) ? url.queryItemValue( "title" ) : QString();
XSPFLoader* l= new XSPFLoader( true, this );
l->setOverrideTitle( title );
l->load( xspf );
connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), ViewManager::instance(), SLOT( show( Tomahawk::playlist_ptr ) ) );
connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), this, SLOT( playlistCreatedToShow( Tomahawk::playlist_ptr) ) );
} else if( parts [ 0 ] == "new" ) {
if( !url.hasQueryItem( "title" ) ) {
@@ -323,6 +323,22 @@ GlobalActionManager::handlePlaylistCommand( const QUrl& url )
return false;
}
void
GlobalActionManager::playlistCreatedToShow( const playlist_ptr& pl )
{
connect( pl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistReadyToShow() ) );
pl->setProperty( "sharedptr", QVariant::fromValue<Tomahawk::playlist_ptr>( pl ) );
}
void GlobalActionManager::playlistReadyToShow()
{
playlist_ptr pl = sender()->property( "sharedptr" ).value<Tomahawk::playlist_ptr>();
if ( !pl.isNull() )
ViewManager::instance()->show( pl );
disconnect( sender(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistReadyToShow() ) );
}
bool
GlobalActionManager::handleCollectionCommand( const QUrl& url )
@@ -408,6 +424,7 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
QString title, artist, album, urlStr;
foreach( pair, queryItems ) {
pair.second = pair.second.replace( "+", " " ); // QUrl::queryItems doesn't decode + to a space :(
if( pair.first == "title" )
title = pair.second;
else if( pair.first == "artist" )

View File

@@ -81,6 +81,8 @@ private slots:
void playOrQueueNow( const Tomahawk::query_ptr& );
void playNow( const Tomahawk::query_ptr& );
void playlistCreatedToShow( const Tomahawk::playlist_ptr& pl );
void playlistReadyToShow();
private:
explicit GlobalActionManager( QObject* parent = 0 );
void doBookmark( const Tomahawk::playlist_ptr& pl, const Tomahawk::query_ptr& q );

View File

@@ -39,9 +39,6 @@
<height>64</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
@@ -76,9 +73,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
@@ -92,9 +86,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
@@ -143,9 +134,6 @@
<height>62</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>

View File

@@ -19,12 +19,10 @@
#include "chartsplugin.h"
#include <QDir>
#include <QSettings>
#include <QCryptographicHash>
#include <QNetworkConfiguration>
#include <QNetworkReply>
#include <QDomElement>
#include <QtCore/QDir>
#include <QtCore/QSettings>
#include <QtNetwork/QNetworkConfiguration>
#include <QtNetwork/QNetworkReply>
#include "album.h"
#include "chartsplugin_data_p.h"
@@ -34,7 +32,7 @@
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#define CHART_URL "http://charts.tomahawk-player.org:10080/"
#define CHART_URL "http://charts.tomahawk-player.org/"
//#define CHART_URL "http://localhost:8080/"
#include <qjson/parser.h>
#include <qjson/serializer.h>
@@ -50,27 +48,12 @@ ChartsPlugin::ChartsPlugin()
m_chartResources << "billboard" << "itunes" << "rdio" << "wearehunted" << "ex.fm";
m_supportedGetTypes << InfoChart << InfoChartCapabilities;
/// Then get each chart from resource
/// We want to prepopulate the breadcrumb to fetch them before they are asked for
if ( !m_chartResources.isEmpty() && m_allChartsMap.isEmpty() )
{
tDebug() << "ChartsPlugin: InfoChart fetching possible resources";
foreach ( QVariant resource, m_chartResources )
{
QUrl url = QUrl( QString( CHART_URL "source/%1" ).arg(resource.toString() ) );
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
tDebug() << "fetching:" << url;
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
m_chartsFetchJobs++;
}
}
}
ChartsPlugin::~ChartsPlugin()
{
qDebug() << Q_FUNC_INFO;
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
}
@@ -85,27 +68,27 @@ ChartsPlugin::dataError( Tomahawk::InfoSystem::InfoRequestData requestData )
void
ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO << requestData.caller;
qDebug() << Q_FUNC_INFO << requestData.customData;
//qDebug() << Q_FUNC_INFO << requestData.caller;
//qDebug() << Q_FUNC_INFO << requestData.customData;
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
bool foundSource = false;
switch ( requestData.type )
{
case InfoChart:
/// We need something to check if the request is actually ment to go to this plugin
if ( !hash.contains( "chart_source" ) )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required param!";
dataError( requestData );
break;
}
else
{
foreach( QVariant resource, m_chartResources )
foreach( QString resource, m_chartResources )
{
if( resource.toString() == hash["chart_source"] )
if( resource == hash["chart_source"] )
{
foundSource = true;
}
@@ -130,15 +113,6 @@ ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
}
void
ChartsPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
void
ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
{
@@ -155,6 +129,7 @@ ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
/// Each request needs to contain both a id and source
if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required params!";
dataError( requestData );
return;
@@ -163,7 +138,7 @@ ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
criteria["chart_id"] = hash["chart_id"];
criteria["chart_source"] = hash["chart_source"];
emit getCachedInfo( criteria, 0, requestData );
emit getCachedInfo( criteria, 86400000, requestData );
}
void
@@ -171,13 +146,14 @@ ChartsPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requ
{
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Could not convert requestData to InfoStringHash!";
dataError( requestData );
return;
}
Tomahawk::InfoSystem::InfoStringHash criteria;
emit getCachedInfo( criteria, 0, requestData );
criteria[ "InfoChartCapabilities" ] = "chartsplugin";
emit getCachedInfo( criteria, 604800000, requestData );
}
void
@@ -187,9 +163,11 @@ ChartsPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
{
case InfoChart:
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
/// Fetch the chart, we need source and id
QUrl url = QUrl( QString( CHART_URL "source/%1/chart/%2" ).arg( criteria["chart_source"] ).arg( criteria["chart_id"] ) );
qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Getting chart url" << url;
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
@@ -201,9 +179,33 @@ ChartsPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
case InfoChartCapabilities:
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
// we never need to re-fetch
if ( !m_allChartsMap.isEmpty() )
return;
/// Then get each chart from resource
if ( !m_chartResources.isEmpty() && m_allChartsMap.isEmpty() )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart fetching possible resources";
foreach ( QString resource, m_chartResources )
{
QUrl url = QUrl( QString( CHART_URL "source/%1" ).arg( resource ) );
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
reply->setProperty( "chart_resource", resource);
tDebug() << "fetching:" << url;
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
m_chartsFetchJobs++;
}
}
if ( m_chartsFetchJobs > 0 )
{
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
m_cachedRequests.append( requestData );
return;
}
@@ -226,9 +228,10 @@ void
ChartsPlugin::chartTypes()
{
/// Get possible chart type for specificChartsPlugin: InfoChart types returned chart source
tDebug() << "Got chart type result";
tDebug( LOGVERBOSE ) << "Got chart type result";
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
if ( reply->error() == QNetworkReply::NoError )
{
QJson::Parser p;
@@ -262,7 +265,8 @@ ChartsPlugin::chartTypes()
QHash< QString, QVariantMap > extraType;
foreach( const QVariant& chartObj, chartObjs.values() )
{
if( !chartObj.toMap().isEmpty() ){
if( !chartObj.toMap().isEmpty() )
{
const QVariantMap chart = chartObj.toMap();
const QString id = chart.value( "id" ).toString();
const QString geo = chart.value( "geo" ).toString();
@@ -271,7 +275,8 @@ ChartsPlugin::chartTypes()
const bool isDefault = ( chart.contains( "default" ) && chart[ "default" ].toInt() == 1 );
QString extra;
if( !geo.isEmpty() ){
if( !geo.isEmpty() )
{
if ( !m_cachedCountries.contains( geo ) )
{
@@ -289,10 +294,10 @@ ChartsPlugin::chartTypes()
m_cachedCountries[ geo ] = extra;
}
else
{
extra = m_cachedCountries[ geo ];
}
}else extra = chart.value( "extra" ).toString();
else
extra = chart.value( "extra" ).toString();
if ( name.isEmpty() ) // not a specific chart, an all chart
name = tr( "Top Overall" );
@@ -304,10 +309,10 @@ ChartsPlugin::chartTypes()
if ( isDefault )
c[ "default" ] = "true";
QList<InfoStringHash> extraTypeData = extraType[ extra ][ type ].value< QList< InfoStringHash > >();
QList< Tomahawk::InfoSystem::InfoStringHash > extraTypeData = extraType[ extra ][ type ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
extraTypeData.append( c );
extraType[ extra ][ type ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( extraTypeData );
extraType[ extra ].insert( type, QVariant::fromValue< QList< InfoStringHash > >( extraTypeData ) );
if ( isDefault )
{
defaultChain.clear();
@@ -319,7 +324,7 @@ ChartsPlugin::chartTypes()
foreach( const QString& c, extraType.keys() )
{
charts[ c ] = extraType[ c ];
// qDebug() << "extraType has types:" << c;
// tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "extraType has types:" << c;
}
if( source == "itunes" ){
chartName = "iTunes";
@@ -330,7 +335,8 @@ ChartsPlugin::chartTypes()
}
}
}else
}
else
{
// We'll just build:
// [Source] - Album - Chart Type
@@ -380,11 +386,11 @@ ChartsPlugin::chartTypes()
}
}
if( !artistCharts.isEmpty() )
charts.insert( tr( "Artists" ), QVariant::fromValue< QList< InfoStringHash > >( artistCharts ) );
charts.insert( tr( "Artists" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( artistCharts ) );
if( !albumCharts.isEmpty() )
charts.insert( tr( "Albums" ), QVariant::fromValue< QList< InfoStringHash > >( albumCharts ) );
charts.insert( tr( "Albums" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( albumCharts ) );
if( !trackCharts.isEmpty() )
charts.insert( tr( "Tracks" ), QVariant::fromValue< QList< InfoStringHash > >( trackCharts ) );
charts.insert( tr( "Tracks" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( trackCharts ) );
/// @note For displaying purposes, upper the first letter
/// @note Remeber to lower it when fetching this!
@@ -394,7 +400,7 @@ ChartsPlugin::chartTypes()
}
/// Add the possible charts and its types to breadcrumb
// qDebug() << "ADDING CHART TYPE TO CHARTS:" << chartName;
// tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "ADDING CHART TYPE TO CHARTS:" << chartName;
QVariantMap defaultMap = m_allChartsMap.value( "defaults" ).value< QVariantMap >();
defaultMap[ source ] = defaultChain;
m_allChartsMap[ "defaults" ] = defaultMap;
@@ -413,6 +419,10 @@ ChartsPlugin::chartTypes()
foreach ( InfoRequestData request, m_cachedRequests )
{
emit info( request, m_allChartsMap );
// update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "chartsplugin";
emit updateCache( criteria, 604800000, request.type, m_allChartsMap );
}
m_cachedRequests.clear();
}
@@ -441,8 +451,8 @@ ChartsPlugin::chartReturned()
/// SO we have a result, parse it!
QVariantList chartResponse = res.value( "list" ).toList();
QList< InfoStringHash > top_tracks;
QList< InfoStringHash > top_albums;
QList< Tomahawk::InfoSystem::InfoStringHash > top_tracks;
QList< Tomahawk::InfoSystem::InfoStringHash > top_albums;
QStringList top_artists;
/// Deside what type, we need to handle it differently
@@ -478,16 +488,16 @@ ChartsPlugin::chartReturned()
if ( album.isEmpty() && artist.isEmpty() ) // don't have enough...
{
tLog() << "Didn't get an artist and album name from chart, not enough to build a query on. Aborting" << title << album << artist;
tDebug( LOGVERBOSE ) << "Didn't get an artist and album name from chart, not enough to build a query on. Aborting" << title << album << artist;
}
else
{
qDebug() << Q_FUNC_INFO << album << artist;
InfoStringHash pair;
Tomahawk::InfoSystem::InfoStringHash pair;
pair["artist"] = artist;
pair["album"] = album;
top_albums << pair;
top_albums.append( pair );
}
}
@@ -497,28 +507,28 @@ ChartsPlugin::chartReturned()
if ( title.isEmpty() && artist.isEmpty() ) // don't have enough...
{
tLog() << "Didn't get an artist and track name from charts, not enough to build a query on. Aborting" << title << artist << album;
tDebug( LOGVERBOSE ) << "Didn't get an artist and track name from charts, not enough to build a query on. Aborting" << title << artist << album;
}
else
{
InfoStringHash pair;
Tomahawk::InfoSystem::InfoStringHash pair;
pair["artist"] = artist;
pair["track"] = title;
top_tracks << pair;
top_tracks.append( pair );
}
}else if( chartType() == Artist )
{
if ( artist.isEmpty() ) // don't have enough...
{
tLog() << "Didn't get an artist from charts, not enough to build a query on. Aborting" << artist;
tDebug( LOGVERBOSE ) << "Didn't get an artist from charts, not enough to build a query on. Aborting" << artist;
}
else
{
top_artists << artist;
top_artists.append( artist );
}
}
@@ -528,31 +538,35 @@ ChartsPlugin::chartReturned()
if( chartType() == Artist )
{
tDebug() << "ChartsPlugin:" << "\tgot " << top_artists.size() << " artists";
returnedData["artists"] = QVariant::fromValue( top_artists );
returnedData["type"] = "artists";
returnedData[ "artists" ] = QVariant::fromValue< QStringList >( top_artists );
returnedData[ "type" ] = "artists";
}
if( chartType() == Track )
{
tDebug() << "ChartsPlugin:" << "\tgot " << top_tracks.size() << " tracks";
returnedData["tracks"] = QVariant::fromValue( top_tracks );
returnedData["type"] = "tracks";
returnedData[ "tracks" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( top_tracks );
returnedData[ "type" ] = "tracks";
}
if( chartType() == Album )
{
tDebug() << "ChartsPlugin:" << "\tgot " << top_albums.size() << " albums";
returnedData["albums"] = QVariant::fromValue( top_albums );
returnedData["type"] = "albums";
returnedData[ "albums" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( top_albums );
returnedData[ "type" ] = "albums";
}
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( requestData, returnedData );
// TODO update cache
// update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
criteria[ "chart_id" ] = origData[ "chart_id" ];
criteria[ "chart_source" ] = origData[ "chart_source" ];
emit updateCache( criteria, 86400000, requestData.type, returnedData );
}
else
qDebug() << "Network error in fetching chart:" << reply->url().toString();
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Network error in fetching chart:" << reply->url().toString();
}

View File

@@ -21,8 +21,8 @@
#include "infosystem/infosystem.h"
#include "infosystem/infosystemworker.h"
#include <QNetworkReply>
#include <QObject>
#include <QtNetwork/QNetworkReply>
#include <QtCore/QObject>
class QNetworkReply;
@@ -47,6 +47,7 @@ public:
Artist = 0x04
};
void setChartType( ChartType type ) { m_chartType = type; }
ChartType chartType() const { return m_chartType; }
@@ -58,15 +59,20 @@ protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data )
{
Q_UNUSED( caller )
Q_UNUSED( type )
Q_UNUSED( data )
}
private:
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
QVariantList m_chartResources;
QList<InfoStringHash> m_charts;
QStringList m_chartResources;
QList< InfoStringHash > m_charts;
ChartType m_chartType;
QVariantMap m_allChartsMap;

View File

@@ -23,11 +23,9 @@
#include <QCryptographicHash>
#include <QNetworkConfiguration>
#include <QNetworkReply>
#include <QDomElement>
#include "album.h"
#include "typedefs.h"
#include "audio/audioengine.h"
#include "tomahawksettings.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
@@ -140,16 +138,6 @@ hypemPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
}
}
void
hypemPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
void
hypemPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
{
@@ -173,8 +161,9 @@ hypemPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
/// Set the criterias for current chart
criteria["chart_id"] = hash["chart_id"];
criteria["chart_source"] = hash["chart_source"];
emit getCachedInfo( criteria, 0, requestData );
/// @todo
/// set cache time based on wether requested type is 3day, lastweek or recent.
emit getCachedInfo( criteria, 86400000, requestData );
}
void
@@ -198,7 +187,7 @@ hypemPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSys
case InfoChart:
{
/// Fetch the chart, we need source and id
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
QUrl url = QUrl( QString( HYPEM_URL "%1/%2" ).arg( criteria["chart_id"].toLower() ).arg(HYPEM_END_URL) );
qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
@@ -212,6 +201,7 @@ hypemPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSys
case InfoChartCapabilities:
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
if ( m_chartsFetchJobs > 0 )
{
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
@@ -390,7 +380,14 @@ hypemPlugin::chartReturned()
emit info( requestData, returnedData );
// TODO update cache
// update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
criteria[ "chart_id" ] = origData[ "chart_id" ];
criteria[ "chart_source" ] = origData[ "chart_source" ];
/// @todo
/// set cache time based on wether requested type is 3day, lastweek or recent.
emit updateCache( criteria, 86400000, requestData.type, returnedData );
}
else
qDebug() << "Network error in fetching chart:" << reply->url().toString();

View File

@@ -57,8 +57,13 @@ public slots:
protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
private:
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );

View File

@@ -53,11 +53,6 @@ LastFmPlugin::LastFmPlugin()
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChart << InfoChartCapabilities;
m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove;
/*
Your API Key is 7194b85b6d1f424fe1668173a78c0c4a
Your secret is ba80f1df6d27ae63e9cb1d33ccf2052f
*/
// Flush session key cache
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
@@ -394,9 +389,7 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
}
}
tDebug() << "LastFmPlugin: InfoChart not in cache, fetching";
QMap<QString, QString> args;
tDebug() << "LastFmPlugin: " << "args chart_id" << criteria["chart_id"];
args["method"] = criteria["chart_id"];
args["limit"] = "100";
QNetworkReply* reply = lastfm::ws::get(args);
@@ -412,26 +405,24 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
InfoStringHash c;
c[ "type" ] = "tracks";
c[ "id" ] = "chart.getTopTracks";
c[ "label" ] = "Top Tracks";
c[ "label" ] = tr( "Top Tracks" );
track_charts.append( c );
c[ "id" ] = "chart.getLovedTracks";
c[ "label" ] = "Loved Tracks";
c[ "label" ] = tr( "Loved Tracks" );
track_charts.append( c );
c[ "id" ] = "chart.getHypedTracks";
c[ "label" ] = "Hyped Tracks";
c[ "label" ] = tr( "Hyped Tracks" );
track_charts.append( c );
QList< InfoStringHash > artist_charts;
c[ "type" ] = "artists";
c[ "id" ] = "chart.getTopArtists";
c[ "label" ] = "Top Artists";
c[ "label" ] = tr( "Top Artists" );
artist_charts.append( c );
c[ "id" ] = "chart.getHypedArtists";
c[ "label" ] = "Hyped Artists";
c[ "label" ] = tr( "Hyped Artists" );
artist_charts.append( c );
QVariantMap charts;
charts.insert( "Tracks", QVariant::fromValue< QList< InfoStringHash > >( track_charts ) );
charts.insert( "Artists", QVariant::fromValue< QList< InfoStringHash > >( artist_charts ) );
@@ -439,7 +430,6 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
QVariantMap result;
result.insert( "Last.fm", QVariant::fromValue<QVariantMap>( charts ) );
tDebug() << "LASTFM RETURNING CHART LIST!";
emit info( requestData, result );
return;
}
@@ -531,7 +521,6 @@ LastFmPlugin::similarArtistsReturned()
void
LastFmPlugin::chartReturned()
{
tDebug() << "LastfmPlugin: InfoChart data returned!";
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
QVariantMap returnedData;
@@ -549,7 +538,6 @@ LastFmPlugin::chartReturned()
pair[ "track" ] = t.title();
top_tracks << pair;
}
tDebug() << "LastFmPlugin:" << "\tgot " << top_tracks.size() << " tracks";
returnedData["tracks"] = QVariant::fromValue( top_tracks );
returnedData["type"] = "tracks";
@@ -558,7 +546,6 @@ LastFmPlugin::chartReturned()
{
QList<lastfm::Artist> list = lastfm::Artist::list( reply );
QStringList al;
tDebug() << "LastFmPlugin:"<< "\tgot " << list.size() << " artists";
foreach ( const lastfm::Artist& a, list )
al << a.toString();
returnedData["artists"] = al;
@@ -566,7 +553,7 @@ LastFmPlugin::chartReturned()
}
else
{
tDebug() << "LastfmPlugin:: got non tracks and non artists";
tDebug() << Q_FUNC_INFO << "got non tracks and non artists";
}
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();

View File

@@ -165,6 +165,7 @@ MusicBrainzPlugin::artistSearchSlot()
if ( domNodeList.isEmpty() )
{
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
tDebug() << Q_FUNC_INFO << doc.toString();
return;
}

View File

@@ -23,7 +23,6 @@
#include <QCryptographicHash>
#include <QNetworkConfiguration>
#include <QNetworkReply>
#include <QDomElement>
#include "album.h"
#include "typedefs.h"
@@ -33,7 +32,7 @@
#include "utils/logger.h"
#include "chartsplugin_data_p.h"
#define SPOTIFY_API_URL "http://spotikea.tomahawk-player.org:10380/"
#define SPOTIFY_API_URL "http://spotikea.tomahawk-player.org/"
#include <qjson/parser.h>
#include <qjson/serializer.h>
@@ -47,19 +46,6 @@ SpotifyPlugin::SpotifyPlugin()
m_supportedGetTypes << InfoChart << InfoChartCapabilities;
// we never need to re-fetch
if ( !m_allChartsMap.isEmpty() )
return;
/// We need to fetch possible types before they are asked for
tDebug() << "SpotifyPlugin: InfoChart fetching possible resources";
QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/charts" ) );
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
tDebug() << Q_FUNC_INFO << "fetching:" << url;
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
m_chartsFetchJobs++;
}
@@ -107,14 +93,6 @@ SpotifyPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
}
void
SpotifyPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
void
SpotifyPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
{
@@ -123,17 +101,22 @@ SpotifyPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
dataError( requestData );
return;
}
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
Tomahawk::InfoSystem::InfoStringHash criteria;
if ( !hash.contains( "chart_id" ) )
/// Each request needs to contain both a id and source
if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required params!";
dataError( requestData );
return;
} else {
criteria["chart_id"] = hash["chart_id"];
}
emit getCachedInfo( criteria, 604800000 /* Expire chart cache in 1 week */, requestData );
}
/// Set the criterias for current chart
criteria["chart_id"] = hash["chart_id"];
criteria["chart_source"] = hash["chart_source"];
emit getCachedInfo( criteria, 86400000 /* Expire chart cache in 1 day */, requestData );
}
void
SpotifyPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData )
@@ -145,7 +128,8 @@ SpotifyPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData req
}
Tomahawk::InfoSystem::InfoStringHash criteria;
emit getCachedInfo( criteria, 0, requestData );
criteria[ "InfoChartCapabilities" ] = "spotifyplugin";
emit getCachedInfo( criteria, 604800000, requestData );
}
void
@@ -157,6 +141,7 @@ SpotifyPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, To
case InfoChart:
{
/// Fetch the chart, we need source and id
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/%1/" ).arg( criteria["chart_id"] ) );
qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
@@ -169,6 +154,21 @@ SpotifyPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, To
}
case InfoChartCapabilities:
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
// we never need to re-fetch
if ( !m_allChartsMap.isEmpty() )
return;
/// We need to fetch possible types before they are asked for
tDebug() << "SpotifyPlugin: InfoChart fetching possible resources";
QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/charts" ) );
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
tDebug() << Q_FUNC_INFO << "fetching:" << url;
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
m_chartsFetchJobs++;
if ( m_chartsFetchJobs > 0 )
{
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
@@ -275,6 +275,9 @@ SpotifyPlugin::chartTypes()
foreach ( InfoRequestData request, m_cachedRequests )
{
emit info( request, m_allChartsMap );
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "spotifyplugin";
emit updateCache( criteria,604800000, request.type, m_allChartsMap );
}
m_cachedRequests.clear();
}
@@ -379,9 +382,14 @@ SpotifyPlugin::chartReturned()
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( requestData, returnedData );
// update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
criteria[ "chart_id" ] = origData[ "chart_id" ];
criteria[ "chart_source" ] = origData[ "chart_source" ];
emit updateCache( criteria, 86400000, requestData.type, returnedData );
}
else
qDebug() << "Network error in fetching chart:" << reply->url().toString();

View File

@@ -57,7 +57,12 @@ public slots:
protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
private:
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );

View File

@@ -258,7 +258,7 @@ MprisPlugin::metadata() const
// Only return art if tempfile exists, and if its name contains the same "artist_album_tomahawk_cover.png"
if( m_coverTempFile && m_coverTempFile->exists() &&
m_coverTempFile->fileName().contains( track->artist()->name() + "_" + track->album()->name() + "_tomahawk_cover.png" ) )
metadataMap.insert( "mpris:artUrl", QFileInfo( *m_coverTempFile ).absoluteFilePath() );
metadataMap.insert( "mpris:artUrl", QString( QUrl::fromLocalFile( QFileInfo( *m_coverTempFile ).absoluteFilePath() ).toEncoded() ) );
else
{
// Need to fetch the album cover
@@ -275,7 +275,6 @@ MprisPlugin::metadata() const
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
}
}
return metadataMap;

View File

@@ -51,6 +51,7 @@ InfoSystem::instance()
InfoSystem::InfoSystem( QObject *parent )
: QObject( parent )
, m_inited( false )
, m_infoSystemCacheThreadController( 0 )
, m_infoSystemWorkerThreadController( 0 )
{
@@ -59,71 +60,94 @@ InfoSystem::InfoSystem( QObject *parent )
qDebug() << Q_FUNC_INFO;
m_infoSystemCacheThreadController = new InfoSystemCacheThread( this );
m_cache = QWeakPointer< InfoSystemCache >( new InfoSystemCache() );
m_cache.data()->moveToThread( m_infoSystemCacheThreadController );
m_infoSystemCacheThreadController->setCache( m_cache );
m_infoSystemCacheThreadController->start( QThread::IdlePriority );
m_infoSystemWorkerThreadController = new InfoSystemWorkerThread( this );
m_worker = QWeakPointer< InfoSystemWorker >( new InfoSystemWorker() );
m_worker.data()->moveToThread( m_infoSystemWorkerThreadController );
m_infoSystemWorkerThreadController->setWorker( m_worker );
m_infoSystemWorkerThreadController->start();
QMetaObject::invokeMethod( m_worker.data(), "init", Qt::QueuedConnection, Q_ARG( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache >, m_cache ) );
connect( m_cache.data(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
m_worker.data(), SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( finished( QString ) ), this, SIGNAL( finished( QString ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ),
this, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ), Qt::UniqueConnection );
QTimer::singleShot( 0, this, SLOT( init() ) );
}
InfoSystem::~InfoSystem()
{
qDebug() << Q_FUNC_INFO << " beginning";
tDebug() << Q_FUNC_INFO << " beginning";
if ( !m_worker.isNull() )
if ( m_infoSystemWorkerThreadController->worker() )
{
m_infoSystemWorkerThreadController->quit();
m_infoSystemWorkerThreadController->wait( 60000 );
//delete m_worker.data();
delete m_infoSystemWorkerThreadController;
m_infoSystemWorkerThreadController = 0;
}
qDebug() << Q_FUNC_INFO << " done deleting worker";
tDebug() << Q_FUNC_INFO << " done deleting worker";
if( m_infoSystemCacheThreadController )
if( m_infoSystemCacheThreadController->cache() )
{
m_infoSystemCacheThreadController->quit();
m_infoSystemCacheThreadController->wait( 60000 );
//delete m_cache.data();
delete m_infoSystemCacheThreadController;
m_infoSystemCacheThreadController = 0;
}
qDebug() << Q_FUNC_INFO << " done deleting cache";
tDebug() << Q_FUNC_INFO << " done deleting cache";
}
void
InfoSystem::init()
{
tDebug() << Q_FUNC_INFO;
if ( !m_infoSystemCacheThreadController->cache() || !m_infoSystemWorkerThreadController->worker() )
{
QTimer::singleShot( 0, this, SLOT( init() ) );
return;
}
Tomahawk::InfoSystem::InfoSystemCache* cache = m_infoSystemCacheThreadController->cache();
Tomahawk::InfoSystem::InfoSystemWorker* worker = m_infoSystemWorkerThreadController->worker();
connect( cache, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
worker, SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( worker, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( worker, SIGNAL( finished( QString ) ), this, SIGNAL( finished( QString ) ), Qt::UniqueConnection );
connect( worker, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ),
this, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ), Qt::UniqueConnection );
QMetaObject::invokeMethod( worker, "init", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoSystemCache*, cache ) );
m_inited = true;
}
bool
InfoSystem::getInfo( const InfoRequestData &requestData )
{
qDebug() << Q_FUNC_INFO;
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
return false;
}
QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
return true;
}
void
bool
InfoSystem::getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap, bool allSources )
{
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
return false;
}
InfoRequestData requestData;
requestData.caller = caller;
requestData.customData = customData;
@@ -133,82 +157,102 @@ InfoSystem::getInfo( const QString &caller, const QVariantMap &customData, const
requestData.type = type;
requestData.input = inputMap[ type ];
requestData.timeoutMillis = timeoutMap.contains( type ) ? timeoutMap[ type ] : 10000;
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
}
return false;
}
void
bool
InfoSystem::pushInfo( const QString &caller, const InfoType type, const QVariant& input )
{
qDebug() << Q_FUNC_INFO;
QMetaObject::invokeMethod( m_worker.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ) );
tDebug() << Q_FUNC_INFO;
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
return false;
}
QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ) );
return true;
}
void
bool
InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input )
{
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
return false;
}
Q_FOREACH( InfoType type, input.keys() )
QMetaObject::invokeMethod( m_worker.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input[ type ] ) );
QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input[ type ] ) );
return true;
}
InfoSystemCacheThread::InfoSystemCacheThread( QObject *parent )
: QThread( parent )
{
tDebug() << Q_FUNC_INFO;
}
InfoSystemCacheThread::~InfoSystemCacheThread()
{
delete m_cache.data();
tDebug() << Q_FUNC_INFO;
}
void
InfoSystemCacheThread::InfoSystemCacheThread::run()
{
m_cache = QWeakPointer< InfoSystemCache >( new InfoSystemCache() );
exec();
if ( !m_cache.isNull() )
delete m_cache.data();
}
QWeakPointer< InfoSystemCache >
InfoSystemCache*
InfoSystemCacheThread::cache() const
{
return m_cache;
if ( m_cache.isNull() )
return 0;
return m_cache.data();
}
void
InfoSystemCacheThread::setCache( QWeakPointer< InfoSystemCache > cache )
{
m_cache = cache;
}
InfoSystemWorkerThread::InfoSystemWorkerThread( QObject *parent )
: QThread( parent )
{
tDebug() << Q_FUNC_INFO;
}
InfoSystemWorkerThread::~InfoSystemWorkerThread()
{
tDebug() << Q_FUNC_INFO;
}
void
InfoSystemWorkerThread::InfoSystemWorkerThread::run()
{
m_worker = QWeakPointer< InfoSystemWorker >( new InfoSystemWorker() );
exec();
if( m_worker )
if( !m_worker.isNull() )
delete m_worker.data();
}
QWeakPointer< InfoSystemWorker >
InfoSystemWorker*
InfoSystemWorkerThread::worker() const
{
return m_worker;
}
void
InfoSystemWorkerThread::setWorker( QWeakPointer< InfoSystemWorker > worker )
{
m_worker = worker;
if ( m_worker.isNull() )
return 0;
return m_worker.data();
}

View File

@@ -205,8 +205,7 @@ public:
virtual ~InfoSystemCacheThread();
void run();
QWeakPointer< InfoSystemCache > cache() const;
void setCache( QWeakPointer< InfoSystemCache > cache );
InfoSystemCache* cache() const;
private:
QWeakPointer< InfoSystemCache > m_cache;
@@ -221,8 +220,7 @@ public:
virtual ~InfoSystemWorkerThread();
void run();
QWeakPointer< InfoSystemWorker > worker() const;
void setWorker( QWeakPointer< InfoSystemWorker > worker );
InfoSystemWorker* worker() const;
private:
QWeakPointer< InfoSystemWorker > m_worker;
@@ -238,20 +236,22 @@ public:
InfoSystem( QObject *parent );
~InfoSystem();
void getInfo( const InfoRequestData &requestData );
bool getInfo( const InfoRequestData &requestData );
//WARNING: if changing timeoutMillis above, also change in below function in .cpp file
void getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap = InfoTimeoutMap(), bool allSources = false );
void pushInfo( const QString &caller, const InfoType type, const QVariant &input );
void pushInfo( const QString &caller, const InfoTypeMap &input );
bool getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap = InfoTimeoutMap(), bool allSources = false );
bool pushInfo( const QString &caller, const InfoType type, const QVariant &input );
bool pushInfo( const QString &caller, const InfoTypeMap &input );
signals:
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void finished( QString target );
void finished( QString target, Tomahawk::InfoSystem::InfoType type );
private slots:
void init();
private:
QWeakPointer< InfoSystemCache > m_cache;
QWeakPointer< InfoSystemWorker > m_worker;
bool m_inited;
InfoSystemCacheThread* m_infoSystemCacheThreadController;
InfoSystemWorkerThread* m_infoSystemWorkerThreadController;
@@ -287,7 +287,7 @@ inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash )
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoStringHash );
Q_DECLARE_METATYPE( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > );
Q_DECLARE_METATYPE( QList<Tomahawk::InfoSystem::InfoStringHash> );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoSystemCache* );
Q_DECLARE_METATYPE( QList< Tomahawk::InfoSystem::InfoStringHash > );
#endif // TOMAHAWK_INFOSYSTEM_H

View File

@@ -39,6 +39,7 @@ InfoSystemCache::InfoSystemCache( QObject* parent )
, m_cacheBaseDir( QDesktopServices::storageLocation( QDesktopServices::CacheLocation ) + "/InfoSystemCache/" )
, m_cacheVersion( 2 )
{
tDebug() << Q_FUNC_INFO;
TomahawkSettings *s = TomahawkSettings::instance();
if ( s->infoSystemCacheVersion() != m_cacheVersion )
{
@@ -64,6 +65,7 @@ InfoSystemCache::InfoSystemCache( QObject* parent )
InfoSystemCache::~InfoSystemCache()
{
tDebug() << Q_FUNC_INFO;
}
void

View File

@@ -53,7 +53,7 @@ namespace InfoSystem
InfoSystemWorker::InfoSystemWorker()
: QObject()
{
// qDebug() << Q_FUNC_INFO;
tDebug() << Q_FUNC_INFO;
m_checkTimeoutsTimer.setInterval( 1000 );
m_checkTimeoutsTimer.setSingleShot( false );
@@ -64,20 +64,20 @@ InfoSystemWorker::InfoSystemWorker()
InfoSystemWorker::~InfoSystemWorker()
{
// qDebug() << Q_FUNC_INFO << " beginning";
tDebug() << Q_FUNC_INFO << " beginning";
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
{
if( plugin )
delete plugin.data();
}
// qDebug() << Q_FUNC_INFO << " finished";
tDebug() << Q_FUNC_INFO << " finished";
}
void
InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cache )
InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache )
{
// qDebug() << Q_FUNC_INFO << "and cache is" << cache.data();
tDebug() << Q_FUNC_INFO;
InfoPluginPtr enptr( new EchoNestPlugin() );
m_plugins.append( enptr );
@@ -132,13 +132,13 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac
connect(
plugin.data(),
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
cache.data(),
cache,
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) )
);
connect(
plugin.data(),
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
cache.data(),
cache,
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
);
}

View File

@@ -55,7 +55,7 @@ signals:
void finished( QString target, Tomahawk::InfoSystem::InfoType type );
public slots:
void init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > cache );
void init( Tomahawk::InfoSystem::InfoSystemCache* cache );
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );

View File

@@ -21,18 +21,21 @@
#include "JobStatusItem.h"
#include "utils/logger.h"
JobStatusModel::JobStatusModel( QObject* parent )
: QAbstractListModel ( parent )
{
}
JobStatusModel::~JobStatusModel()
{
qDeleteAll( m_items );
m_collapseCount.clear();
}
void
JobStatusModel::addJob( JobStatusItem* item )
{
@@ -55,11 +58,12 @@ JobStatusModel::addJob( JobStatusItem* item )
}
qDebug() << "Adding item:" << item;
beginInsertRows( QModelIndex(), 0, 0 );
m_items.prepend( item );
beginInsertRows( QModelIndex(), m_items.count(), m_items.count() );
m_items.append( item );
endInsertRows();
}
Qt::ItemFlags
JobStatusModel::flags( const QModelIndex& index ) const
{
@@ -81,6 +85,7 @@ JobStatusModel::data( const QModelIndex& index, int role ) const
{
case Qt::DecorationRole:
return item->icon();
case Qt::ToolTipRole:
case Qt::DisplayRole:
{
if ( m_collapseCount.contains( item->type() ) )
@@ -100,6 +105,7 @@ JobStatusModel::data( const QModelIndex& index, int role ) const
return QVariant();
}
int
JobStatusModel::rowCount( const QModelIndex& parent ) const
{
@@ -114,7 +120,7 @@ JobStatusModel::itemFinished()
JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() );
Q_ASSERT( item );
tDebug() << "Got item finished:" << item->type() << item->mainText() << item;
// tDebug() << "Got item finished:" << item->type() << item->mainText() << item;
if ( !m_items.contains( item ) && !m_collapseCount.contains( item->type() ) )
return;
@@ -140,7 +146,7 @@ JobStatusModel::itemFinished()
// qDebug() << "Replaced" << m_collapseCount[ item->type() ].first() << "with:" << m_collapseCount[ item->type() ][ 1 ] << m_items;
}
m_collapseCount[ item->type() ].removeAll( item );
tDebug() << "New collapse count list:" << m_collapseCount[ item->type() ];
// tDebug() << "New collapse count list:" << m_collapseCount[ item->type() ];
if ( m_collapseCount[ item->type() ].isEmpty() )
m_collapseCount.remove( item->type() );
else
@@ -164,6 +170,7 @@ JobStatusModel::itemFinished()
item->deleteLater();
}
void
JobStatusModel::itemUpdated()
{

View File

@@ -19,23 +19,22 @@
#include "JobStatusView.h"
#include "libtomahawk/pipeline.h"
#include "pipeline.h"
#include "JobStatusModel.h"
#include "JobStatusDelegate.h"
#include "PipelineStatusItem.h"
#include "TransferStatusItem.h"
#include "LatchedStatusItem.h"
#include "utils/logger.h"
#include <QHeaderView>
#include <QVBoxLayout>
#include <QListView>
#include <QAbstractItemModel>
#include "TransferStatusItem.h"
#include "LatchedStatusItem.h"
using namespace Tomahawk;
JobStatusView* JobStatusView::s_instance = 0;
JobStatusView::JobStatusView( AnimatedSplitter* parent )
@@ -72,13 +71,12 @@ JobStatusView::JobStatusView( AnimatedSplitter* parent )
setFont( f );
#endif
hideWidget();
new PipelineStatusManager( this );
new TransferStatusManager( this );
new LatchedStatusManager( this );
}
void
JobStatusView::setModel( JobStatusModel* m )
{
@@ -90,15 +88,14 @@ JobStatusView::setModel( JobStatusModel* m )
connect( m_view->model(), SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( checkCount() ) );
}
void
JobStatusView::checkCount()
{
if ( m_view->model()->rowCount() == 0 && !isHidden() )
emit hideWidget();
else if ( isHidden() && m_view->model()->rowCount() > 0 )
emit showWidget();
else
emit sizeChanged( sizeHint() );
emit sizeHintChanged( sizeHint() );
}

View File

@@ -18,8 +18,8 @@
#include "connection.h"
#include <QTime>
#include <QThread>
#include <QtCore/QTime>
#include <QtCore/QThread>
#include "network/servent.h"
#include "utils/logger.h"
@@ -63,7 +63,7 @@ Connection::Connection( Servent* parent )
Connection::~Connection()
{
qDebug() << "DTOR connection (super)" << id() << thread() << m_sock.isNull();
tDebug() << "DTOR connection (super)" << id() << thread() << m_sock.isNull();
if( !m_sock.isNull() )
{
// qDebug() << "deleteLatering sock" << m_sock;
@@ -82,7 +82,7 @@ Connection::handleIncomingQueueEmpty()
// << "m_peer_disconnected" << m_peer_disconnected
// << "bytes rx" << bytesReceived();
if( m_sock->bytesAvailable() == 0 && m_peer_disconnected )
if( !m_sock.isNull() && m_sock->bytesAvailable() == 0 && m_peer_disconnected )
{
qDebug() << "No more data to read, peer disconnected. shutting down connection."
<< "bytesavail" << m_sock->bytesAvailable()
@@ -144,13 +144,13 @@ void
Connection::actualShutdown()
{
qDebug() << Q_FUNC_INFO << m_actually_shutting_down << id();
if( m_actually_shutting_down )
if ( m_actually_shutting_down )
{
return;
}
m_actually_shutting_down = true;
if( !m_sock.isNull() && m_sock->isOpen() )
if ( !m_sock.isNull() && m_sock->isOpen() )
{
m_sock->disconnectFromHost();
}
@@ -261,7 +261,7 @@ Connection::doSetup()
void
Connection::socketDisconnected()
{
qDebug() << "SOCKET DISCONNECTED" << this->name() << id()
tDebug() << "SOCKET DISCONNECTED" << this->name() << id()
<< "shutdown will happen after incoming queue empties."
<< "bytesavail:" << m_sock->bytesAvailable()
<< "bytesRecvd" << bytesReceived();
@@ -276,14 +276,15 @@ Connection::socketDisconnected()
}
}
void
Connection::socketDisconnectedError(QAbstractSocket::SocketError e)
Connection::socketDisconnectedError( QAbstractSocket::SocketError e )
{
qDebug() << "SOCKET ERROR CODE" << e << this->name() << "CALLING Connection::shutdown(false)";
if ( e == QAbstractSocket::RemoteHostClosedError )
return;
qDebug() << "SOCKET ERROR CODE" << e << this->name() << "CALLING Connection::shutdown(false)";
m_peer_disconnected = true;
emit socketErrored(e);
@@ -423,16 +424,16 @@ Connection::sendMsg_now( msg_ptr msg )
{
//qDebug() << Q_FUNC_INFO << thread() << QThread::currentThread();
Q_ASSERT( QThread::currentThread() == thread() );
Q_ASSERT( this->isRunning() );
// Q_ASSERT( this->isRunning() );
if( m_sock.isNull() || !m_sock->isOpen() || !m_sock->isWritable() )
if ( m_sock.isNull() || !m_sock->isOpen() || !m_sock->isWritable() )
{
qDebug() << "***** Socket problem, whilst in sendMsg(). Cleaning up. *****";
shutdown( false );
return;
}
if( ! msg->write( m_sock.data() ) )
if ( !msg->write( m_sock.data() ) )
{
//qDebug() << "Error writing to socket in sendMsg() *************";
shutdown( false );

View File

@@ -19,17 +19,17 @@
#ifndef CONNECTION_H
#define CONNECTION_H
#include <QSharedPointer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QVariant>
#include <QVariantMap>
#include <QString>
#include <QDataStream>
#include <QtEndian>
#include <QTimer>
#include <QTime>
#include <QPointer>
#include <QtCore/QSharedPointer>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QHostAddress>
#include <QtCore/QVariant>
#include <QtCore/QVariantMap>
#include <QtCore/QString>
#include <QtCore/QDataStream>
#include <QtCore/QtEndian>
#include <QtCore/QTimer>
#include <QtCore/QTime>
#include <QtCore/QPointer>
#include <qjson/parser.h>
#include <qjson/serializer.h>
@@ -87,6 +87,8 @@ public:
void setMsgProcessorModeOut( quint32 m ) { m_msgprocessor_out.setMode( m ); }
void setMsgProcessorModeIn( quint32 m ) { m_msgprocessor_in.setMode( m ); }
const QHostAddress peerIpAddress() const { return m_peerIpAddress; }
signals:
void ready();
void failed();
@@ -128,6 +130,7 @@ protected:
bool m_outbound, m_ready, m_onceonly;
msg_ptr m_firstmsg;
QString m_name;
QHostAddress m_peerIpAddress;
private:
void handleReadMsg();

View File

@@ -33,7 +33,7 @@
using namespace Tomahawk;
ControlConnection::ControlConnection( Servent* parent )
ControlConnection::ControlConnection( Servent* parent, const QHostAddress &ha )
: Connection( parent )
, m_dbsyncconn( 0 )
, m_registered( false )
@@ -47,6 +47,38 @@ ControlConnection::ControlConnection( Servent* parent )
this->setMsgProcessorModeIn( MsgProcessor::UNCOMPRESS_ALL | MsgProcessor::PARSE_JSON );
this->setMsgProcessorModeOut( MsgProcessor::COMPRESS_IF_LARGE );
m_peerIpAddress = ha;
}
ControlConnection::ControlConnection( Servent* parent, const QString &ha )
: Connection( parent )
, m_dbsyncconn( 0 )
, m_registered( false )
, m_pingtimer( 0 )
{
qDebug() << "CTOR controlconnection";
setId("ControlConnection()");
// auto delete when connection closes:
connect( this, SIGNAL( finished() ), SLOT( deleteLater() ) );
this->setMsgProcessorModeIn( MsgProcessor::UNCOMPRESS_ALL | MsgProcessor::PARSE_JSON );
this->setMsgProcessorModeOut( MsgProcessor::COMPRESS_IF_LARGE );
if ( !ha.isEmpty() )
{
QHostAddress qha( ha );
if ( !qha.isNull() )
m_peerIpAddress = qha;
else
{
QHostInfo qhi = QHostInfo::fromName( ha );
if ( !qhi.addresses().isEmpty() )
m_peerIpAddress = qhi.addresses().first();
}
}
}
@@ -72,7 +104,7 @@ ControlConnection::source() const
Connection*
ControlConnection::clone()
{
ControlConnection* clone = new ControlConnection( servent() );
ControlConnection* clone = new ControlConnection( servent(), m_peerIpAddress.toString() );
clone->setOnceOnly( onceOnly() );
clone->setName( name() );
return clone;
@@ -102,6 +134,8 @@ ControlConnection::setup()
else
friendlyName = name();
tDebug() << "Detected name:" << name() << friendlyName << m_sock->peerAddress();
// setup source and remote collection for this peer
m_source = SourceList::instance()->get( id(), friendlyName );
m_source->setControlConnection( this );

View File

@@ -39,7 +39,8 @@ class DLLEXPORT ControlConnection : public Connection
Q_OBJECT
public:
explicit ControlConnection( Servent* parent = 0 );
explicit ControlConnection( Servent* parent = 0, const QHostAddress &ha = QHostAddress() );
explicit ControlConnection( Servent* parent = 0, const QString &ha = QString() );
~ControlConnection();
Connection* clone();

View File

@@ -39,10 +39,6 @@
#include "sourcelist.h"
#include "utils/logger.h"
// close the dbsync connection after this much inactivity.
// it's automatically reestablished as needed.
#define IDLE_TIMEOUT 300000
using namespace Tomahawk;
@@ -52,11 +48,11 @@ DBSyncConnection::DBSyncConnection( Servent* s, const source_ptr& src )
, m_state( UNKNOWN )
{
qDebug() << Q_FUNC_INFO << src->id() << thread();
connect( this, SIGNAL( stateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ),
m_source.data(), SLOT( onStateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ) );
m_timer.setInterval( IDLE_TIMEOUT );
connect( &m_timer, SIGNAL( timeout() ), SLOT( idleTimeout() ) );
connect( m_source.data(), SIGNAL( commandsFinished() ),
this, SLOT( lastOpApplied() ) );
this->setMsgProcessorModeIn( MsgProcessor::PARSE_JSON | MsgProcessor::UNCOMPRESS_ALL );
@@ -67,19 +63,11 @@ DBSyncConnection::DBSyncConnection( Servent* s, const source_ptr& src )
DBSyncConnection::~DBSyncConnection()
{
qDebug() << "DTOR" << Q_FUNC_INFO;
tDebug() << "DTOR" << Q_FUNC_INFO << m_source->id() << m_source->friendlyName();
m_state = SHUTDOWN;
}
void
DBSyncConnection::idleTimeout()
{
qDebug() << Q_FUNC_INFO;
shutdown( true );
}
void
DBSyncConnection::changeState( State newstate )
{
@@ -96,7 +84,6 @@ DBSyncConnection::changeState( State newstate )
void
DBSyncConnection::setup()
{
// qDebug() << Q_FUNC_INFO;
setId( QString( "DBSyncConnection/%1" ).arg( socket()->peerAddress().toString() ) );
check();
}
@@ -105,23 +92,19 @@ DBSyncConnection::setup()
void
DBSyncConnection::trigger()
{
// qDebug() << Q_FUNC_INFO;
// if we're still setting up the connection, do nothing - we sync on first connect anyway:
if ( !isRunning() )
return;
QMetaObject::invokeMethod( this, "sendMsg", Qt::QueuedConnection,
Q_ARG( msg_ptr,
Msg::factory( "{\"method\":\"trigger\"}", Msg::JSON ) )
);
Q_ARG( msg_ptr, Msg::factory( "{\"method\":\"trigger\"}", Msg::JSON ) ) );
}
void
DBSyncConnection::check()
{
qDebug() << Q_FUNC_INFO << m_source->id();
qDebug() << Q_FUNC_INFO << this << m_source->id();
if ( m_state != UNKNOWN && m_state != SYNCED )
{
qDebug() << "Syncing in progress already.";
@@ -133,10 +116,7 @@ DBSyncConnection::check()
return;
}
Q_ASSERT( m_cmds.isEmpty() );
m_uscache.clear();
m_us.clear();
changeState( CHECKING );
// load last-modified etc data for our collection and theirs from our DB:
@@ -154,9 +134,6 @@ DBSyncConnection::check()
{
fetchOpsData( m_source->lastCmdGuid() );
}
// restarts idle countdown
m_timer.start();
}
@@ -165,7 +142,7 @@ DBSyncConnection::check()
void
DBSyncConnection::gotUs( const QVariantMap& m )
{
m_us = m;
Q_UNUSED( m )
if ( !m_uscache.empty() )
sendOps();
}
@@ -231,19 +208,16 @@ DBSyncConnection::handleMsg( msg_ptr msg )
if ( msg->is( Msg::DBOP ) )
{
DatabaseCommand* cmd = DatabaseCommand::factory( m, m_source );
if ( !cmd )
if ( cmd )
{
qDebug() << "UNKNOWN DBOP CMD";
return;
}
QSharedPointer<DatabaseCommand> cmdsp = QSharedPointer<DatabaseCommand>(cmd);
m_cmds << cmdsp;
m_source->addCommand( cmdsp );
}
if ( !msg->is( Msg::FRAGMENT ) ) // last msg in this batch
{
changeState( SAVING ); // just DB work left to complete
executeCommands();
m_source->executeCommands();
}
return;
}
@@ -251,7 +225,6 @@ DBSyncConnection::handleMsg( msg_ptr msg )
if ( m.value( "method" ).toString() == "fetchops" )
{
m_uscache = m;
if ( !m_us.empty() )
sendOps();
return;
}
@@ -269,23 +242,11 @@ DBSyncConnection::handleMsg( msg_ptr msg )
void
DBSyncConnection::executeCommands()
DBSyncConnection::lastOpApplied()
{
if ( !m_cmds.isEmpty() )
{
QSharedPointer<DatabaseCommand> cmd = m_cmds.takeFirst();
if ( !cmd->singletonCmd() )
m_source->setLastCmdGuid( cmd->guid() );
connect( cmd.data(), SIGNAL( finished() ), SLOT( executeCommands() ) );
Database::instance()->enqueue( cmd );
}
else
{
changeState( SYNCED );
// check again, until peer responds we have no new ops to process
check();
}
}
@@ -314,6 +275,7 @@ DBSyncConnection::sendOpsData( QString sinceguid, QString lastguid, QList< dbop_
m_lastSentOp = lastguid;
if ( ops.length() == 0 )
{
tLog( LOGVERBOSE ) << "Sending ok" << m_source->id() << m_source->friendlyName();
sendMsg( Msg::factory( "ok", Msg::DBOP ) );
return;
}

Some files were not shown because too many files have changed in this diff Show More