diff --git a/admin/mac/build-release-osx.sh b/admin/mac/build-release-osx.sh index 66cf4d648..5413399dc 100755 --- a/admin/mac/build-release-osx.sh +++ b/admin/mac/build-release-osx.sh @@ -45,6 +45,9 @@ VERSION=$1 header "Creating DMG" cd .. + header "Signing bundle" + codesign -s "Developer ID Application: Leonardo Franchi" -f -v ./Tomahawk.app + $ROOT/../admin/mac/create-dmg.sh Tomahawk.app mv Tomahawk.dmg Tomahawk-$VERSION.dmg diff --git a/data/icons/tomahawk-icon-128x128-grayscale.png b/data/icons/tomahawk-icon-128x128-grayscale.png index f9daadb33..b7368f2bc 100644 Binary files a/data/icons/tomahawk-icon-128x128-grayscale.png and b/data/icons/tomahawk-icon-128x128-grayscale.png differ diff --git a/data/icons/tomahawk-icon-128x128.png b/data/icons/tomahawk-icon-128x128.png index 4701db23a..5bbe89c0f 100644 Binary files a/data/icons/tomahawk-icon-128x128.png and b/data/icons/tomahawk-icon-128x128.png differ diff --git a/data/icons/tomahawk-icon-16x16.png b/data/icons/tomahawk-icon-16x16.png index 8d2cd8589..a08e02e80 100644 Binary files a/data/icons/tomahawk-icon-16x16.png and b/data/icons/tomahawk-icon-16x16.png differ diff --git a/data/icons/tomahawk-icon-256x256.png b/data/icons/tomahawk-icon-256x256.png index 559067acd..bdc9c0ef0 100644 Binary files a/data/icons/tomahawk-icon-256x256.png and b/data/icons/tomahawk-icon-256x256.png differ diff --git a/data/icons/tomahawk-icon-32x32.png b/data/icons/tomahawk-icon-32x32.png index 952151ba2..be06f5166 100644 Binary files a/data/icons/tomahawk-icon-32x32.png and b/data/icons/tomahawk-icon-32x32.png differ diff --git a/data/icons/tomahawk-icon-512x512.png b/data/icons/tomahawk-icon-512x512.png index 14db6cbc3..b7524186c 100644 Binary files a/data/icons/tomahawk-icon-512x512.png and b/data/icons/tomahawk-icon-512x512.png differ diff --git a/data/icons/tomahawk-icon-64x64.png b/data/icons/tomahawk-icon-64x64.png index e27712df7..b64010805 100644 Binary files a/data/icons/tomahawk-icon-64x64.png and b/data/icons/tomahawk-icon-64x64.png differ diff --git a/data/icons/tomahawk-icon.svg b/data/icons/tomahawk-icon.svg index 05b80614d..2570b4bef 100644 --- a/data/icons/tomahawk-icon.svg +++ b/data/icons/tomahawk-icon.svg @@ -1,80 +1,101 @@ - - - -image/svg+xml - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/images/view-toggle-icon-grid-active.png b/data/images/view-toggle-icon-grid-active.png new file mode 100644 index 000000000..2c475716f Binary files /dev/null and b/data/images/view-toggle-icon-grid-active.png differ diff --git a/data/images/view-toggle-icon-grid-inactive.png b/data/images/view-toggle-icon-grid-inactive.png new file mode 100644 index 000000000..0ceb65da5 Binary files /dev/null and b/data/images/view-toggle-icon-grid-inactive.png differ diff --git a/data/stylesheets/topbar-radiobuttons.css b/data/stylesheets/topbar-radiobuttons.css index 6ee4719d6..402d3c1cb 100644 --- a/data/stylesheets/topbar-radiobuttons.css +++ b/data/stylesheets/topbar-radiobuttons.css @@ -10,7 +10,7 @@ QRadioButton { padding:0; background-repeat: none; /*width:0; height:0;*/ -} +} QRadioButton::indicator { width: 29px; @@ -18,15 +18,15 @@ QRadioButton::indicator { } QRadioButton::indicator::unchecked { - background-image: url(:/data/images/view-toggle-inactive-right.png); + background-image: url(:/data/images/view-toggle-inactive-centre.png); image: url(:/data/images/view-toggle-icon-list-inactive.png); } QRadioButton::indicator::checked { - background-image: url(:/data/images/view-toggle-active-right.png); + background-image: url(:/data/images/view-toggle-active-centre.png); image: url(:/data/images/view-toggle-icon-list-active.png); } QRadioButton::indicator::pressed { - background-image: url(:/data/images/view-toggle-pressed-right.png); + background-image: url(:/data/images/view-toggle-pressed-centre.png); image: url(:/data/images/view-toggle-icon-list-active.png); } QRadioButton#radioNormal::indicator::unchecked { @@ -43,13 +43,13 @@ QRadioButton#radioNormal::indicator::pressed { } QRadioButton#radioCloud::indicator::unchecked { background-image: url(:/data/images/view-toggle-inactive-right.png); - image: url(:/data/images/view-toggle-icon-cloud-inactive.png); + image: url(:/data/images/view-toggle-icon-grid-inactive.png); } QRadioButton#radioCloud::indicator::checked { background-image: url(:/data/images/view-toggle-active-right.png); - image: url(:/data/images/view-toggle-icon-cloud-active.png); + image: url(:/data/images/view-toggle-icon-grid-active.png); } QRadioButton#radioCloud::indicator::pressed { background-image: url(:/data/images/view-toggle-pressed-right.png); - image: url(:/data/images/view-toggle-icon-cloud-active.png); + image: url(:/data/images/view-toggle-icon-grid-active.png); } diff --git a/lang/tomahawk_ar.ts b/lang/tomahawk_ar.ts index 41f6e1ebd..548d1bd66 100644 --- a/lang/tomahawk_ar.ts +++ b/lang/tomahawk_ar.ts @@ -474,11 +474,19 @@ connect and stream from you? &Copy to Clipboard - + &نسخ إلى الحافظة Open &Log-file + فتح &ملف السجل + + + + FlexibleHeader + + + Filter... @@ -557,7 +565,7 @@ connect and stream from you? %1 is listening along with you! - + %1 يستمع معك! @@ -617,12 +625,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! نعتذر، لم نستطيع إيجاد اي من الأغاني المحبوبة! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks الأغاني المحبوبة @@ -735,7 +763,7 @@ connect and stream from you? تقدم - + - Properties - خصائص @@ -845,6 +873,31 @@ connect and stream from you? إسم + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1369,7 +1422,7 @@ connect and stream from you? - + Latest Additions أحدث الإضافات @@ -1384,37 +1437,37 @@ connect and stream from you? سوبر كولكشن - + Latest additions to your collection آخر إضافات على مجموعتك - + Latest additions to %1's collection آخر إضافات على مجموعة %1 - + Sorry, we could not find any recent additions! نعتذر، لم نستطيع إيجاد إضافة جديدة! - + Recently Played Tracks الأغاني التي إستمعت إليها مؤخرا - + Your recently played tracks الأغاني التي إستمعت إليها مؤخرا - + %1's recently played tracks الأغاني التي سمعها مؤخرا %1 - + Sorry, we could not find any recent plays! نعتذر، لم نستطيع إيجاد أغاني مسموعة مؤخرا! @@ -1492,77 +1545,72 @@ connect and stream from you? SourcesModel - + Group فئة - + Collection مجموعة - + Playlist قائمة الأغاني - + Automatic Playlist قائمة أغاني أوتوماتيكية - + Station إذاعة - + Browse تصفح - + Search History تاريخ البحث - + My Music موسيقتي الخاصة - + SuperCollection سوبر كولكشن - - Top Loved Tracks - الأغاني المحبوبة الأكثر شهرة - - - + Dashboard لوحة القيادة - + Recently Played تم الاستماع لها مؤخرا - + Charts الرسوم البيانية - + New Releases جديد الاصدارات - + Friends الأصدقاء @@ -1623,12 +1671,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? أحذف في سبوتيفي (Spotify)؟ - + Would you like to delete the corresponding Spotify playlist as well? هل ترغب في حذف قائمة التشغيل المطابقة على سبوتيفي (Spotify)؟ @@ -1935,17 +1983,37 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify مزامنة مع سبوتيفي (Spotify) - + Re-enable syncing with Spotify إعادة تمكين المزامنة مع سبوتيفي (Spotify) - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify أوقف المزامنة مع سبوتيفي (Spotify) @@ -1953,28 +2021,28 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... جاري تسجيل الدخول... - + Failed: %1 فشل: %1 - - - Logged in as %1 - - - Log Out - + Logged in as %1 + مسجل تحت اسم %1 - - + + Log Out + تسجيل الخروج + + + + Log In تسجيل الدخول @@ -1982,7 +2050,7 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium إسمع موسيقى و زامن قوائم تشغيلك مع سبوتيفي بريميوم (Spotify Premium) @@ -2203,7 +2271,7 @@ You may wish to try re-authenticating. Properties... - + خصائص... @@ -2221,39 +2289,6 @@ You may wish to try re-authenticating. &أظهر صفحة الفنان - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - الأغاني المحبوبة الأكثر شهرة - - - - Your loved tracks - الأغاني التي أحببتها - - - - %1's loved tracks - الأغاني المحبوبة ل%1 - - - - The most loved tracks from all your friends - الأغاني المحبوبة كثيرا بين أصدقائك - - - - All of your loved tracks - جميع الأغاني التي أحببتها - - - - All of %1's loved tracks - جميع الأغاني المحبوبة ل%1 - - Tomahawk::DropJobNotifier @@ -2995,7 +3030,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! مشكلة في جلب معلومات "Spotify" من الشبكة! @@ -3011,7 +3046,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection مجموعتي الخاصة @@ -3623,35 +3658,40 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. بعد إجراء مسح مجموعة أغانيك الخاصة ستجد أغانيك هنا. - + This collection is empty. هذه المجموعة فارغة. - + SuperCollection سوبر كولكشن - + Combined libraries of all your online friends مكتبات مجمعة لكل اصحابك المتصلين - + Recently Played Tracks الأغاني التي إستمعت إليها مؤخرا - + Recently played tracks from all your friends جميع الأغاني التي استمع إليها أصدقائك مؤخرا + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_bg.ts b/lang/tomahawk_bg.ts index 0ae5c430d..41646624d 100644 --- a/lang/tomahawk_bg.ts +++ b/lang/tomahawk_bg.ts @@ -484,6 +484,14 @@ Tomahaw създаде доклад относно това и изпращай + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -619,12 +627,32 @@ Tomahaw създаде доклад относно това и изпращай LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks @@ -737,7 +765,7 @@ Tomahaw създаде доклад относно това и изпращай - + - Properties @@ -847,6 +875,31 @@ Tomahaw създаде доклад относно това и изпращай Име + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1369,7 +1422,7 @@ Tomahaw създаде доклад относно това и изпращай - + Latest Additions Последно добавени @@ -1385,37 +1438,37 @@ Tomahaw създаде доклад относно това и изпращай /Сборен излед от локалните и наличните в колекциите на приятелите ти/ - + Latest additions to your collection Последно добавени към колекцията - + Latest additions to %1's collection Последно добавени в колекцията на %1 - + Sorry, we could not find any recent additions! Съжалявам, но не откривам нито една ново-добавена позиция! - + Recently Played Tracks Наскоро изпълнени песни - + Your recently played tracks Наскоро изпълнени песни от теб - + %1's recently played tracks Наскоро изпълнените песни от %1 - + Sorry, we could not find any recent plays! Съжалявам, но не откривам нито една наскоро изпълнена песен! @@ -1493,78 +1546,73 @@ Tomahaw създаде доклад относно това и изпращай SourcesModel - + Group Гпупирай - + Collection Колекция - + Playlist Списък за изпълнение - + Automatic Playlist Автоматичен списък - + Station Станция - + Browse Разгледай - + Search History Търси в историята - + My Music Моята музика - + SuperCollection Супер колекция /Сборен излед от локалните и наличните в колекциите на приятелите ти/ - - Top Loved Tracks - Най-харесвани песни - - - + Dashboard Табло - + Recently Played Наскоро изпълнени песни - + Charts Класации - + New Releases Нови албуми - + Friends Приятели @@ -1625,12 +1673,12 @@ Tomahaw създаде доклад относно това и изпращай SpotifyPlaylistUpdater - + Delete in Spotify? Изтривам и в Spotify? - + Would you like to delete the corresponding Spotify playlist as well? Желаеш ли да изтриеш и съответните Spotify списъци? @@ -1941,17 +1989,37 @@ Tomahaw създаде доклад относно това и изпращай Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify Синхронизирай със Spotify - + Re-enable syncing with Spotify Включи отново синхронизирането със Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify Спри синхронизацията със Spotify @@ -1959,28 +2027,28 @@ Tomahaw създаде доклад относно това и изпращай Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... Влизам... - + Failed: %1 Неуспех: %1 - + Logged in as %1 - + Log Out - - + + Log In Влез @@ -1988,7 +2056,7 @@ Tomahaw създаде доклад относно това и изпращай Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium Слушай музика и синхронизирай твоите списъци със Spotify Premium @@ -2229,39 +2297,6 @@ You may wish to try re-authenticating. &Покажи страницата на артистът - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Най-харесвани песни - - - - Your loved tracks - Песните, които харесам. - - - - %1's loved tracks - Песните, каресвани от %1 - - - - The most loved tracks from all your friends - Най-харесваните песни от всички твои приятели. - - - - All of your loved tracks - Всички песни, които харесвам. - - - - All of %1's loved tracks - Всички песни, харесвани от %1 - - Tomahawk::DropJobNotifier @@ -3002,7 +3037,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! Грешка при извличане на информация от Spotify @@ -3018,7 +3053,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection Моята колекция @@ -3634,36 +3669,41 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. След като бъде сканирана колекцията ти, ще откриеш твоите песни точно тук. - + This collection is empty. Празна колекция. - + SuperCollection Супер колекция /Сборен излед от локалните и наличните в колекциите на приятелите ти/ - + Combined libraries of all your online friends Обща колекция с всичките ми приятели на линия - + Recently Played Tracks Наскоро изпълени песни - + Recently played tracks from all your friends Наскоро изпълнени песни от всичките ти приятели + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_ca.ts b/lang/tomahawk_ca.ts index 578d03edc..39bdc19ae 100644 --- a/lang/tomahawk_ca.ts +++ b/lang/tomahawk_ca.ts @@ -481,6 +481,14 @@ connect and stream from you? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -616,12 +624,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks @@ -734,7 +762,7 @@ connect and stream from you? - + - Properties @@ -844,6 +872,31 @@ connect and stream from you? Nom + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1367,7 +1420,7 @@ connect and stream from you? - + Latest Additions Darreres Novetats @@ -1382,37 +1435,37 @@ connect and stream from you? SuperCol·lecció - + Latest additions to your collection Darreres novetats a la vostra col·lecció - + Latest additions to %1's collection Darreres novetats a la col·lecció de %1 - + Sorry, we could not find any recent additions! - + Recently Played Tracks Cançons Escoltades Recentment - + Your recently played tracks Cançons Escoltades Recentment - + %1's recently played tracks Cançons Escoltades Recentment per %1 - + Sorry, we could not find any recent plays! @@ -1490,77 +1543,72 @@ connect and stream from you? SourcesModel - + Group Grup - + Collection Col·lecció - + Playlist Llista de Reproducció - + Automatic Playlist Llista de Reproducció Automàtica - + Station Emissora - + Browse Cerca - + Search History Historial de Cerca - + My Music La Meva Música - + SuperCollection SuperCol·lecció - - Top Loved Tracks - Top de Cançons Preferides - - - + Dashboard Presentació - + Recently Played Escoltades Recentment - + Charts Llistes - + New Releases Nous Llançaments - + Friends Amics @@ -1621,12 +1669,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? Voleu esborrar-ho de Spotify? - + Would you like to delete the corresponding Spotify playlist as well? Voleu esborrar les llistes de Spotify, també? @@ -1934,17 +1982,37 @@ i emissores de ràdio basades en el vostre gust musical. Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify Sincronitza amb Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify Atura la sincronització amb Spotify @@ -1952,28 +2020,28 @@ i emissores de ràdio basades en el vostre gust musical. Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... Iniciant sessió... - + Failed: %1 Error: %1 - + Logged in as %1 - + Log Out - - + + Log In Incia Sessió @@ -1981,7 +2049,7 @@ i emissores de ràdio basades en el vostre gust musical. Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium Reprodueix música i sincronitza les llistes de reproducció amb Spotify Premium @@ -2220,39 +2288,6 @@ Torneu a autenticar-vos. &Mostra la pàgina de l'artista - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Top de Cançons Preferides - - - - Your loved tracks - Les meves cançons preferides - - - - %1's loved tracks - Les cançons preferides de %1 - - - - The most loved tracks from all your friends - Les cançons preferides de tots els amics - - - - All of your loved tracks - Totes les meves cançons preferides - - - - All of %1's loved tracks - Totes les cançons preferides de %1 - - Tomahawk::DropJobNotifier @@ -2994,7 +3029,7 @@ Intenteu ajustar els filtres per reproduir noves cançons. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! Error en cercar la informació de Spotify a través de la xarxa! @@ -3010,7 +3045,7 @@ Intenteu ajustar els filtres per reproduir noves cançons. TomahawkApp - + My Collection La meva Col·lecció @@ -3622,35 +3657,40 @@ Podeu reenviar un missatge de sincronisme en qualsevol moment simplement enviant ViewManager - + After you have scanned your music collection you will find your tracks right here. - + This collection is empty. - + SuperCollection SuperCol·lecció - + Combined libraries of all your online friends Biblioteques combinades de tots els amis en línia - + Recently Played Tracks Cançons Escoltades Recentment - + Recently played tracks from all your friends Cançons escoltades recentment pels amics + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_de.ts b/lang/tomahawk_de.ts index 5bbf3920d..eddf0e796 100644 --- a/lang/tomahawk_de.ts +++ b/lang/tomahawk_de.ts @@ -482,6 +482,14 @@ erlauben sich mit dir zu verbinden? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -617,12 +625,32 @@ erlauben sich mit dir zu verbinden? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! Sorry, wir konnten keine Lieblingslieder finden! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks Lieblingslieder @@ -735,7 +763,7 @@ erlauben sich mit dir zu verbinden? Vorwärts - + - Properties - Eigenschaften @@ -845,6 +873,31 @@ erlauben sich mit dir zu verbinden? Name + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1368,7 +1421,7 @@ erlauben sich mit dir zu verbinden? - + Latest Additions Kürzlich hinzugekommen @@ -1383,37 +1436,37 @@ erlauben sich mit dir zu verbinden? Supersammlung - + Latest additions to your collection Neueste Lieder in deiner Sammlung - + Latest additions to %1's collection Neueste Lieder in %1's Sammlung - + Sorry, we could not find any recent additions! Sorry, wir konnten keine Lieder finden die kürzlich hinzugefügt wurden! - + Recently Played Tracks Zuletzt gehörte Lieder - + Your recently played tracks Deine zuletzt gehörten Lieder - + %1's recently played tracks %1's zuletzt gehörte Lieder - + Sorry, we could not find any recent plays! Sorry, wir konnten keine kürzlich gespielten Lieder finden! @@ -1491,77 +1544,72 @@ erlauben sich mit dir zu verbinden? SourcesModel - + Group Gruppe - + Collection Sammlung - + Playlist Playlist - + Automatic Playlist Automatische Playlist - + Station Station - + Browse Stöbern - + Search History Suchverlauf - + My Music Meine Musik - + SuperCollection Supersammlung - - Top Loved Tracks - Gemeinsame Lieblingslieder - - - + Dashboard Dashboard - + Recently Played Kürzlich gehörte Lieder - + Charts Charts - + New Releases Neuerscheinungen - + Friends Freunde @@ -1622,12 +1670,12 @@ erlauben sich mit dir zu verbinden? SpotifyPlaylistUpdater - + Delete in Spotify? Auf Spotify löschen - + Would you like to delete the corresponding Spotify playlist as well? Möchtest du die entsprechende Spotify Playlist auch löschen? @@ -1932,17 +1980,37 @@ erlauben sich mit dir zu verbinden? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify Mit Spotify synchronisieren - + Re-enable syncing with Spotify Synchronisierung mit Spotify re-aktivieren - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify Synchronisation beenden @@ -1950,28 +2018,28 @@ erlauben sich mit dir zu verbinden? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... Anmelden... - + Failed: %1 Fehler: %1 - + Logged in as %1 - + Log Out - - + + Log In Anmelden @@ -1979,7 +2047,7 @@ erlauben sich mit dir zu verbinden? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium Musik abspielen und Playlisten synchronisieren mit Spotify Premium @@ -2216,39 +2284,6 @@ You may wish to try re-authenticating. &Gehe zur Künstler Seite - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Meist geliebte Lieder - - - - Your loved tracks - Deine Lieblingslieder - - - - %1's loved tracks - Die Lieblingslieder von %1 - - - - The most loved tracks from all your friends - Die Lieblingslieder deiner Freunde - - - - All of your loved tracks - All deine Lieblingslieder - - - - All of %1's loved tracks - Alle Lieblingslieder von %1 - - Tomahawk::DropJobNotifier @@ -2990,7 +3025,7 @@ Versuch die Filter anzupassen für neue Lieder. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! Konnte Spotify-Daten nicht laden! @@ -3006,7 +3041,7 @@ Versuch die Filter anzupassen für neue Lieder. TomahawkApp - + My Collection Meine Sammlung @@ -3613,35 +3648,40 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. Nachdem du deine Musik Sammlung gescannt hast, findest du all deine Lieder genau hier. - + This collection is empty. Diese Sammlung ist leer. - + SuperCollection SuperCollection - + Combined libraries of all your online friends Kombinierte Sammlung all deiner Freunde - + Recently Played Tracks Zuletzt gehörte Lieder - + Recently played tracks from all your friends Zuletzt gehörte Lieder all deiner Freunde + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_en.ts b/lang/tomahawk_en.ts index 52dafea70..730a84a58 100644 --- a/lang/tomahawk_en.ts +++ b/lang/tomahawk_en.ts @@ -482,6 +482,14 @@ connect and stream from you? Open &Log-file + + FlexibleHeader + + + Filter... + Filter... + + GlobalSearchWidget @@ -617,12 +625,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + Top Loved Tracks + + + Sorry, we could not find any loved tracks! Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + The most loved tracks from all your friends + + + + All of your loved tracks + All of your loved tracks + + + + All of %1's loved tracks + All of %1's loved tracks + + + Loved Tracks Loved Tracks @@ -735,7 +763,7 @@ connect and stream from you? Forward - + - Properties - Properties @@ -845,6 +873,31 @@ connect and stream from you? Name + + PlaylistHeader + + + InfoBar + InfoBar + + + + Caption + Caption + + + + Description + Description + + + + + + RadioButton + RadioButton + + PlaylistItemDelegate @@ -1368,7 +1421,7 @@ connect and stream from you? - + Latest Additions Latest Additions @@ -1383,37 +1436,37 @@ connect and stream from you? SuperCollection - + Latest additions to your collection Latest additions to your collection - + Latest additions to %1's collection Latest additions to %1's collection - + Sorry, we could not find any recent additions! Sorry, we could not find any recent additions! - + Recently Played Tracks Recently Played Tracks - + Your recently played tracks Your recently played tracks - + %1's recently played tracks %1's recently played tracks - + Sorry, we could not find any recent plays! Sorry, we could not find any recent plays! @@ -1491,77 +1544,72 @@ connect and stream from you? SourcesModel - + Group Group - + Collection Collection - + Playlist Playlist - + Automatic Playlist Automatic Playlist - + Station Station - + Browse Browse - + Search History Search History - + My Music My Music - + SuperCollection SuperCollection - - Top Loved Tracks - Top Loved Tracks - - - + Dashboard Dashboard - + Recently Played Recently Played - + Charts Charts - + New Releases New Releases - + Friends Friends @@ -1622,12 +1670,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? Delete in Spotify? - + Would you like to delete the corresponding Spotify playlist as well? Would you like to delete the corresponding Spotify playlist as well? @@ -1935,17 +1983,37 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify Sync with Spotify - + Re-enable syncing with Spotify Re-enable syncing with Spotify - + + Create local copy + Create local copy + + + + Subscribe to playlist changes + Subscribe to playlist changes + + + + Re-enable playlist subscription + Re-enable playlist subscription + + + + Stop subscribing to changes + Stop subscribing to changes + + + Stop syncing with Spotify Stop syncing with Spotify @@ -1953,28 +2021,28 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... Logging in... - + Failed: %1 Failed: %1 - + Logged in as %1 Logged in as %1 - + Log Out Log Out - - + + Log In Log In @@ -1982,7 +2050,7 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium Play music from and sync your playlists with Spotify Premium @@ -2221,39 +2289,6 @@ You may wish to try re-authenticating. &Show Artist Page - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Top Loved Tracks - - - - Your loved tracks - Your loved tracks - - - - %1's loved tracks - %1's loved tracks - - - - The most loved tracks from all your friends - The most loved tracks from all your friends - - - - All of your loved tracks - All of your loved tracks - - - - All of %1's loved tracks - All of %1's loved tracks - - Tomahawk::DropJobNotifier @@ -2995,7 +3030,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! Error fetching Spotify information from the network! @@ -3011,7 +3046,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection My Collection @@ -3623,35 +3658,40 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. After you have scanned your music collection you will find your tracks right here. - + This collection is empty. This collection is empty. - + SuperCollection SuperCollection - + Combined libraries of all your online friends Combined libraries of all your online friends - + Recently Played Tracks Recently Played Tracks - + Recently played tracks from all your friends Recently played tracks from all your friends + + + Sorry, we could not find any recent plays! + Sorry, we could not find any recent plays! + WelcomeWidget diff --git a/lang/tomahawk_es.ts b/lang/tomahawk_es.ts index ad5dbfa8a..1e15f3b45 100644 --- a/lang/tomahawk_es.ts +++ b/lang/tomahawk_es.ts @@ -481,6 +481,14 @@ connect and stream from you? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -616,12 +624,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks @@ -734,7 +762,7 @@ connect and stream from you? - + - Properties @@ -844,6 +872,31 @@ connect and stream from you? + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1366,7 +1419,7 @@ connect and stream from you? - + Latest Additions Añadidos recientemente @@ -1381,37 +1434,37 @@ connect and stream from you? SuperColección - + Latest additions to your collection Últimas novedades en mi colección - + Latest additions to %1's collection Últimas novedadoes en la colección de %1 - + Sorry, we could not find any recent additions! - + Recently Played Tracks Temas Escuchados Recientemente - + Your recently played tracks Mis canciones escuchadas recientemente - + %1's recently played tracks Las canciones escuchadas recientemente por %1 - + Sorry, we could not find any recent plays! @@ -1489,77 +1542,72 @@ connect and stream from you? SourcesModel - + Group Grupo - + Collection Colección - + Playlist Lista de reproducción - + Automatic Playlist Lista de reproducción automática - + Station Estación - + Browse Buscar - + Search History Historial de Búsqueda - + My Music Mi Musica - + SuperCollection SuperColección - - Top Loved Tracks - Pistas favoritas - - - + Dashboard Panel de inicio - + Recently Played Reproducido recientemente - + Charts Listas - + New Releases Últimas novedades - + Friends Amigos @@ -1620,12 +1668,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? ¿Borrar en Spotify? - + Would you like to delete the corresponding Spotify playlist as well? Quieres eliminar la lista de Spotify correspondiente, también? @@ -1933,17 +1981,37 @@ y estaciones basadas en sus gustos personales. Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify Sincronizar con Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify Dejar de sincronizar con Spotify @@ -1951,28 +2019,28 @@ y estaciones basadas en sus gustos personales. Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... Inciando sesión... - + Failed: %1 Fallo: %1 - + Logged in as %1 - + Log Out - - + + Log In Iniciar Sesión @@ -1980,7 +2048,7 @@ y estaciones basadas en sus gustos personales. Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium Reproduce música de Spotofy Premium y sincroniza las listas de reprodución @@ -2219,39 +2287,6 @@ Hay que volverse a autenticar. - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Pistas favoritas - - - - Your loved tracks - Tus pistas favoritas - - - - %1's loved tracks - Pistas favoritas de %1 - - - - The most loved tracks from all your friends - Las pistas favoritas de tus amigos - - - - All of your loved tracks - Todas tus pistas favoritas - - - - All of %1's loved tracks - Todas las pistas favoritas de %1 - - Tomahawk::DropJobNotifier @@ -2993,7 +3028,7 @@ Intente ajustar los filtros para reproducir nuevas canciones. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! Error al buscar la información de Spotify en la red! @@ -3009,7 +3044,7 @@ Intente ajustar los filtros para reproducir nuevas canciones. TomahawkApp - + My Collection Mi colección @@ -3621,35 +3656,40 @@ Puede reenviar el mensaje de sincronización en cualquier momento simplemente en ViewManager - + After you have scanned your music collection you will find your tracks right here. - + This collection is empty. - + SuperCollection SuperColección - + Combined libraries of all your online friends Bibliotecas combinadas de todos tus amigos conectados - + Recently Played Tracks Temas Escuchados Recientemente - + Recently played tracks from all your friends Temas escuchados recientemente por mis amigos + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_fr.ts b/lang/tomahawk_fr.ts index b02fa3971..278c8e8e0 100644 --- a/lang/tomahawk_fr.ts +++ b/lang/tomahawk_fr.ts @@ -474,11 +474,19 @@ de se connecter et streamer de vous? &Copy to Clipboard - + &Copier à la planchette Open &Log-file + Ouvrir le &fichier journal + + + + FlexibleHeader + + + Filter... @@ -557,7 +565,7 @@ de se connecter et streamer de vous? %1 is listening along with you! - + %1 écoute avec vous! @@ -617,12 +625,32 @@ de se connecter et streamer de vous? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! Désolé, on a pas pu trouver aucune piste favoris! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks Titres favoris @@ -735,7 +763,7 @@ de se connecter et streamer de vous? Avancer - + - Properties - Propriétés @@ -845,6 +873,31 @@ de se connecter et streamer de vous? Nom + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1368,7 +1421,7 @@ de se connecter et streamer de vous? - + Latest Additions Derniers ajouts @@ -1383,37 +1436,37 @@ de se connecter et streamer de vous? SuperCollection - + Latest additions to your collection Derniers ajouts à votre collection - + Latest additions to %1's collection Derniers ajouts à la collection de %1 - + Sorry, we could not find any recent additions! Désolé, on a pas pu trouver des dernier ajouts! - + Recently Played Tracks Derniers titres joués - + Your recently played tracks Les derniers titres que vous avez joués - + %1's recently played tracks Derniers titres joués par %1 - + Sorry, we could not find any recent plays! Désolé, on a pas pu trouver aucune piste récement joués! @@ -1491,77 +1544,72 @@ de se connecter et streamer de vous? SourcesModel - + Group Groupe - + Collection Collection - + Playlist Liste de lecture - + Automatic Playlist Liste de lecture automatique - + Station Station - + Browse Parcourir - + Search History Chercher dans l'historique - + My Music Ma Musique - + SuperCollection SuperCollection - - Top Loved Tracks - Top des titres favoris - - - + Dashboard Tableau de bord - + Recently Played Joués récemment - + Charts Charts - + New Releases Nouveautés - + Friends Amis @@ -1622,12 +1670,12 @@ de se connecter et streamer de vous? SpotifyPlaylistUpdater - + Delete in Spotify? Supprimer dans Spotify ? - + Would you like to delete the corresponding Spotify playlist as well? Voulez-vous aussi supprimer la liste de lecture correspondante dans Spotify ? @@ -1935,17 +1983,37 @@ et des stations basées sur vos goûts. Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify Synchroniser avec Spotify - + Re-enable syncing with Spotify Réactiver la synchronisation avec Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify Stopper la synchronisation avec Spotify @@ -1953,28 +2021,28 @@ et des stations basées sur vos goûts. Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... Connexion... - + Failed: %1 Echec : %1 - - - Logged in as %1 - - - Log Out - + Logged in as %1 + Connecté sous %1 - - + + Log Out + Déconnectez-vous + + + + Log In Connexion @@ -1982,7 +2050,7 @@ et des stations basées sur vos goûts. Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium Jouer la musique et synchroniser vos listes avec Spotify Premium @@ -2203,7 +2271,7 @@ Essayez de vous authentifier de nouveau. Properties... - + Propriétés... @@ -2221,39 +2289,6 @@ Essayez de vous authentifier de nouveau. &Afficher la page artiste - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Top des titres favoris - - - - Your loved tracks - Vos titres favoris - - - - %1's loved tracks - Titres favoris de %1 - - - - The most loved tracks from all your friends - Les titres favoris de vos amis - - - - All of your loved tracks - Tous vos titres favoris - - - - All of %1's loved tracks - Tous les titres favoris de %1 - - Tomahawk::DropJobNotifier @@ -2995,7 +3030,7 @@ Essayez de changer les filtres pour avoir de nouveaux morceaux à jouer. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! Échec du chargement des informations Spotify depuis le réseau! @@ -3011,7 +3046,7 @@ Essayez de changer les filtres pour avoir de nouveaux morceaux à jouer. TomahawkApp - + My Collection Ma Collection @@ -3623,35 +3658,40 @@ Vous pouvez envoyer un message de synchronisation quand vous le souhaitez en env ViewManager - + After you have scanned your music collection you will find your tracks right here. Après avoir scanné votre collection musicale, vous trouverez tous vos titres ici. - + This collection is empty. La collection est vide. - + SuperCollection SuperCollection - + Combined libraries of all your online friends Collections regroupant toutes celles de vos amis en ligne - + Recently Played Tracks Derniers titres joués - + Recently played tracks from all your friends Derniers titres joués par vos amis + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_ja.ts b/lang/tomahawk_ja.ts index 664ad2fbf..e662672b0 100644 --- a/lang/tomahawk_ja.ts +++ b/lang/tomahawk_ja.ts @@ -15,7 +15,7 @@ connect and stream from you? Deny Access - + アクセスを拒否 @@ -36,7 +36,7 @@ connect and stream from you? Description goes here - + 内容 @@ -147,12 +147,12 @@ connect and stream from you? Sorry, we could not find any other albums for this artist! - + このアーティストのアルバムは他に見つかりませんでした。 Sorry, we could not find any tracks for this album! - + このアルバムの曲は見つかりませんでした。 @@ -194,7 +194,7 @@ connect and stream from you? Artist - + アーティスト @@ -204,7 +204,7 @@ connect and stream from you? Cover - + カバー @@ -214,12 +214,12 @@ connect and stream from you? Sorry, we could not find any related artists! - + 関連アーティストは見つかりませんでした。 Sorry, we could not find any top hits for this artist! - + このアーティストの大ヒット曲は見つかりませんでした。 @@ -257,7 +257,7 @@ connect and stream from you? Owner - + オーナー @@ -305,17 +305,17 @@ connect and stream from you? Sorry, Tomahawk couldn't find the track '%1' by %2 - + Tomahawkは%2の%1を見つかりませんでした。 Sorry, Tomahawk couldn't find the artist '%1' - + Tomahawkは'%1'と言うアーティストを見つかりませんでした。 Sorry, Tomahawk couldn't find the album '%1' by %2 - + Tomahawkは%2の%1を見つかりませんでした。 @@ -474,12 +474,20 @@ connect and stream from you? &Copy to Clipboard - + クリップボードにコピー Open &Log-file - + ログファイルを開く + + + + FlexibleHeader + + + Filter... + フィルター... @@ -557,7 +565,7 @@ connect and stream from you? %1 is listening along with you! - + %1さんが一緒に聴いています。 @@ -617,14 +625,34 @@ connect and stream from you? LovedTracksItem - - Sorry, we could not find any loved tracks! - + + Top Loved Tracks + 最もLove トラック - + + Sorry, we could not find any loved tracks! + Love トラックが見つかりませんでした。 + + + + The most loved tracks from all your friends + 友達の最もLove トラック + + + + All of your loved tracks + 自分のLove トラック + + + + All of %1's loved tracks + %1さんのLove トラック + + + Loved Tracks - + Love トラック @@ -632,112 +660,112 @@ connect and stream from you? Form - + フォーム Tags - + タグ Title: - + タイトル: Title... - + タイトル... Artist: - + アーティスト: Artist... - + アーティスト... Album: - + アルバム: Album... - + アルバム... Disc Number: - + ディスク番号: Duration: - + 時間: 00.00 - + 00.00 Year: - + 年: Bitrate: - + ビットレート: File - + ファイル File Name: - + ファイルネーム: File Name... - + ファイルネーム... File Size... - + ファイルサイズ... File size... - + ファイルサイズ... File Size: - + ファイルサイズ: Back - + 前へ Forward - + 次へ - + - Properties - + - 情報 @@ -845,6 +873,31 @@ connect and stream from you? 名前 + + PlaylistHeader + + + InfoBar + インフォメーションバー + + + + Caption + 表題 + + + + Description + 内容 + + + + + + RadioButton + RadioButton + + PlaylistItemDelegate @@ -909,12 +962,12 @@ connect and stream from you? Just a regular old playlist... Give it a name, drag in some tracks, and go! - + 普通のプレイリスト... 名付けて、曲をドラッグ・アンド・ドロップして行こう! Don't know exactly what you want? Give Tomahawk a few pointers and let it build a playlist for you! - + 欲しいのが分かりませんか?Tomahawkに何らかのヒントを与えたら、プレイリストの作成を任せて下さい! @@ -1202,12 +1255,12 @@ connect and stream from you? Delete all Access Control entries? - + 全てのアクセス制御のエントリーを削除しますか? Do you really want to delete all Access Control entries? You will be asked for a decision again for each peer that you connect to. - + 本当に全てのアクセス制御のエントリーを削除しますか?ピア接続に対して、改めて同意を求めます。 @@ -1220,7 +1273,7 @@ connect and stream from you? Popular New Albums From Your Friends - + 友達に人気のある新アルバム @@ -1230,7 +1283,7 @@ connect and stream from you? Most Played Tracks You Don't Have - + あなたの無い最も再生された曲 @@ -1238,47 +1291,47 @@ connect and stream from you? Form - + フォーム Facebook - + Facebook Twitter - + Twitter Cover - + カバー TextLabel - + TextLabel Tweet - + ツイート Listening to "%1" by %2. %3 - + %2の"%1"を聴いています。%3 Listening to "%1" by %2 on "%3". %4 - + %2の"%3"の"%1"を聴いています。%4 %1 characters left - + 残り%1文字 @@ -1301,29 +1354,29 @@ connect and stream from you? Local - + ローカル Top 10 - + トップ10 All available tracks - + 利用可能トラック Show - + 表示 Hide - + 隠す @@ -1331,32 +1384,32 @@ connect and stream from you? Recent Albums - + 最近のアルバム Latest Additions - + 最新追加した項目 Recently Played Tracks - + 最近再生したトラック New Additions - + 新しく追加した項目 My recent activity - + 自分の最近の活動 Recent activity from %1 - + %1の最近の活動 @@ -1368,14 +1421,14 @@ connect and stream from you? - + Latest Additions - + 最新追加した項目 Recently Played - + 最近聴いたトラック @@ -1383,39 +1436,39 @@ connect and stream from you? スーパーコレクション - + Latest additions to your collection - + コレクションの最新追加した項目 - + Latest additions to %1's collection - + %1のコレクションの最新追加した項目 - + Sorry, we could not find any recent additions! - + 最近追加した項目が見つかりませんでした。 - + Recently Played Tracks - + 最近再生したトラック - + Your recently played tracks - + あなたの最近再生したトラック - + %1's recently played tracks - + %1の最近再生したトラック - + Sorry, we could not find any recent plays! - + 最近の再生した項目が見つかりませんでした。 @@ -1428,54 +1481,54 @@ connect and stream from you? &Delete %1 - + %1を削除 Add to my Playlists - + プレイリストに追加する Add to my Automatic Playlists - + 自動プレイリストに追加する Add to my Stations - + ステーションに追加する &Export Playlist - + プレイリストを書き出し playlist - + プレイリスト automatic playlist - + 自動プレイリスト station - + ステーション Delete %1? playlist/station/... - + %1を削除しますか? Would you like to delete the %1 <b>"%2"</b>? e.g. Would you like to delete the playlist named Foobar? - + <b>"%2"</b>と言う%1を削除しますか? @@ -1485,85 +1538,80 @@ connect and stream from you? Playlists (*.xspf) - + プレイリスト (*.xspf) SourcesModel - + Group - + グループ - + Collection コレクション - + Playlist プレイリスト - + Automatic Playlist - + 自動プレイリスト - + Station ステーション - - - Browse - - - Search History - + Browse + 閲覧 - + + Search History + 履歴を検索 + + + My Music マイミュージック - + SuperCollection スーパーコレクション - - Top Loved Tracks - - - - + Dashboard ダッシュボード - + Recently Played 最近聴いたトラック - + Charts - + チャート - + New Releases - + ニューリリース - + Friends - + 友達 @@ -1576,12 +1624,12 @@ connect and stream from you? Configure your Spotify account - + Spotifyのアカウントを設定 Username or Facebook Email - + ユーザーネームまたはFacebookのメールアドレス @@ -1591,45 +1639,45 @@ connect and stream from you? Right click on any Tomahawk playlist to sync it to Spotify. - + Tomahawkのプレイリストを右クリクすると、Spotifyに同期することができます。 High Quality Streams - + 高音質ストリーム Spotify playlists to keep in sync: - + 同期するSpotifyのプレイリスト: Delete Tomahawk playlist when removing synchronization - + 同期を無効すれば、Tomahawkのプレイリストを削除 Username: - + ユーザー名 Password: - + パスワード SpotifyPlaylistUpdater - + Delete in Spotify? - + Spotifyにも削除しますか? - + Would you like to delete the corresponding Spotify playlist as well? - + 同期のSpotifyのプレイリストも削除してもよろしいですか? @@ -1637,7 +1685,7 @@ connect and stream from you? Tomahawk Settings - + 設定 @@ -1932,17 +1980,37 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify @@ -1950,28 +2018,28 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... ログイン中... - + Failed: %1 - + Logged in as %1 - + Log Out - - + + Log In ログイン @@ -1979,7 +2047,7 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium @@ -2215,39 +2283,6 @@ You may wish to try re-authenticating. - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - - - - - Your loved tracks - - - - - %1's loved tracks - - - - - The most loved tracks from all your friends - - - - - All of your loved tracks - - - - - All of %1's loved tracks - - - Tomahawk::DropJobNotifier @@ -2985,7 +3020,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! @@ -3001,7 +3036,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection @@ -3613,35 +3648,40 @@ Twitterを使っている友達にTomahawkを接続したいなら、ツイー ViewManager - + After you have scanned your music collection you will find your tracks right here. コレクションのスキャンが完了したら、トラックはここに表示されます。 - + This collection is empty. このコレクションには何も入っていません。 - + SuperCollection スーパーコレクション - + Combined libraries of all your online friends オンラインの友達全員のライブラリ - + Recently Played Tracks 最近再生したトラック - + Recently played tracks from all your friends 友達の最近再生したトラック + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_pl.ts b/lang/tomahawk_pl.ts index 638f26874..6184f3d42 100644 --- a/lang/tomahawk_pl.ts +++ b/lang/tomahawk_pl.ts @@ -481,6 +481,14 @@ connect and stream from you? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -616,12 +624,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks @@ -734,7 +762,7 @@ connect and stream from you? - + - Properties @@ -844,6 +872,31 @@ connect and stream from you? + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1366,7 +1419,7 @@ connect and stream from you? - + Latest Additions Ostatnio Dodane @@ -1381,37 +1434,37 @@ connect and stream from you? Superkolekcja - + Latest additions to your collection - + Latest additions to %1's collection - + Sorry, we could not find any recent additions! - + Recently Played Tracks - + Your recently played tracks - + %1's recently played tracks - + Sorry, we could not find any recent plays! @@ -1489,77 +1542,72 @@ connect and stream from you? SourcesModel - + Group Grupa - + Collection kolekcja - + Playlist Lista - + Automatic Playlist Automatyczna Lista - + Station Stacja - + Browse Przeglądaj - + Search History Historia wyszukiwania - + My Music Moja Muzyka - + SuperCollection Superkolekcja - - Top Loved Tracks - - - - + Dashboard - + Recently Played Ostatnio Odtworzone - + Charts Listy Przebojów - + New Releases Nowe Wydania - + Friends Znajomi @@ -1620,12 +1668,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? - + Would you like to delete the corresponding Spotify playlist as well? @@ -1934,17 +1982,37 @@ indywidualnego profilu gustu. Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify @@ -1952,28 +2020,28 @@ indywidualnego profilu gustu. Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... - + Failed: %1 - + Logged in as %1 - + Log Out - - + + Log In @@ -1981,7 +2049,7 @@ indywidualnego profilu gustu. Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium @@ -2217,39 +2285,6 @@ You may wish to try re-authenticating. - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Najbardziej Lubiane Utwory - - - - Your loved tracks - Twoje ulubione utwory - - - - %1's loved tracks - Ulubione utwory %1 - - - - The most loved tracks from all your friends - Najbardziej lubiane utwory wszystkich twoich znajomych - - - - All of your loved tracks - Wszystkie twoje ulubione utwory - - - - All of %1's loved tracks - Wszystkie ulubione utwory %1 - - Tomahawk::DropJobNotifier @@ -2989,7 +3024,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! @@ -3005,7 +3040,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection Moja Kolekcja @@ -3617,35 +3652,40 @@ Zawsze możesz ponownie wysłać wiadomość synchronizacyjną - po prostu wyśl ViewManager - + After you have scanned your music collection you will find your tracks right here. - + This collection is empty. - + SuperCollection SuperKolekcja - + Combined libraries of all your online friends Połączone biblioteki wszystkich twoich znajomych online - + Recently Played Tracks - + Recently played tracks from all your friends + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_pt_BR.ts b/lang/tomahawk_pt_BR.ts index 58ae843f8..8be3fe8aa 100644 --- a/lang/tomahawk_pt_BR.ts +++ b/lang/tomahawk_pt_BR.ts @@ -482,6 +482,14 @@ se conecte e faça o stream de você? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -617,12 +625,32 @@ se conecte e faça o stream de você? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! Desculpe, não encontramos nenhuma faixa favorita! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks Faixas Favoritas @@ -735,7 +763,7 @@ se conecte e faça o stream de você? Avançar - + - Properties - Propriedades @@ -845,6 +873,31 @@ se conecte e faça o stream de você? Nome + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1368,7 +1421,7 @@ se conecte e faça o stream de você? - + Latest Additions Últimas Adições @@ -1383,37 +1436,37 @@ se conecte e faça o stream de você? SuperColeção - + Latest additions to your collection Últimas adições à sua coleção - + Latest additions to %1's collection Últimas adições à coleção de %1 - + Sorry, we could not find any recent additions! Desculpe, não foi possível encontrar adições recentes! - + Recently Played Tracks Faixas Reproduzidas Recentemente - + Your recently played tracks Suas faixas reproduzidas recentemente - + %1's recently played tracks Faixas reproduzidas recentemente por %1 - + Sorry, we could not find any recent plays! Desculpe, não foi possível encontrar playlists recentes! @@ -1491,77 +1544,72 @@ se conecte e faça o stream de você? SourcesModel - + Group Grupo - + Collection Coleção - + Playlist Playlist - + Automatic Playlist Playlist Automática - + Station Estação - + Browse Navegar - + Search History Histórico de Busca - + My Music Minhas Músicas - + SuperCollection SuperColeção - - Top Loved Tracks - Faixas Favoritas - - - + Dashboard Painel - + Recently Played Ouvidas Recentemente - + Charts Charts - + New Releases Lançamentos - + Friends Amigos @@ -1622,12 +1670,12 @@ se conecte e faça o stream de você? SpotifyPlaylistUpdater - + Delete in Spotify? Deletar no Spotify? - + Would you like to delete the corresponding Spotify playlist as well? Você também gostaria de deletar a playlist correspondente no Spotify? @@ -1935,17 +1983,37 @@ automáticas baseadas no seu gosto pessoal. Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify Sincronizar com o Spotify - + Re-enable syncing with Spotify Reativar sincronização com Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify Parar a sincronização com o Spotify @@ -1953,28 +2021,28 @@ automáticas baseadas no seu gosto pessoal. Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... Logando... - + Failed: %1 Falha: %1 - + Logged in as %1 - + Log Out - - + + Log In Log In @@ -1982,7 +2050,7 @@ automáticas baseadas no seu gosto pessoal. Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium Reproduzir e sincronizar suas playlists com o Spotify Premium @@ -2221,39 +2289,6 @@ Você pode tentar re-autenticar. &Mostrar Página do Artista - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Faixas Favoritas - - - - Your loved tracks - Suas faixas favoritas - - - - %1's loved tracks - Faixas favoritas de %1 - - - - The most loved tracks from all your friends - As faixas favoritas de todos os seus amigos - - - - All of your loved tracks - Todas as suas faixas favoritas - - - - All of %1's loved tracks - Todas as faixas favoritas de %1 - - Tomahawk::DropJobNotifier @@ -2995,7 +3030,7 @@ Tente ajustar os filtros para ouvir um novo conjunto de músicas. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! Erro ao obter informações do Spotify pela rede! @@ -3011,7 +3046,7 @@ Tente ajustar os filtros para ouvir um novo conjunto de músicas. TomahawkApp - + My Collection Minha Coleção @@ -3623,35 +3658,40 @@ Você pode enviar uma outra mensagem de sincronia a qualquer momento simplesment ViewManager - + After you have scanned your music collection you will find your tracks right here. Depois de escanear sua biblioteca de músicas as faixas irão aparecer aqui. - + This collection is empty. Esta coleção esta vazia. - + SuperCollection SuperColeção - + Combined libraries of all your online friends Bibliotecas combinadas de todos os seus amigos online - + Recently Played Tracks Faixas Reproduzidas Recentemente - + Recently played tracks from all your friends Faixas reproduzidas recentemente por todos os seus amigos + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_ru.ts b/lang/tomahawk_ru.ts index c8e9962d1..2bd49de0c 100644 --- a/lang/tomahawk_ru.ts +++ b/lang/tomahawk_ru.ts @@ -481,6 +481,14 @@ connect and stream from you? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -616,12 +624,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks @@ -734,7 +762,7 @@ connect and stream from you? - + - Properties @@ -844,6 +872,31 @@ connect and stream from you? Имя + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1367,7 +1420,7 @@ connect and stream from you? - + Latest Additions Последние добавленные @@ -1382,37 +1435,37 @@ connect and stream from you? Общая коллекция - + Latest additions to your collection Последние добавления в коллекцию - + Latest additions to %1's collection - + Sorry, we could not find any recent additions! - + Recently Played Tracks Недавно Воспроизводимые - + Your recently played tracks Ваши Недавно Воспроизводимые - + %1's recently played tracks - + Sorry, we could not find any recent plays! @@ -1490,77 +1543,72 @@ connect and stream from you? SourcesModel - + Group Группа - + Collection Коллекция - + Playlist Плейлист - + Automatic Playlist Автоматический плейлист - + Station Станция - + Browse Просмотреть - + Search History История поиска - + My Music Моя музыка - + SuperCollection Общая коллекция - - Top Loved Tracks - Топ любимых песен - - - + Dashboard Панель - + Recently Played Последние воспроизводимые - + Charts Чарты - + New Releases Новые релизы - + Friends Друзья @@ -1621,12 +1669,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? Удалить в Spotify? - + Would you like to delete the corresponding Spotify playlist as well? @@ -1931,17 +1979,37 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify Синхронизировать с Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify Прекратить синхронизацию с Spotify @@ -1949,28 +2017,28 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... Вхожу... - + Failed: %1 Ошибка: %1 - + Logged in as %1 - + Log Out - - + + Log In Войти @@ -1978,7 +2046,7 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium @@ -2217,39 +2285,6 @@ You may wish to try re-authenticating. &Показать Станицу Исполнителя - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Топ любимых песен - - - - Your loved tracks - Ваши любимые песни - - - - %1's loved tracks - %1's любимая песня - - - - The most loved tracks from all your friends - Самые любимые песни от всех ваших друзей - - - - All of your loved tracks - Все любимые песни - - - - All of %1's loved tracks - Все от %1 любимые песни - - Tomahawk::DropJobNotifier @@ -2989,7 +3024,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! Возникла ошибка при получении информации из Spotify! @@ -3005,7 +3040,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection Моя коллекция @@ -3615,35 +3650,40 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. - + This collection is empty. Коллекция пуста - + SuperCollection Общая коллекция - + Combined libraries of all your online friends Комбинированные библиотек всех ваших друзей онлайн - + Recently Played Tracks - + Recently played tracks from all your friends + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_sv.ts b/lang/tomahawk_sv.ts index f73257155..ad6f19cb3 100644 --- a/lang/tomahawk_sv.ts +++ b/lang/tomahawk_sv.ts @@ -481,6 +481,14 @@ connect and stream from you? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -616,12 +624,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks @@ -734,7 +762,7 @@ connect and stream from you? - + - Properties @@ -844,6 +872,31 @@ connect and stream from you? + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1367,7 +1420,7 @@ connect and stream from you? - + Latest Additions Senast tillagda @@ -1382,37 +1435,37 @@ connect and stream from you? SuperCollection - + Latest additions to your collection - + Latest additions to %1's collection - + Sorry, we could not find any recent additions! - + Recently Played Tracks - + Your recently played tracks - + %1's recently played tracks - + Sorry, we could not find any recent plays! @@ -1490,77 +1543,72 @@ connect and stream from you? SourcesModel - + Group Grupp - + Collection Samling - + Playlist Spellista - + Automatic Playlist Automatisk spellista - + Station Station - + Browse Bläddra - + Search History Sökhistorik - + My Music Min Musik - + SuperCollection SuperCollection - - Top Loved Tracks - Mest älskade spår - - - + Dashboard - + Recently Played - + Charts Topplistor - + New Releases - + Friends Vänner @@ -1621,12 +1669,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? - + Would you like to delete the corresponding Spotify playlist as well? @@ -1931,17 +1979,37 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify @@ -1949,28 +2017,28 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... - + Failed: %1 - + Logged in as %1 - + Log Out - - + + Log In @@ -1978,7 +2046,7 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium @@ -2214,39 +2282,6 @@ You may wish to try re-authenticating. - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - Mest älskade spår - - - - Your loved tracks - Dina älskade spår - - - - %1's loved tracks - Älskade spår för %1 - - - - The most loved tracks from all your friends - De mest älskade spåren från alla dina vänner - - - - All of your loved tracks - Alla dina älskade spår - - - - All of %1's loved tracks - Alla spår som %1 älskar - - Tomahawk::DropJobNotifier @@ -2984,7 +3019,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! @@ -3000,7 +3035,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection @@ -3606,35 +3641,40 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. - + This collection is empty. - + SuperCollection - + Combined libraries of all your online friends - + Recently Played Tracks - + Recently played tracks from all your friends + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_tr.ts b/lang/tomahawk_tr.ts index 7149903f6..2243d4b64 100644 --- a/lang/tomahawk_tr.ts +++ b/lang/tomahawk_tr.ts @@ -481,6 +481,14 @@ connect and stream from you? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -616,12 +624,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks @@ -734,7 +762,7 @@ connect and stream from you? - + - Properties @@ -844,6 +872,31 @@ connect and stream from you? + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1366,7 +1419,7 @@ connect and stream from you? - + Latest Additions @@ -1381,37 +1434,37 @@ connect and stream from you? - + Latest additions to your collection - + Latest additions to %1's collection - + Sorry, we could not find any recent additions! - + Recently Played Tracks - + Your recently played tracks - + %1's recently played tracks - + Sorry, we could not find any recent plays! @@ -1489,77 +1542,72 @@ connect and stream from you? SourcesModel - + Group - + Collection - + Playlist - + Automatic Playlist - + Station - + Browse - + Search History - + My Music - + SuperCollection - - Top Loved Tracks - - - - + Dashboard - + Recently Played - + Charts - + New Releases - + Friends @@ -1620,12 +1668,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? - + Would you like to delete the corresponding Spotify playlist as well? @@ -1930,17 +1978,37 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify @@ -1948,28 +2016,28 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... - + Failed: %1 - + Logged in as %1 - + Log Out - - + + Log In @@ -1977,7 +2045,7 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium @@ -2213,39 +2281,6 @@ You may wish to try re-authenticating. - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - - - - - Your loved tracks - - - - - %1's loved tracks - - - - - The most loved tracks from all your friends - - - - - All of your loved tracks - - - - - All of %1's loved tracks - - - Tomahawk::DropJobNotifier @@ -2983,7 +3018,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! @@ -2999,7 +3034,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection @@ -3605,35 +3640,40 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. - + This collection is empty. - + SuperCollection - + Combined libraries of all your online friends - + Recently Played Tracks - + Recently played tracks from all your friends + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_zh_CN.ts b/lang/tomahawk_zh_CN.ts index 4daaeaeab..629cf3e86 100644 --- a/lang/tomahawk_zh_CN.ts +++ b/lang/tomahawk_zh_CN.ts @@ -481,6 +481,14 @@ connect and stream from you? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -616,12 +624,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks 喜爱曲目 @@ -734,7 +762,7 @@ connect and stream from you? - + - Properties @@ -844,6 +872,31 @@ connect and stream from you? + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1366,7 +1419,7 @@ connect and stream from you? - + Latest Additions @@ -1381,37 +1434,37 @@ connect and stream from you? - + Latest additions to your collection - + Latest additions to %1's collection - + Sorry, we could not find any recent additions! - + Recently Played Tracks 最近播放曲目 - + Your recently played tracks 你最近播放的曲目 - + %1's recently played tracks %1最近播放的曲目 - + Sorry, we could not find any recent plays! @@ -1489,77 +1542,72 @@ connect and stream from you? SourcesModel - + Group - + Collection - + Playlist - + Automatic Playlist - + Station - + Browse 随便看看 - + Search History 搜索历史 - + My Music 我的音乐 - + SuperCollection - - Top Loved Tracks - - - - + Dashboard - + Recently Played 最近播放 - + Charts 排行榜 - + New Releases 新专辑 - + Friends @@ -1620,12 +1668,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? - + Would you like to delete the corresponding Spotify playlist as well? @@ -1930,17 +1978,37 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify @@ -1948,28 +2016,28 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... - + Failed: %1 - + Logged in as %1 - + Log Out - - + + Log In @@ -1977,7 +2045,7 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium @@ -2213,39 +2281,6 @@ You may wish to try re-authenticating. - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - - - - - Your loved tracks - - - - - %1's loved tracks - - - - - The most loved tracks from all your friends - - - - - All of your loved tracks - - - - - All of %1's loved tracks - - - Tomahawk::DropJobNotifier @@ -2983,7 +3018,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! @@ -2999,7 +3034,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection @@ -3605,35 +3640,40 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. - + This collection is empty. - + SuperCollection - + Combined libraries of all your online friends - + Recently Played Tracks 最近播放曲目 - + Recently played tracks from all your friends 所有朋友最近播放的曲目 + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/lang/tomahawk_zh_TW.ts b/lang/tomahawk_zh_TW.ts index cb8ce803d..9366a8bbb 100644 --- a/lang/tomahawk_zh_TW.ts +++ b/lang/tomahawk_zh_TW.ts @@ -481,6 +481,14 @@ connect and stream from you? + + FlexibleHeader + + + Filter... + + + GlobalSearchWidget @@ -616,12 +624,32 @@ connect and stream from you? LovedTracksItem - + + Top Loved Tracks + + + + Sorry, we could not find any loved tracks! - + + The most loved tracks from all your friends + + + + + All of your loved tracks + + + + + All of %1's loved tracks + + + + Loved Tracks @@ -734,7 +762,7 @@ connect and stream from you? - + - Properties @@ -844,6 +872,31 @@ connect and stream from you? + + PlaylistHeader + + + InfoBar + + + + + Caption + + + + + Description + + + + + + + RadioButton + + + PlaylistItemDelegate @@ -1366,7 +1419,7 @@ connect and stream from you? - + Latest Additions 最新加入 @@ -1381,37 +1434,37 @@ connect and stream from you? 超級收藏 - + Latest additions to your collection - + Latest additions to %1's collection - + Sorry, we could not find any recent additions! - + Recently Played Tracks - + Your recently played tracks - + %1's recently played tracks - + Sorry, we could not find any recent plays! @@ -1489,77 +1542,72 @@ connect and stream from you? SourcesModel - + Group - + Collection 收藏 - + Playlist 播放清單 - + Automatic Playlist 自動播放清單 - + Station - + Browse 瀏覽 - + Search History 搜尋記錄 - + My Music 我的音樂 - + SuperCollection 超級收藏 - - Top Loved Tracks - 最喜愛的曲目 - - - + Dashboard 儀表板 - + Recently Played 最近播放的 - + Charts - + New Releases 新版本 - + Friends 朋友 @@ -1620,12 +1668,12 @@ connect and stream from you? SpotifyPlaylistUpdater - + Delete in Spotify? - + Would you like to delete the corresponding Spotify playlist as well? @@ -1930,17 +1978,37 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccount - + Sync with Spotify - + Re-enable syncing with Spotify - + + Create local copy + + + + + Subscribe to playlist changes + + + + + Re-enable playlist subscription + + + + + Stop subscribing to changes + + + + Stop syncing with Spotify @@ -1948,28 +2016,28 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountConfig - + Logging in... 登錄中... - + Failed: %1 失敗:%1 - + Logged in as %1 - + Log Out - - + + Log In 登錄 @@ -1977,7 +2045,7 @@ connect and stream from you? Tomahawk::Accounts::SpotifyAccountFactory - + Play music from and sync your playlists with Spotify Premium @@ -2213,39 +2281,6 @@ You may wish to try re-authenticating. - - Tomahawk::CustomPlaylistView - - - Top Loved Tracks - - - - - Your loved tracks - - - - - %1's loved tracks - - - - - The most loved tracks from all your friends - 在您所有的朋友中,最受喜愛的曲目 - - - - All of your loved tracks - - - - - All of %1's loved tracks - - - Tomahawk::DropJobNotifier @@ -2983,7 +3018,7 @@ Try tweaking the filters for a new set of songs to play. Tomahawk::SpotifyParser - + Error fetching Spotify information from the network! @@ -2999,7 +3034,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection 我的收藏 @@ -3605,35 +3640,40 @@ You can re-send a sync message at any time simply by sending another tweet using ViewManager - + After you have scanned your music collection you will find your tracks right here. - + This collection is empty. - + SuperCollection 超級收藏 - + Combined libraries of all your online friends 聯合您所有線上朋友的音樂庫 - + Recently Played Tracks - + Recently played tracks from all your friends + + + Sorry, we could not find any recent plays! + + WelcomeWidget diff --git a/resources.qrc b/resources.qrc index 4e39e93b0..f4e960b76 100644 --- a/resources.qrc +++ b/resources.qrc @@ -45,6 +45,8 @@ data/images/view-toggle-icon-artist-inactive.png data/images/view-toggle-icon-cloud-active.png data/images/view-toggle-icon-cloud-inactive.png + data/images/view-toggle-icon-grid-active.png + data/images/view-toggle-icon-grid-inactive.png data/images/view-toggle-icon-list-active.png data/images/view-toggle-icon-list-inactive.png data/images/view-toggle-inactive-centre.png diff --git a/src/libtomahawk/AlbumPlaylistInterface.cpp b/src/libtomahawk/AlbumPlaylistInterface.cpp index d74af3811..e8217186e 100644 --- a/src/libtomahawk/AlbumPlaylistInterface.cpp +++ b/src/libtomahawk/AlbumPlaylistInterface.cpp @@ -92,6 +92,31 @@ AlbumPlaylistInterface::hasNextItem() } +bool +AlbumPlaylistInterface::hasPreviousItem() +{ + int p = m_currentTrack; + p--; + if ( p < 0 || p >= m_queries.count() ) + return false; + + return true; +} + + +bool +AlbumPlaylistInterface::setCurrentTrack( unsigned int albumpos ) +{ + albumpos--; + if ( albumpos >= m_queries.count() ) + return false; + + m_currentTrack = albumpos; + m_currentItem = m_queries.at( albumpos )->results().first(); + return true; +} + + QList< Tomahawk::query_ptr > AlbumPlaylistInterface::tracks() { @@ -114,6 +139,10 @@ AlbumPlaylistInterface::tracks() connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) ); + + connect( Tomahawk::InfoSystem::InfoSystem::instance(), + SIGNAL( finished( QString ) ), + SLOT( infoSystemFinished( QString ) ) ); } else if ( m_mode == DatabaseMode && !m_databaseLoaded ) { @@ -178,9 +207,24 @@ AlbumPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData re } } + if ( !m_queries.isEmpty() ) + { + infoSystemFinished( id() ); + } +} + + +void +AlbumPlaylistInterface::infoSystemFinished( const QString& infoId ) +{ + if ( infoId != id() ) + return; + m_infoSystemLoaded = true; disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), this, SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) ); + disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), + this, SLOT( infoSystemFinished( QString ) ) ); if ( m_queries.isEmpty() && m_mode == Mixed ) { diff --git a/src/libtomahawk/AlbumPlaylistInterface.h b/src/libtomahawk/AlbumPlaylistInterface.h index b2c9d471c..c479b6342 100644 --- a/src/libtomahawk/AlbumPlaylistInterface.h +++ b/src/libtomahawk/AlbumPlaylistInterface.h @@ -47,6 +47,7 @@ public: virtual Tomahawk::result_ptr siblingItem( int itemsAway ); virtual bool hasNextItem(); + virtual bool hasPreviousItem(); virtual Tomahawk::result_ptr currentItem() const; virtual PlaylistModes::RepeatMode repeatMode() const { return PlaylistModes::NoRepeat; } @@ -54,6 +55,7 @@ public: virtual void setRepeatMode( PlaylistModes::RepeatMode ) {} virtual void setShuffled( bool ) {} + virtual bool setCurrentTrack( unsigned int albumpos ); signals: void tracksLoaded( Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection ); @@ -61,6 +63,7 @@ signals: private slots: void onTracksLoaded( const QList< Tomahawk::query_ptr >& tracks ); void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); + void infoSystemFinished( const QString& infoId ); private: QList< Tomahawk::query_ptr > m_queries; diff --git a/src/libtomahawk/Artist.cpp b/src/libtomahawk/Artist.cpp index 6d8dcb9f9..a178dcc77 100644 --- a/src/libtomahawk/Artist.cpp +++ b/src/libtomahawk/Artist.cpp @@ -32,6 +32,8 @@ #include +#define ID_THREAD_DEBUG 0 + using namespace Tomahawk; QHash< QString, artist_ptr > Artist::s_artistsByName = QHash< QString, artist_ptr >(); @@ -55,6 +57,9 @@ Artist::get( const QString& name, bool autoCreate ) if ( !Database::instance() || !Database::instance()->impl() ) return artist_ptr(); +#if ID_THREAD_DEBUG + qDebug() << "Creating artist:" << name; +#endif artist_ptr artist = artist_ptr( new Artist( name ), &QObject::deleteLater ); artist->setWeakRef( artist.toWeakRef() ); artist->loadId( autoCreate ); @@ -274,8 +279,20 @@ Artist::id() const if ( waiting ) { + +#if ID_THREAD_DEBUG + qDebug() << Q_FUNC_INFO << "Asked for artist ID and NOT loaded yet" << m_name << m_idFuture.isFinished(); +#endif + m_idFuture.waitForFinished(); +#if ID_THREAD_DEBUG + qDebug() << "DONE WAITING:" << m_idFuture.resultCount() << m_idFuture.isResultReadyAt(0) << m_idFuture.isCanceled() << m_idFuture.isFinished() << m_idFuture.isPaused() << m_idFuture.isRunning() << m_idFuture.isStarted(); +#endif finalid = m_idFuture.result(); +#if ID_THREAD_DEBUG + qDebug() << Q_FUNC_INFO << "Got loaded artist:" << m_name << finalid; +#endif + s_idMutex.lockForWrite(); m_id = finalid; m_waitingForFuture = false; diff --git a/src/libtomahawk/ArtistPlaylistInterface.cpp b/src/libtomahawk/ArtistPlaylistInterface.cpp index 977edec2c..750c08c4b 100644 --- a/src/libtomahawk/ArtistPlaylistInterface.cpp +++ b/src/libtomahawk/ArtistPlaylistInterface.cpp @@ -112,6 +112,10 @@ ArtistPlaylistInterface::tracks() connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) ); + + connect( Tomahawk::InfoSystem::InfoSystem::instance(), + SIGNAL( finished( QString ) ), + SLOT( infoSystemFinished( QString ) ) ); } else if ( m_mode == DatabaseMode && !m_databaseLoaded ) { @@ -176,9 +180,23 @@ ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData r } } + if ( !m_queries.isEmpty() ) + infoSystemFinished( id() ); +} + + +void +ArtistPlaylistInterface::infoSystemFinished( const QString &infoId ) +{ + if ( infoId != id() ) + return; + m_infoSystemLoaded = true; + disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), this, SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) ); + disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), + this, SLOT( infoSystemFinished( QString) ) ); if ( m_queries.isEmpty() && m_mode == Mixed ) { diff --git a/src/libtomahawk/ArtistPlaylistInterface.h b/src/libtomahawk/ArtistPlaylistInterface.h index 655832d1f..fd8ecf302 100644 --- a/src/libtomahawk/ArtistPlaylistInterface.h +++ b/src/libtomahawk/ArtistPlaylistInterface.h @@ -60,6 +60,7 @@ signals: private slots: void onTracksLoaded( const QList< Tomahawk::query_ptr >& tracks ); void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); + void infoSystemFinished( const QString& infoId ); private: Q_DISABLE_COPY( ArtistPlaylistInterface ) diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 0e7fcf2ea..371b4db42 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -48,6 +48,7 @@ set( libGuiSources infobar/InfoBar.cpp + playlist/FlexibleHeader.cpp playlist/FlexibleView.cpp playlist/TreeModel.cpp playlist/TreeProxyModel.cpp @@ -66,8 +67,8 @@ set( libGuiSources playlist/GridItemDelegate.cpp playlist/GridView.cpp playlist/TreeView.cpp - playlist/CustomPlaylistView.cpp playlist/ViewHeader.cpp + playlist/LovedTracksModel.cpp playlist/RecentlyAddedModel.cpp playlist/RecentlyPlayedModel.cpp playlist/PlaylistLargeItemDelegate.cpp @@ -90,8 +91,6 @@ set( libGuiSources playlist/dynamic/widgets/CollapsibleControls.cpp playlist/dynamic/widgets/DynamicSetupWidget.cpp - - ExternalResolverGui.cpp resolvers/ScriptResolver.cpp resolvers/QtScriptResolver.cpp @@ -324,6 +323,7 @@ set( libUI ${libUI} widgets/infowidgets/AlbumInfoWidget.ui widgets/infowidgets/TrackInfoWidget.ui playlist/QueueView.ui + playlist/PlaylistHeader.ui filemetadata/MetadataEditor.ui context/ContextWidget.ui infobar/InfoBar.ui diff --git a/src/libtomahawk/ContextMenu.cpp b/src/libtomahawk/ContextMenu.cpp index 8092aa00c..b4573d804 100644 --- a/src/libtomahawk/ContextMenu.cpp +++ b/src/libtomahawk/ContextMenu.cpp @@ -336,12 +336,12 @@ ContextMenu::onSocialActionsLoaded() if ( m_queries.isEmpty() || m_queries.first().isNull() ) return; - if ( m_queries.first()->loved() ) + if ( m_loveAction && m_queries.first()->loved() ) { m_loveAction->setText( tr( "Un-&Love" ) ); m_loveAction->setIcon( QIcon( RESPATH "images/not-loved.png" ) ); } - else + else if ( m_loveAction ) { m_loveAction->setText( tr( "&Love" ) ); m_loveAction->setIcon( QIcon( RESPATH "images/loved.png" ) ); diff --git a/src/libtomahawk/PlaylistInterface.h b/src/libtomahawk/PlaylistInterface.h index e61b8c60c..3fcd8e6d4 100644 --- a/src/libtomahawk/PlaylistInterface.h +++ b/src/libtomahawk/PlaylistInterface.h @@ -47,6 +47,7 @@ public: virtual Tomahawk::result_ptr currentItem() const = 0; virtual Tomahawk::result_ptr previousItem(); virtual bool hasNextItem() { return true; } + virtual bool hasPreviousItem() { return true; } virtual Tomahawk::result_ptr nextItem(); virtual Tomahawk::result_ptr siblingItem( int itemsAway ) = 0; @@ -65,6 +66,8 @@ public: virtual PlaylistModes::LatchMode latchMode() const { return m_latchMode; } virtual void setLatchMode( PlaylistModes::LatchMode latchMode ) { m_latchMode = latchMode; } + virtual bool setCurrentTrack( unsigned int albumpos ) { Q_UNUSED( albumpos ); return false; } + virtual void reset() {} //TODO: Get rid of the next two functions once all playlsitinterfaces are factored out diff --git a/src/libtomahawk/ViewManager.cpp b/src/libtomahawk/ViewManager.cpp index 9893378e6..d247e932b 100644 --- a/src/libtomahawk/ViewManager.cpp +++ b/src/libtomahawk/ViewManager.cpp @@ -38,7 +38,6 @@ #include "SourceList.h" #include "TomahawkSettings.h" -#include "CustomPlaylistView.h" #include "PlaylistLargeItemDelegate.h" #include "RecentlyPlayedModel.h" #include "dynamic/widgets/DynamicWidget.h" @@ -76,7 +75,6 @@ ViewManager::ViewManager( QObject* parent ) , m_welcomeWidget( new WelcomeWidget() ) , m_whatsHotWidget( new WhatsHotWidget() ) , m_newReleasesWidget( new NewReleasesWidget() ) - , m_topLovedWidget( 0 ) , m_recentPlaysWidget( 0 ) , m_currentPage( 0 ) , m_loaded( false ) @@ -126,7 +124,6 @@ ViewManager::~ViewManager() delete m_whatsHotWidget; delete m_newReleasesWidget; delete m_welcomeWidget; - delete m_topLovedWidget; delete m_recentPlaysWidget; delete m_contextWidget; delete m_widget; @@ -138,13 +135,14 @@ ViewManager::createPageForPlaylist( const playlist_ptr& playlist ) { FlexibleView* view = new FlexibleView(); PlaylistModel* model = new PlaylistModel(); - view->setPlayableModel( model ); PlaylistView* pv = new PlaylistView(); pv->setPlaylistModel( model ); view->setDetailedView( pv ); + view->setPixmap( pv->pixmap() ); model->loadPlaylist( playlist ); + view->setPlayableModel( model ); playlist->resolve(); return view; @@ -386,40 +384,24 @@ ViewManager::showNewReleasesPage() } -Tomahawk::ViewPage* -ViewManager::showTopLovedPage() -{ - if ( !m_topLovedWidget ) - { - CustomPlaylistView* view = new CustomPlaylistView( CustomPlaylistView::TopLovedTracks, source_ptr(), m_widget ); - PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::LovedTracks, view, view->proxyModel() ); - connect( del, SIGNAL( updateIndex( QModelIndex ) ), view, SLOT( update( QModelIndex ) ) ); - view->setItemDelegate( del ); - - m_topLovedWidget = view; - } - - return show( m_topLovedWidget ); -} - - Tomahawk::ViewPage* ViewManager::showRecentPlaysPage() { if ( !m_recentPlaysWidget ) { - PlaylistView* pv = new PlaylistView( m_widget ); + FlexibleView* pv = new FlexibleView( m_widget ); + pv->setPixmap( QPixmap( RESPATH "images/recently-played.png" ) ); RecentlyPlayedModel* raModel = new RecentlyPlayedModel( pv ); raModel->setTitle( tr( "Recently Played Tracks" ) ); raModel->setDescription( tr( "Recently played tracks from all your friends" ) ); - pv->proxyModel()->setStyle( PlayableProxyModel::Large ); - PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::RecentlyPlayed, pv, pv->proxyModel() ); - connect( del, SIGNAL( updateIndex( QModelIndex ) ), pv, SLOT( update( QModelIndex ) ) ); - pv->setItemDelegate( del ); + PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::RecentlyPlayed, pv->trackView(), pv->trackView()->proxyModel() ); + connect( del, SIGNAL( updateIndex( QModelIndex ) ), pv->trackView(), SLOT( update( QModelIndex ) ) ); + pv->trackView()->setItemDelegate( del ); - pv->setPlaylistModel( raModel ); + pv->setPlayableModel( raModel ); + pv->setEmptyTip( tr( "Sorry, we could not find any recent plays!" ) ); raModel->setSource( source_ptr() ); m_recentPlaysWidget = pv; @@ -904,13 +886,6 @@ ViewManager::newReleasesWidget() const } -Tomahawk::ViewPage* -ViewManager::topLovedWidget() const -{ - return m_topLovedWidget; -} - - Tomahawk::ViewPage* ViewManager::recentPlaysWidget() const { diff --git a/src/libtomahawk/ViewManager.h b/src/libtomahawk/ViewManager.h index 5e97bb73f..8d59585e8 100644 --- a/src/libtomahawk/ViewManager.h +++ b/src/libtomahawk/ViewManager.h @@ -91,7 +91,6 @@ public: Tomahawk::ViewPage* welcomeWidget() const; Tomahawk::ViewPage* whatsHotWidget() const; Tomahawk::ViewPage* newReleasesWidget() const; - Tomahawk::ViewPage* topLovedWidget() const; Tomahawk::ViewPage* recentPlaysWidget() const; TreeView* superCollectionView() const; @@ -134,7 +133,6 @@ public slots: Tomahawk::ViewPage* showWelcomePage(); Tomahawk::ViewPage* showWhatsHotPage(); Tomahawk::ViewPage* showNewReleasesPage(); - Tomahawk::ViewPage* showTopLovedPage(); Tomahawk::ViewPage* showRecentPlaysPage(); void showCurrentTrack(); @@ -195,7 +193,6 @@ private: WelcomeWidget* m_welcomeWidget; WhatsHotWidget* m_whatsHotWidget; NewReleasesWidget* m_newReleasesWidget; - Tomahawk::ViewPage* m_topLovedWidget; Tomahawk::ViewPage* m_recentPlaysWidget; QList< Tomahawk::collection_ptr > m_superCollections; diff --git a/src/libtomahawk/accounts/spotify/SpotifyAccount.cpp b/src/libtomahawk/accounts/spotify/SpotifyAccount.cpp index a72b828ea..f330678ea 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyAccount.cpp +++ b/src/libtomahawk/accounts/spotify/SpotifyAccount.cpp @@ -62,6 +62,15 @@ static QString s_resolverId = "spotify-linux-x86"; static QString s_resolverId = "spotify-unknown"; #endif + +namespace { +enum ActionType { + Sync = 0, + Subscribe +}; +} + + Account* SpotifyAccountFactory::createAccount( const QString& accountId ) { @@ -79,6 +88,14 @@ SpotifyAccountFactory::icon() const } +SpotifyAccount* SpotifyAccount::s_instance = 0; + +SpotifyAccount* +SpotifyAccount::instance() +{ + return s_instance; +} + SpotifyAccount::SpotifyAccount( const QString& accountId ) : CustomAtticaAccount( accountId ) , m_preventEnabling( false ) @@ -424,44 +441,126 @@ SpotifyAccount::aboutToShow( QAction* action, const playlist_ptr& playlist ) // If it's not being synced, allow the option to sync bool found = false; + bool canSubscribe = false; + bool isSubscribed = false; bool manuallyDisabled = false; + bool sync = false; + action->setVisible( true ); + QList updaters = playlist->updaters(); foreach ( PlaylistUpdaterInterface* updater, updaters ) { if ( SpotifyPlaylistUpdater* spotifyUpdater = qobject_cast< SpotifyPlaylistUpdater* >( updater ) ) { found = true; - if ( !spotifyUpdater->sync() ) + + canSubscribe = spotifyUpdater->canSubscribe(); + isSubscribed = spotifyUpdater->subscribed(); + + if ( !canSubscribe && !spotifyUpdater->sync() ) manuallyDisabled = true; + if ( spotifyUpdater->sync() ) + sync = true; + } } - if ( !found ) + const ActionType actionType = static_cast< ActionType >( action->data().toInt() ); + + if ( actionType == Sync ) { - action->setText( tr( "Sync with Spotify" ) ); + if ( !found ) + { + action->setText( tr( "Sync with Spotify" ) ); + } + else if ( manuallyDisabled ) + { + action->setText( tr( "Re-enable syncing with Spotify" ) ); + } + else + { + // We dont want to sync a subscribeable playlist but if a playlist isnt + // collaborative, he will loose his changes on next update, thus, + // we create a new copy of it + if ( canSubscribe ) + action->setText( tr( "Create local copy") ); + else if ( sync ) + action->setText( tr( "Stop syncing with Spotify" ) ); + else + action->setVisible( false ); + } } - else if ( manuallyDisabled ) + + // User can sync or subscribe on playlist. + // Sync means creating a new copy of it, subscribe is listening on changes from owner + if ( actionType == Subscribe ) { - action->setText( tr( "Re-enable syncing with Spotify" ) ); - } - else - { - action->setText( tr( "Stop syncing with Spotify" ) ); + if ( found && canSubscribe ) + { + if ( !isSubscribed ) + { + action->setText( tr( "Subscribe to playlist changes" ) ); + } + else if ( manuallyDisabled ) + { + action->setText( tr( "Re-enable playlist subscription" ) ); + } + else if ( isSubscribed ) + { + action->setText( tr( "Stop subscribing to changes" ) ); + } + else + { + // Hide the action, we dont have this option on the playlist + action->setVisible( false ); + } + } + else + { + action->setVisible( false ); + } } } void -SpotifyAccount::syncActionTriggered( bool checked ) +SpotifyAccount::subscribeActionTriggered( bool ) { - Q_UNUSED( checked ); - QAction* action = qobject_cast< QAction* >( sender() ); + const playlist_ptr playlist = playlistFromAction( qobject_cast< QAction* >( sender() ) ); - if ( !action || !m_customActions.contains( action ) ) + if ( playlist.isNull() ) + { + qWarning() << "Got context menu spotify sync action triggered, but invalid playlist payload!"; + Q_ASSERT( false ); + return; + } + + SpotifyPlaylistUpdater* updater = 0; + QList updaters = playlist->updaters(); + foreach ( PlaylistUpdaterInterface* u, updaters ) + { + if ( SpotifyPlaylistUpdater* spotifyUpdater = qobject_cast< SpotifyPlaylistUpdater* >( u ) ) + { + updater = spotifyUpdater; + break; + } + } + + Q_ASSERT( updater ); + if ( !updater ) return; - const playlist_ptr playlist = action->property( "payload" ).value< playlist_ptr >(); + // Toggle subscription status + setSubscribedForPlaylist( playlist, !updater->subscribed() ); +} + + +void +SpotifyAccount::syncActionTriggered( bool ) +{ + const playlist_ptr playlist = playlistFromAction( qobject_cast< QAction* >( sender() ) ); + if ( playlist.isNull() ) { qWarning() << "Got context menu spotify sync action triggered, but invalid playlist payload!"; @@ -479,12 +578,16 @@ SpotifyAccount::syncActionTriggered( bool checked ) } } - if ( !updater ) + if ( !updater || updater->canSubscribe() ) { QVariantMap msg; msg[ "_msgtype" ] = "createPlaylist"; msg[ "sync" ] = true; - msg[ "title" ] = playlist->title(); + + if ( !updater ) + msg[ "title" ] = playlist->title(); + else + msg[ "title" ] = "Copy of " + playlist->title(); QList< query_ptr > queries; foreach ( const plentry_ptr& ple, playlist->entries() ) @@ -492,27 +595,24 @@ SpotifyAccount::syncActionTriggered( bool checked ) QVariantList tracks = SpotifyPlaylistUpdater::queriesToVariant( queries ); msg[ "tracks" ] = tracks; - const QString qid = sendMessage( msg, this, "playlistCreated" ); + QString qid; + if ( !updater ) + qid = sendMessage( msg, this, "playlistCreated" ); + else + qid = sendMessage( msg, this, "playlistCopyCreated" ); + m_waitingForCreateReply[ qid ] = playlist; } else { - SpotifyPlaylistInfo* info = 0; - foreach ( SpotifyPlaylistInfo* ifo, m_allSpotifyPlaylists ) - { - if ( ifo->plid == updater->spotifyId() ) - { - info = ifo; - break; - } - } + SpotifyPlaylistInfo* info = m_allSpotifyPlaylists.value( updater->spotifyId(), 0 ); Q_ASSERT( info ); if ( info ) info->sync = !updater->sync(); if ( m_configWidget.data() ) - m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists ); + m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists.values() ); if ( !updater->sync() ) { @@ -526,6 +626,75 @@ SpotifyAccount::syncActionTriggered( bool checked ) } +void +SpotifyAccount::setSubscribedForPlaylist( const playlist_ptr& playlist, bool subscribed ) +{ + SpotifyPlaylistUpdater* updater = 0; + QList updaters = playlist->updaters(); + foreach ( PlaylistUpdaterInterface* u, updaters ) + { + if ( SpotifyPlaylistUpdater* spotifyUpdater = qobject_cast< SpotifyPlaylistUpdater* >( u ) ) + { + updater = spotifyUpdater; + break; + } + } + + if ( !updater ) + { + tLog() << "No SpotifyPlaylistUpdater in payload slot of triggered action! Uh oh!!"; + return; + } + + SpotifyPlaylistInfo* info = m_allSpotifyPlaylists.value( updater->spotifyId(), 0 ); + + // When we unsubscribe, all playlists is resent + // and we will could loose the SpotifyPlaylistInfo, but all we really need is the id + if ( updater->spotifyId().isEmpty() ) + { + tLog() << "No spotify id in updater, WTF?"; + return; + } + + if ( !info ) + { + info = new SpotifyPlaylistInfo( playlist->title(), + updater->spotifyId(), + updater->spotifyId(), + false, + false + ); + + registerPlaylistInfo( info ); + } + + info->subscribed = subscribed; + info->sync = subscribed; + + QVariantMap msg; + msg[ "_msgtype" ] = "setSubscription"; + msg[ "subscribe" ] = info->subscribed; + msg[ "playlistid" ] = info->plid; + + sendMessage( msg, this ); + + updater->setSync( subscribed ); + updater->setSubscribed( subscribed ); +} + + +playlist_ptr +SpotifyAccount::playlistFromAction( QAction* action ) const +{ + Q_ASSERT( action ); + + if ( !action || !m_customActions.contains( action ) ) + return playlist_ptr(); + + return action->property( "payload" ).value< playlist_ptr >(); +} + + void SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg ) { @@ -564,13 +733,17 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg QObject* receiver = m_qidToSlotMap[ qid ].first; QString slot = m_qidToSlotMap[ qid ].second; m_qidToSlotMap.remove( qid ); + + QVariant extraData; + if ( m_qidToExtraData.contains( qid ) ) + extraData = m_qidToExtraData.take( qid ); - QMetaObject::invokeMethod( receiver, slot.toLatin1(), Q_ARG( QString, msgType ), Q_ARG( QVariantMap, msg ) ); + QMetaObject::invokeMethod( receiver, slot.toLatin1(), Q_ARG( QString, msgType ), Q_ARG( QVariantMap, msg ), Q_ARG( QVariant, extraData ) ); } else if ( msgType == "allPlaylists" ) { const QVariantList playlists = msg.value( "playlists" ).toList(); - qDeleteAll( m_allSpotifyPlaylists ); + qDeleteAll( m_allSpotifyPlaylists.values() ); m_allSpotifyPlaylists.clear(); foreach ( const QVariant& playlist, playlists ) @@ -580,18 +753,20 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg const QString plid = plMap.value( "id" ).toString(); const QString revid = plMap.value( "revid" ).toString(); const bool sync = plMap.value( "sync" ).toBool(); + const bool subscribed = plMap.value( "subscribed" ).toBool(); if ( name.isNull() || plid.isNull() || revid.isNull() ) { qDebug() << "Did not get name and plid and revid for spotify playlist:" << name << plid << revid << plMap; continue; } - m_allSpotifyPlaylists << new SpotifyPlaylistInfo( name, plid, revid, sync ); + + registerPlaylistInfo( new SpotifyPlaylistInfo( name, plid, revid, sync, subscribed ) ); } if ( !m_configWidget.isNull() ) { - m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists ); + m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists.values() ); } } else if ( msgType == "tracksAdded" ) @@ -655,7 +830,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg updater->spotifyTracksMoved( tracksList, newStartPos, newRev, oldRev ); } - else if( msgType == "playlistRenamed" ) + else if ( msgType == "playlistRenamed" ) { const QString plid = msg.value( "id" ).toString(); // We should already be syncing this playlist if we get updates for it @@ -675,18 +850,18 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg updater->spotifyPlaylistRenamed( title, newRev, oldRev ); } - else if( msgType == "spotifyError" ) + else if ( msgType == "spotifyError" ) { const QString error = msg.value( "msg" ).toString(); - if( error.isEmpty() ) + if ( error.isEmpty() ) return; - if( msg.value( "isDebugMsg" ).toBool() ) + if ( msg.value( "isDebugMsg" ).toBool() ) tDebug( LOGVERBOSE ) << "SpotifyResolverError: " << error; else JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( QString( "Spotify: %1" ).arg( error ) ) ); } - else if( msgType == "userChanged" ) + else if ( msgType == "userChanged" ) { const QString rmsg = msg.value( "msg" ).toString(); clearUser( true ); @@ -710,8 +885,10 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg m_loggedIn = success; if ( success ) + { createActions(); - + s_instance = this; + } configurationWidget(); // ensure it's created so we can set the login button if ( m_configWidget.data() ) { @@ -737,7 +914,10 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg qDebug() << "Got status message with login info:" << loggedIn << username; if ( !loggedIn || username.isEmpty() || credentials().value( "username").toString() != username ) + { m_loggedIn = false; + s_instance = 0; + } QVariantMap msg; msg[ "_msgtype" ] = "status"; @@ -762,7 +942,7 @@ SpotifyAccount::clearUser( bool permanentlyDelete ) m_updaters.clear(); - qDeleteAll( m_allSpotifyPlaylists ); + qDeleteAll( m_allSpotifyPlaylists.values() ); m_allSpotifyPlaylists.clear(); m_qidToSlotMap.clear(); @@ -790,7 +970,7 @@ SpotifyAccount::configurationWidget() m_configWidget = QWeakPointer< SpotifyAccountConfig >( new SpotifyAccountConfig( this ) ); connect( m_configWidget.data(), SIGNAL( login( QString,QString ) ), this, SLOT( login( QString,QString ) ) ); connect( m_configWidget.data(), SIGNAL( logout() ), this, SLOT( logout() ) ); - m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists ); + m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists.values() ); } if ( m_spotifyResolver.isNull() || !m_spotifyResolver.data()->running() ) @@ -847,7 +1027,7 @@ SpotifyAccount::saveConfig() setConfiguration( config ); m_configWidget.data()->saveSettings(); - foreach ( SpotifyPlaylistInfo* pl, m_allSpotifyPlaylists ) + foreach ( SpotifyPlaylistInfo* pl, m_allSpotifyPlaylists.values() ) { // qDebug() << "Checking changed state:" << pl->changed << pl->name << pl->sync; if ( pl->changed ) @@ -892,6 +1072,7 @@ SpotifyAccount::logout() QVariantMap msg; msg[ "_msgtype" ] = "logout"; m_spotifyResolver.data()->sendMessage( msg ); + s_instance = 0; } @@ -911,7 +1092,7 @@ SpotifyAccount::startPlaylistSync( SpotifyPlaylistInfo* playlist ) void -SpotifyAccount::startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg ) +SpotifyAccount::startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg, const QVariant& ) { Q_UNUSED( msgType ); qDebug() << Q_FUNC_INFO << "Got full spotify playlist body, creating a tomahawk playlist and enabling sync!!"; @@ -957,9 +1138,39 @@ SpotifyAccount::startPlaylistSyncWithPlaylist( const QString& msgType, const QVa } } +void +SpotifyAccount::playlistCopyCreated( const QString& msgType, const QVariantMap& msg, const QVariant& ) +{ + Q_UNUSED( msgType ); + + qDebug() << Q_FUNC_INFO << "Got response from our createCopyPlaylist command, now creating updater and attaching"; + const bool success = msg.value( "success" ).toBool(); + + if ( !success ) + { + qWarning() << "Got FAILED return code from spotify resolver createPlaylist command, aborting sync"; + return; + } + + const QString id = msg.value( "playlistid" ).toString(); + const QString revid = msg.value( "playlistid" ).toString(); + const QString qid = msg.value( "qid" ).toString(); + const QString title = msg.value( "playlistname" ).toString(); + + qDebug() << msg; + if ( !m_waitingForCreateReply.contains( qid ) ) + { + qWarning() << "Got a createPlaylist reply for a playlist/qid we were not waiting for :-/ " << qid << m_waitingForCreateReply; + return; + } + + SpotifyPlaylistInfo *info = new SpotifyPlaylistInfo( title, id, revid, true, false ); + startPlaylistSync( info ); +} + void -SpotifyAccount::playlistCreated( const QString& msgType, const QVariantMap& msg ) +SpotifyAccount::playlistCreated( const QString& msgType, const QVariantMap& msg, const QVariant& ) { Q_UNUSED( msgType ); @@ -990,20 +1201,20 @@ SpotifyAccount::playlistCreated( const QString& msgType, const QVariantMap& msg QString -SpotifyAccount::sendMessage( const QVariantMap &m, QObject* obj, const QString& slot ) +SpotifyAccount::sendMessage( const QVariantMap &m, QObject* obj, const QString& slot, const QVariant& extraData ) { QVariantMap msg = m; - QString qid; + const QString qid = uuid(); if ( obj ) { - qid = QUuid::createUuid().toString().replace( "{", "" ).replace( "}", "" ); - m_qidToSlotMap[ qid ] = qMakePair( obj, slot ); msg[ "qid" ] = qid; } + m_qidToExtraData[ qid ] = extraData; + m_spotifyResolver.data()->sendMessage( msg ); return qid; @@ -1016,6 +1227,18 @@ SpotifyAccount::registerUpdaterForPlaylist( const QString& plId, SpotifyPlaylist m_updaters[ plId ] = updater; } +void +SpotifyAccount::registerPlaylistInfo( const QString& name, const QString& plid, const QString &revid, const bool sync, const bool subscribed ) +{ + m_allSpotifyPlaylists[ plid ] = new SpotifyPlaylistInfo( name, plid, revid, sync, subscribed ); +} + +void +SpotifyAccount::registerPlaylistInfo( SpotifyPlaylistInfo* info ) +{ + m_allSpotifyPlaylists[ info->plid ] = info; +} + void SpotifyAccount::unregisterUpdater( const QString& plid ) @@ -1051,6 +1274,7 @@ SpotifyAccount::stopPlaylistSync( SpotifyPlaylistInfo* playlist, bool forceDontD if ( m_updaters.contains( playlist->plid ) ) { + SpotifyPlaylistUpdater* updater = m_updaters[ playlist->plid ]; updater->setSync( false ); @@ -1084,14 +1308,14 @@ SpotifyAccount::loadPlaylists() void SpotifyAccount::setSyncForPlaylist( const QString& spotifyPlaylistId, bool sync ) { - foreach ( SpotifyPlaylistInfo* info, m_allSpotifyPlaylists ) - { - if( info->plid == spotifyPlaylistId ) - info->sync = sync; - } + SpotifyPlaylistInfo* info = m_allSpotifyPlaylists.value( spotifyPlaylistId, 0 ); + + if ( info ) + info->sync = sync; + if ( !m_configWidget.isNull() ) - m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists ); + m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists.values() ); } @@ -1101,11 +1325,20 @@ SpotifyAccount::createActions() if ( !m_customActions.isEmpty() ) return; - QAction* action = new QAction( 0 ); - action->setIcon( QIcon( RESPATH "images/spotify-logo.png" ) ); - connect( action, SIGNAL( triggered( bool ) ), this, SLOT( syncActionTriggered( bool ) ) ); - ActionCollection::instance()->addAction( ActionCollection::LocalPlaylists, action, this ); - m_customActions.append( action ); + QAction* syncAction = new QAction( 0 ); + syncAction->setIcon( QIcon( RESPATH "images/spotify-logo.png" ) ); + connect( syncAction, SIGNAL( triggered( bool ) ), this, SLOT( syncActionTriggered( bool ) ) ); + ActionCollection::instance()->addAction( ActionCollection::LocalPlaylists, syncAction, this ); + syncAction->setData( Sync); + m_customActions.append( syncAction ); + + QAction* subscribeAction = new QAction( 0 ); + subscribeAction->setIcon( QIcon( RESPATH "images/spotify-logo.png" ) ); + connect( subscribeAction, SIGNAL( triggered( bool ) ), this, SLOT( subscribeActionTriggered( bool ) ) ); + ActionCollection::instance()->addAction( ActionCollection::LocalPlaylists, subscribeAction, this ); + subscribeAction->setData( Subscribe ); + m_customActions.append( subscribeAction ); + } diff --git a/src/libtomahawk/accounts/spotify/SpotifyAccount.h b/src/libtomahawk/accounts/spotify/SpotifyAccount.h index e524baed4..c31bcff2d 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyAccount.h +++ b/src/libtomahawk/accounts/spotify/SpotifyAccount.h @@ -36,6 +36,8 @@ class ScriptResolver; namespace Tomahawk { +class SpotifyParser; + namespace InfoSystem { class SpotifyInfoPlugin; @@ -48,11 +50,11 @@ class SpotifyAccountConfig; // metadata for a playlist struct SpotifyPlaylistInfo { QString name, plid, revid; - bool sync, changed; + bool sync, subscribed, changed; - SpotifyPlaylistInfo( const QString& nname, const QString& pid, const QString& rrevid, bool ssync ) - : name( nname ), plid( pid ), revid( rrevid ), sync( ssync ), changed( false ) {} + SpotifyPlaylistInfo( const QString& nname, const QString& pid, const QString& rrevid, bool ssync, bool ssubscribed ) + : name( nname ), plid( pid ), revid( rrevid ), sync( ssync ), subscribed( ssubscribed ), changed( false ) {} SpotifyPlaylistInfo() : sync( false ), changed( false ) {} }; @@ -83,7 +85,7 @@ public: SpotifyAccount( const QString& accountId ); SpotifyAccount( const QString& accountId, const QString& path ); virtual ~SpotifyAccount(); - + static SpotifyAccount* instance(); virtual QPixmap icon() const; virtual QWidget* configurationWidget(); virtual QWidget* aboutWidget(); @@ -99,9 +101,10 @@ public: virtual SipPlugin* sipPlugin() { return 0; } virtual bool preventEnabling() const { return m_preventEnabling; } - QString sendMessage( const QVariantMap& msg, QObject* receiver = 0, const QString& slot = QString() ); void registerUpdaterForPlaylist( const QString& plId, SpotifyPlaylistUpdater* updater ); + void registerPlaylistInfo( const QString& name, const QString& plid, const QString &revid, const bool sync, const bool subscribed ); + void registerPlaylistInfo( SpotifyPlaylistInfo* info ); void unregisterUpdater( const QString& plid ); bool deleteOnUnsync() const; @@ -111,8 +114,11 @@ public: bool loggedIn() const; public slots: + QString sendMessage( const QVariantMap& msg, QObject* receiver = 0, const QString& slot = QString(), const QVariant& extraData = QVariant() ); + void aboutToShow( QAction* action, const Tomahawk::playlist_ptr& playlist ); void syncActionTriggered( bool ); + void subscribeActionTriggered( bool ); void atticaLoaded(Attica::Content::List); private slots: @@ -125,10 +131,10 @@ private slots: void logout(); // SpotifyResolver message handlers, all take msgtype, msg as argument - // void ( const QString& msgType, const QVariantMap& msg ); - void startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg ); - void playlistCreated( const QString& msgType, const QVariantMap& msg ); - + // void ( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); + void startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); + void playlistCreated( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); + void playlistCopyCreated( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); void delayedInit(); void hookupAfterDeletion( bool autoEnable ); @@ -146,9 +152,13 @@ private: void fetchFullPlaylist( SpotifyPlaylistInfo* playlist ); void setSyncForPlaylist( const QString& spotifyPlaylistId, bool sync ); + void setSubscribedForPlaylist( const playlist_ptr& pl, bool subscribed ); void createActions(); void removeActions(); + playlist_ptr playlistFromAction( QAction* action ) const; + + static SpotifyAccount* s_instance; QWeakPointer m_configWidget; QWeakPointer m_aboutWidget; @@ -156,9 +166,10 @@ private: QWeakPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin; QMap > m_qidToSlotMap; + QMap m_qidToExtraData; // List of synced spotify playlists in config UI - QList< SpotifyPlaylistInfo* > m_allSpotifyPlaylists; + QHash< QString, SpotifyPlaylistInfo* > m_allSpotifyPlaylists; QHash< QString, SpotifyPlaylistUpdater* > m_updaters; QHash< QString, playlist_ptr > m_waitingForCreateReply; @@ -167,6 +178,7 @@ private: SmartPointerList< QAction > m_customActions; friend class ::SpotifyPlaylistUpdater; + friend class Tomahawk::SpotifyParser; }; } diff --git a/src/libtomahawk/accounts/spotify/SpotifyAccountConfig.cpp b/src/libtomahawk/accounts/spotify/SpotifyAccountConfig.cpp index a91890abf..ec57e12e2 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyAccountConfig.cpp +++ b/src/libtomahawk/accounts/spotify/SpotifyAccountConfig.cpp @@ -41,6 +41,8 @@ SpotifyAccountConfig::SpotifyAccountConfig( SpotifyAccount *account ) { m_ui->setupUi( this ); + m_ui->loginButton->setDefault( true ); + connect( m_ui->loginButton, SIGNAL( clicked( bool ) ), this, SLOT( doLogin() ) ); connect( m_ui->usernameEdit, SIGNAL( textEdited( QString ) ), this, SLOT( resetLoginButton() ) ); diff --git a/src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.cpp b/src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.cpp index 297b93fe2..b16e24351 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.cpp +++ b/src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.cpp @@ -103,9 +103,10 @@ SpotifyInfoPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requ message[ "artist" ] = artist; message[ "album" ] = album; - const QString qid = m_account.data()->sendMessage( message, this, "albumListingResult" ); - - m_waitingForResults[ qid ] = requestData; + QMetaObject::invokeMethod( m_account.data(), "sendMessage", Qt::QueuedConnection, Q_ARG( QVariantMap, message ), + Q_ARG( QObject*, this ), + Q_ARG( QString, "albumListingResult" ), + Q_ARG( QVariant, QVariant::fromValue< InfoRequestData >( requestData ) ) ); } break; } @@ -119,15 +120,12 @@ SpotifyInfoPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requ void -SpotifyInfoPlugin::albumListingResult( const QString& msgType, const QVariantMap& msg ) +SpotifyInfoPlugin::albumListingResult( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ) { Q_ASSERT( msg.contains( "qid" ) ); - Q_ASSERT( m_waitingForResults.contains( msg.value( "qid" ).toString() ) ); + Q_ASSERT( extraData.canConvert< InfoRequestData >() ); - if ( !msg.contains( "qid" ) || !m_waitingForResults.contains( msg.value( "qid" ).toString() ) ) - return; - - const InfoRequestData requestData = m_waitingForResults.take( msg.value( "qid" ).toString() ); + const InfoRequestData requestData = extraData.value< InfoRequestData >(); QVariantList tracks = msg.value( "tracks" ).toList(); QStringList trackNameList; diff --git a/src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.h b/src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.h index fafc0cead..97c0b96ad 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.h +++ b/src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.h @@ -46,7 +46,7 @@ public: virtual ~SpotifyInfoPlugin(); public slots: - void albumListingResult( const QString& msgType, const QVariantMap& msg ); + void albumListingResult( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); protected slots: virtual void init() {} @@ -62,8 +62,6 @@ private: void dataError( InfoRequestData ); void trackListResult( const QStringList& trackNameList, const Tomahawk::InfoSystem::InfoRequestData& requestData ); - QHash< QString, InfoRequestData > m_waitingForResults; - QWeakPointer< Tomahawk::Accounts::SpotifyAccount > m_account; }; diff --git a/src/libtomahawk/accounts/spotify/SpotifyPlaylistUpdater.cpp b/src/libtomahawk/accounts/spotify/SpotifyPlaylistUpdater.cpp index 43ee8cf70..e2c4ab252 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyPlaylistUpdater.cpp +++ b/src/libtomahawk/accounts/spotify/SpotifyPlaylistUpdater.cpp @@ -1,6 +1,7 @@ /* === This file is part of Tomahawk Player - === * * Copyright 2010-2012, Leo Franchi + * Copyright 2012, Hugo Lindström * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,10 +58,14 @@ SpotifyUpdaterFactory::create( const Tomahawk::playlist_ptr& pl, const QVariantH const QString spotifyId = settings.value( "spotifyId" ).toString(); const QString latestRev = settings.value( "latestrev" ).toString(); const bool sync = settings.value( "sync" ).toBool(); + const bool canSubscribe = settings.value( "canSubscribe" ).toBool(); + const bool isSubscribed = settings.value( "subscribed" ).toBool(); Q_ASSERT( !spotifyId.isEmpty() ); SpotifyPlaylistUpdater* updater = new SpotifyPlaylistUpdater( m_account.data(), latestRev, spotifyId, pl ); updater->setSync( sync ); + updater->setCanSubscribe( canSubscribe ); + updater->setSubscribed( isSubscribed ); m_account.data()->registerUpdaterForPlaylist( spotifyId, updater ); return updater; @@ -74,6 +79,8 @@ SpotifyPlaylistUpdater::SpotifyPlaylistUpdater( SpotifyAccount* acct, const QStr , m_spotifyId( spotifyId ) , m_blockUpdatesForNextRevision( false ) , m_sync( false ) + , m_canSubscribe( false ) + , m_subscribed( false ) { init(); } @@ -126,12 +133,18 @@ SpotifyPlaylistUpdater::remove( bool askToDeletePlaylist ) void SpotifyPlaylistUpdater::aboutToDelete() { - if ( m_sync ) + if ( QThread::currentThread() != QApplication::instance()->thread() ) + QMetaObject::invokeMethod( const_cast(this), "aboutToDelete", Qt::BlockingQueuedConnection ); + else { - if ( QThread::currentThread() != QApplication::instance()->thread() ) - QMetaObject::invokeMethod( const_cast(this), "checkDeleteDialog", Qt::BlockingQueuedConnection ); - else - checkDeleteDialog(); + if ( m_subscribed ) + { + m_spotify.data()->setSubscribedForPlaylist( playlist(), false ); + } + else if ( m_sync ) + { + checkDeleteDialog(); + } } } @@ -177,6 +190,8 @@ SpotifyPlaylistUpdater::saveToSettings() s[ "latestrev" ] = m_latestRev; s[ "sync" ] = m_sync; + s[ "canSubscribe" ] = m_canSubscribe; + s[ "subscribed" ] = m_subscribed; s[ "spotifyId" ] = m_spotifyId; saveSettings( s ); @@ -227,6 +242,45 @@ SpotifyPlaylistUpdater::sync() const return m_sync; } +void +SpotifyPlaylistUpdater::setSubscribed( bool subscribed ) +{ + if ( m_subscribed == subscribed ) + return; + + m_subscribed = subscribed; + setSync( subscribed ); + saveToSettings(); + emit changed(); +} + + +bool +SpotifyPlaylistUpdater::subscribed() const +{ + return m_subscribed; +} + + +void +SpotifyPlaylistUpdater::setCanSubscribe( bool canSubscribe ) +{ + if ( m_canSubscribe == canSubscribe ) + return; + + m_canSubscribe = canSubscribe; + + saveToSettings(); + emit changed(); +} + + +bool +SpotifyPlaylistUpdater::canSubscribe() const +{ + return m_canSubscribe; +} + void SpotifyPlaylistUpdater::spotifyTracksAdded( const QVariantList& tracks, const QString& startPosId, const QString& newRev, const QString& oldRev ) @@ -353,6 +407,8 @@ SpotifyPlaylistUpdater::tomahawkPlaylistRenamed(const QString &newT, const QStri msg[ "newTitle" ] = newT; msg[ "oldTitle" ] = oldT; msg[ "playlistid" ] = m_spotifyId; + + // TODO check return value m_spotify.data()->sendMessage( msg, this, "onPlaylistRename" ); } @@ -493,7 +549,7 @@ SpotifyPlaylistUpdater::plentryToVariant( const QList< plentry_ptr >& entries ) void -SpotifyPlaylistUpdater::onTracksInsertedReturn( const QString& msgType, const QVariantMap& msg ) +SpotifyPlaylistUpdater::onTracksInsertedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& ) { const bool success = msg.value( "success" ).toBool(); @@ -577,7 +633,7 @@ SpotifyPlaylistUpdater::tomahawkTracksRemoved( const QList< query_ptr >& tracks void -SpotifyPlaylistUpdater::onTracksRemovedReturn( const QString& msgType, const QVariantMap& msg ) +SpotifyPlaylistUpdater::onTracksRemovedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& ) { const bool success = msg.value( "success" ).toBool(); @@ -626,7 +682,7 @@ SpotifyPlaylistUpdater::tomahawkTracksMoved( const QList< plentry_ptr >& tracks, void -SpotifyPlaylistUpdater::onTracksMovedReturn( const QString& msgType, const QVariantMap& msg ) +SpotifyPlaylistUpdater::onTracksMovedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& ) { const bool success = msg.value( "success" ).toBool(); @@ -678,8 +734,10 @@ SpotifyPlaylistUpdater::variantToQueries( const QVariantList& list ) continue; if ( trackMap.contains( "id" ) ) + { + q->setResultHint( trackMap.value( "id" ).toString() ); q->setProperty( "annotation", trackMap.value( "id" ) ); - + } queries << q; } diff --git a/src/libtomahawk/accounts/spotify/SpotifyPlaylistUpdater.h b/src/libtomahawk/accounts/spotify/SpotifyPlaylistUpdater.h index 896e507d3..b5de8e4b9 100644 --- a/src/libtomahawk/accounts/spotify/SpotifyPlaylistUpdater.h +++ b/src/libtomahawk/accounts/spotify/SpotifyPlaylistUpdater.h @@ -1,7 +1,8 @@ /* === This file is part of Tomahawk Player - === * * Copyright 2010-2012, Leo Franchi - * + * Copyright 2012, Hugo Lindström + * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -53,7 +54,10 @@ public: bool sync() const; void setSync( bool sync ); - + bool subscribed() const; + void setSubscribed( bool subscribed ); + bool canSubscribe() const; + void setCanSubscribe( bool canSub ); QString spotifyId() const { return m_spotifyId; } void remove( bool askToDeletePlaylist = true ); @@ -69,14 +73,13 @@ public slots: void tomahawkTracksMoved( const QList& ,int ); void tomahawkPlaylistRenamed( const QString&, const QString& ); -protected: void aboutToDelete(); - + private slots: // SpotifyResolver message handlers, all take msgtype, msg as argument - void onTracksInsertedReturn( const QString& msgType, const QVariantMap& msg ); - void onTracksRemovedReturn( const QString& msgType, const QVariantMap& msg ); - void onTracksMovedReturn( const QString& msgType, const QVariantMap& msg ); + void onTracksInsertedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); + void onTracksRemovedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); + void onTracksMovedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); void checkDeleteDialog() const; @@ -99,7 +102,8 @@ private: bool m_blockUpdatesForNextRevision; bool m_sync; - + bool m_subscribed; + bool m_canSubscribe; QQueue<_detail::Closure*> m_queuedOps; #ifndef ENABLE_HEADLESS static QPixmap* s_typePixmap; diff --git a/src/libtomahawk/audio/AudioEngine.cpp b/src/libtomahawk/audio/AudioEngine.cpp index 3b7d940ea..e8f07c45c 100644 --- a/src/libtomahawk/audio/AudioEngine.cpp +++ b/src/libtomahawk/audio/AudioEngine.cpp @@ -897,6 +897,9 @@ AudioEngine::checkStateQueue() m_mediaObject->pause(); break; } + + default: + break; } } else diff --git a/src/libtomahawk/database/IdThreadWorker.cpp b/src/libtomahawk/database/IdThreadWorker.cpp index a8ff77e14..3e9b3d268 100644 --- a/src/libtomahawk/database/IdThreadWorker.cpp +++ b/src/libtomahawk/database/IdThreadWorker.cpp @@ -87,6 +87,7 @@ internalGet( const artist_ptr& artist, const album_ptr& album, bool autoCreate, item->album = album; item->type = type; item->create = autoCreate; + item->promise.reportStarted(); return item; } diff --git a/src/libtomahawk/filemetadata/MetadataEditor.cpp b/src/libtomahawk/filemetadata/MetadataEditor.cpp index b881604e6..7611a5737 100644 --- a/src/libtomahawk/filemetadata/MetadataEditor.cpp +++ b/src/libtomahawk/filemetadata/MetadataEditor.cpp @@ -29,40 +29,50 @@ #include "Album.h" #include "Typedefs.h" #include "ScanManager.h" +#include "PlaylistInterface.h" +#include "AlbumPlaylistInterface.h" #include "taglib/fileref.h" #include "filemetadata/taghandlers/tag.h" #include "utils/TomahawkUtils.h" +#include "utils/Closure.h" MetadataEditor::MetadataEditor( const Tomahawk::result_ptr& result, QWidget* parent ) : QDialog( parent ) , ui( new Ui::MetadataEditor ) , m_result( result ) + , m_interface( 0 ) { ui->setupUi( this ); setWindowTitle( QString( result->track() + tr( " - Properties" ) ) ); setAttribute( Qt::WA_DeleteOnClose ); - setTitle( result->track() ); - setArtist( result->artist()->name() ); - setAlbum( result->album()->name() ); - setDiscNumber( result->albumpos() ); - setDuration( result->duration() ); - setYear( result->year() ); - setBitrate( result->bitrate() ); + NewClosure( ui->buttonBox, SIGNAL( accepted() ), + this, SLOT( writeMetadata( bool ) ), true )->setAutoDelete( false ); - QFileInfo fi( QUrl( m_result->url() ).toLocalFile() ); - setFileName( fi.fileName() ); - setFileSize( TomahawkUtils::filesizeToString( fi.size() ) ); - - connect( ui->buttonBox, SIGNAL( accepted() ), SLOT( writeMetadata() ) ); connect( ui->buttonBox, SIGNAL( rejected() ), SLOT( close() ) ); + connect( ui->forwardPushButton, SIGNAL( clicked() ), SLOT( loadNextResult() ) ); + connect( ui->previousPushButton, SIGNAL( clicked() ), SLOT( loadPreviousResult() ) ); + + m_interface = Tomahawk::playlistinterface_ptr( new Tomahawk::AlbumPlaylistInterface( + result->album().data(), + Tomahawk::DatabaseMode, + result->collection() ) ); + connect( m_interface.data(), + SIGNAL( tracksLoaded( Tomahawk::ModelMode, + const Tomahawk::collection_ptr& ) ), + SLOT( enablePushButtons() ) ); + + /* Initiate the interface */ + m_interface->tracks(); + + loadResult( result ); } void -MetadataEditor::writeMetadata() +MetadataEditor::writeMetadata( bool closeDlg ) { QFileInfo fi( QUrl( m_result->url() ).toLocalFile() ); @@ -102,9 +112,68 @@ MetadataEditor::writeMetadata() f.save(); - QStringList files = QStringList( fileName ); - ScanManager::instance()->runFileScan( files ); - close(); + m_editFiles.append( fileName ); + + if ( closeDlg ) { + ScanManager::instance()->runFileScan( m_editFiles ); + close(); + } +} + + +void +MetadataEditor::loadResult( const Tomahawk::result_ptr& result ) +{ + if ( result.isNull() ) + return; + + m_result = result; + setTitle( result->track() ); + setArtist( result->artist()->name() ); + setAlbum( result->album()->name() ); + setDiscNumber( result->albumpos() ); + setDuration( result->duration() ); + setYear( result->year() ); + setBitrate( result->bitrate() ); + + QFileInfo fi( QUrl( m_result->url() ).toLocalFile() ); + setFileName( fi.fileName() ); + setFileSize( TomahawkUtils::filesizeToString( fi.size() ) ); + + enablePushButtons(); +} + + +void MetadataEditor::enablePushButtons() +{ + if ( !m_interface->setCurrentTrack( m_result->albumpos() ) ) + tDebug() << "Error setting current track for MetadataEditor."; + + if ( m_interface->hasNextItem() ) + ui->forwardPushButton->setEnabled( true ); + else + ui->forwardPushButton->setEnabled( false ); + + if ( m_interface->hasPreviousItem() ) + ui->previousPushButton->setEnabled( true ); + else + ui->previousPushButton->setEnabled( false ); +} + + +void +MetadataEditor::loadNextResult() +{ + writeMetadata(); + loadResult( m_interface->nextItem() ); +} + + +void +MetadataEditor::loadPreviousResult() +{ + writeMetadata(); + loadResult( m_interface->previousItem() ); } diff --git a/src/libtomahawk/filemetadata/MetadataEditor.h b/src/libtomahawk/filemetadata/MetadataEditor.h index ccd743b92..641ca0049 100644 --- a/src/libtomahawk/filemetadata/MetadataEditor.h +++ b/src/libtomahawk/filemetadata/MetadataEditor.h @@ -45,9 +45,13 @@ protected: int discnumber() const { return ui->discNumberSpinBox->value(); } int year() const { return ui->yearSpinBox->value(); } int bitrate() const { return ui->bitrateSpinBox->value(); } + void loadResult( const Tomahawk::result_ptr& result ); private slots: - void writeMetadata(); + void writeMetadata( bool closeDlg = false ); + void enablePushButtons(); + void loadNextResult(); + void loadPreviousResult(); /* tag attributes */ void setTitle( const QString& title ); @@ -66,6 +70,8 @@ private: Ui::MetadataEditor* ui; Tomahawk::result_ptr m_result; + Tomahawk::playlistinterface_ptr m_interface; + QStringList m_editFiles; }; #endif // METADATAEDITOR_H diff --git a/src/libtomahawk/filemetadata/MetadataEditor.ui b/src/libtomahawk/filemetadata/MetadataEditor.ui index 1ded5959d..1f40bc41b 100644 --- a/src/libtomahawk/filemetadata/MetadataEditor.ui +++ b/src/libtomahawk/filemetadata/MetadataEditor.ui @@ -227,7 +227,7 @@ - + false @@ -237,7 +237,7 @@ - + false diff --git a/src/libtomahawk/jobview/JobStatusModel.cpp b/src/libtomahawk/jobview/JobStatusModel.cpp index 64ec73c05..1744a5d4b 100644 --- a/src/libtomahawk/jobview/JobStatusModel.cpp +++ b/src/libtomahawk/jobview/JobStatusModel.cpp @@ -110,7 +110,7 @@ JobStatusModel::~JobStatusModel() void JobStatusModel::addJob( JobStatusItem* item ) { - tLog() << Q_FUNC_INFO << "current jobs of item type: " << m_jobTypeCount[ item->type() ] << ", current queue size of item type: " << m_jobQueue[ item->type() ].size(); +// tLog() << Q_FUNC_INFO << "current jobs of item type: " << m_jobTypeCount[ item->type() ] << ", current queue size of item type: " << m_jobQueue[ item->type() ].size(); if ( item->concurrentJobLimit() > 0 ) { if ( m_jobTypeCount[ item->type() ] >= item->concurrentJobLimit() ) @@ -123,7 +123,7 @@ JobStatusModel::addJob( JobStatusItem* item ) m_jobTypeCount[ item->type() ] = currentJobCount; } - tLog() << Q_FUNC_INFO << "new current jobs of item type: " << m_jobTypeCount[ item->type() ]; +// tLog() << Q_FUNC_INFO << "new current jobs of item type: " << m_jobTypeCount[ item->type() ]; connect( item, SIGNAL( statusChanged() ), SLOT( itemUpdated() ) ); connect( item, SIGNAL( finished() ), SLOT( itemFinished() ) ); @@ -142,7 +142,7 @@ JobStatusModel::addJob( JobStatusItem* item ) } } - tLog() << Q_FUNC_INFO << "Adding item:" << item; +// tLog() << Q_FUNC_INFO << "Adding item:" << item; int currentEndRow = m_items.count(); beginInsertRows( QModelIndex(), currentEndRow, currentEndRow ); @@ -151,7 +151,7 @@ JobStatusModel::addJob( JobStatusItem* item ) if ( item->hasCustomDelegate() ) { - tLog() << Q_FUNC_INFO << "job has custom delegate"; +// tLog() << Q_FUNC_INFO << "job has custom delegate"; emit customDelegateJobInserted( currentEndRow, item ); } @@ -221,7 +221,7 @@ JobStatusModel::rowCount( const QModelIndex& parent ) const void JobStatusModel::itemFinished() { - tLog( LOGVERBOSE ) << Q_FUNC_INFO; +// tLog( LOGVERBOSE ) << Q_FUNC_INFO; JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() ); Q_ASSERT( item ); @@ -278,7 +278,7 @@ JobStatusModel::itemFinished() emit refreshDelegates(); - tLog() << Q_FUNC_INFO << "current jobs of item type: " << m_jobTypeCount[ item->type() ] << ", current queue size of item type: " << m_jobQueue[ item->type() ].size(); +// tLog() << Q_FUNC_INFO << "current jobs of item type: " << m_jobTypeCount[ item->type() ] << ", current queue size of item type: " << m_jobQueue[ item->type() ].size(); if ( item->concurrentJobLimit() > 0 ) { int currentJobs = m_jobTypeCount[ item->type() ]; @@ -299,7 +299,7 @@ JobStatusModel::itemFinished() void JobStatusModel::itemUpdated() { - tLog( LOGVERBOSE ) << Q_FUNC_INFO; +// tLog( LOGVERBOSE ) << Q_FUNC_INFO; JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() ); Q_ASSERT( item ); diff --git a/src/libtomahawk/jobview/JobStatusView.cpp b/src/libtomahawk/jobview/JobStatusView.cpp index 26254ebff..46acc4413 100644 --- a/src/libtomahawk/jobview/JobStatusView.cpp +++ b/src/libtomahawk/jobview/JobStatusView.cpp @@ -101,17 +101,14 @@ JobStatusView::setModel( JobStatusSortModel* m ) void JobStatusView::customDelegateJobInserted( int row, JobStatusItem* item ) { - tLog() << Q_FUNC_INFO << "item is" << item << ", row is" << row; if ( !item ) return; item->createDelegate( m_view ); - tLog() << Q_FUNC_INFO << "item delegate is" << item->customDelegate(); m_view->setItemDelegateForRow( row, item->customDelegate() ); ACLJobDelegate* delegate = qobject_cast< ACLJobDelegate* >( item->customDelegate() ); if ( delegate ) { - tLog() << Q_FUNC_INFO << "delegate found"; connect( delegate, SIGNAL( update( const QModelIndex& ) ), m_view, SLOT( update( const QModelIndex & ) ) ); connect( delegate, SIGNAL( aclResult( ACLRegistry::ACL ) ), item, SLOT( aclResult( ACLRegistry::ACL ) ) ); delegate->emitSizeHintChanged( m_model->index( row, 0 ) ); @@ -126,7 +123,6 @@ JobStatusView::customDelegateJobInserted( int row, JobStatusItem* item ) void JobStatusView::customDelegateJobRemoved( int row ) { - tLog() << Q_FUNC_INFO << "row is" << row; checkCount(); } @@ -134,11 +130,9 @@ JobStatusView::customDelegateJobRemoved( int row ) void JobStatusView::refreshDelegates() { - tLog() << Q_FUNC_INFO; int count = m_model->rowCount(); for ( int i = 0; i < count; i++ ) { - tLog() << Q_FUNC_INFO << "checking row" << i; QModelIndex index = m_model->index( i, 0 ); QVariant itemVar = index.data( JobStatusModel::JobDataRole ); if ( !itemVar.canConvert< JobStatusItem* >() || !itemVar.value< JobStatusItem* >() ) diff --git a/src/libtomahawk/playlist/CustomPlaylistView.cpp b/src/libtomahawk/playlist/CustomPlaylistView.cpp deleted file mode 100644 index f29bac29b..000000000 --- a/src/libtomahawk/playlist/CustomPlaylistView.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* === This file is part of Tomahawk Player - === - * - * Copyright 2010-2011, Leo Franchi - * - * Tomahawk is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tomahawk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tomahawk. If not, see . - */ - - -#include "CustomPlaylistView.h" - -#include "database/DatabaseCommand_GenericSelect.h" -#include "database/Database.h" -#include "utils/TomahawkUtils.h" -#include "SourceList.h" -#include "audio/AudioEngine.h" - -using namespace Tomahawk; - -CustomPlaylistView::CustomPlaylistView( CustomPlaylistView::PlaylistType type, const source_ptr& s, QWidget* parent ) - : PlaylistView( parent ) - , m_type( type ) - , m_source( s ) - , m_model( new PlaylistModel( this ) ) -{ - // Generate the tracks, add them to the playlist - proxyModel()->setStyle( PlayableProxyModel::Large ); - - setPlaylistModel( m_model ); - generateTracks(); - - if ( m_type == SourceLovedTracks ) - { - connect( m_source.data(), SIGNAL( socialAttributesChanged( QString ) ), SLOT( socialAttributesChanged( QString ) ) ); - } - else if ( m_type == TopLovedTracks ) - { - connect( SourceList::instance()->getLocal().data(), SIGNAL( socialAttributesChanged( QString ) ), SLOT( socialAttributesChanged( QString ) ) ); - foreach ( const source_ptr& s, SourceList::instance()->sources( true ) ) - connect( s.data(), SIGNAL( socialAttributesChanged( QString ) ), SLOT( socialAttributesChanged( QString ) ) ); - - connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( sourceAdded( Tomahawk::source_ptr ) ) ); - } -} - - -CustomPlaylistView::~CustomPlaylistView() -{ -} - - -bool -CustomPlaylistView::isBeingPlayed() const -{ - return AudioEngine::instance()->currentTrackPlaylist() == playlistInterface(); -} - - -bool -CustomPlaylistView::jumpToCurrentTrack() -{ - return PlaylistView::jumpToCurrentTrack(); -} - - -void -CustomPlaylistView::generateTracks() -{ - m_model->startLoading(); - - QString sql; - switch ( m_type ) - { - // TODO - case SourceLovedTracks: - sql = QString( "SELECT track.name, artist.name, COUNT(*) as counter " - "FROM social_attributes, track, artist " - "WHERE social_attributes.id = track.id AND artist.id = track.artist AND social_attributes.k = 'Love' AND social_attributes.v = 'true' AND social_attributes.source %1 " - "GROUP BY track.id " - "ORDER BY counter DESC, social_attributes.timestamp DESC " ).arg( m_source->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_source->id() ) ); - break; - case TopLovedTracks: - sql = QString( "SELECT track.name, artist.name, source, COUNT(*) as counter " - "FROM social_attributes, track, artist " - "WHERE social_attributes.id = track.id AND artist.id = track.artist AND social_attributes.k = 'Love' AND social_attributes.v = 'true' " - "GROUP BY track.id " - "ORDER BY counter DESC, social_attributes.timestamp DESC LIMIT 0, 50" ); - break; - } - - DatabaseCommand_GenericSelect* cmd = new DatabaseCommand_GenericSelect( sql, DatabaseCommand_GenericSelect::Track, -1, 0 ); - connect( cmd, SIGNAL( tracks( QList ) ), this, SLOT( tracksGenerated( QList ) ) ); - Database::instance()->enqueue( QSharedPointer( cmd ) ); -} - - -void -CustomPlaylistView::tracksGenerated( QList< query_ptr > tracks ) -{ - bool changed = false; - QList< query_ptr > newTracks = TomahawkUtils::mergePlaylistChanges( m_model->queries(), tracks, changed ); - - m_model->finishLoading(); - if ( !changed ) - return; - - m_model->clear(); - m_model->appendQueries( newTracks ); -} - - -QString -CustomPlaylistView::title() const -{ - if ( m_source.isNull() ) - return tr( "Top Loved Tracks" ); - else - { - if ( m_source->isLocal() ) - return tr( "Your loved tracks" ); - else - return tr( "%1's loved tracks" ).arg( m_source->friendlyName() ); - } -} - - -QString -CustomPlaylistView::description() const -{ - if ( m_source.isNull() ) - return tr( "The most loved tracks from all your friends" ); - else - { - if ( m_source->isLocal() ) - return tr( "All of your loved tracks" ); - else - return tr( "All of %1's loved tracks" ).arg( m_source->friendlyName() ); - } -} - - -QString -CustomPlaylistView::longDescription() const -{ - return QString(); -} - - -QPixmap -CustomPlaylistView::pixmap() const -{ - return QPixmap( RESPATH "images/loved_playlist.png" ); -} - - -void -CustomPlaylistView::socialAttributesChanged( const QString& action ) -{ - if ( action == "Love" ) - { - generateTracks(); - } -} - - -void -CustomPlaylistView::sourceAdded( const source_ptr& s ) -{ - connect( s.data(), SIGNAL( socialAttributesChanged( QString ) ), this, SLOT( socialAttributesChanged( QString ) ) ); -} diff --git a/src/libtomahawk/playlist/CustomPlaylistView.h b/src/libtomahawk/playlist/CustomPlaylistView.h deleted file mode 100644 index 8ea0c828a..000000000 --- a/src/libtomahawk/playlist/CustomPlaylistView.h +++ /dev/null @@ -1,70 +0,0 @@ -/* === This file is part of Tomahawk Player - === - * - * Copyright 2010-2011, Leo Franchi - * - * Tomahawk is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tomahawk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tomahawk. If not, see . - */ - - -#ifndef CUSTOMPLAYLISTVIEW_H -#define CUSTOMPLAYLISTVIEW_H - -#include "PlaylistView.h" - -#include "DllMacro.h" - -namespace Tomahawk -{ - -class DLLEXPORT CustomPlaylistView : public PlaylistView -{ - Q_OBJECT -public: - enum PlaylistType - { - SourceLovedTracks, - TopLovedTracks - }; - - explicit CustomPlaylistView( PlaylistType type, const source_ptr& s, QWidget* parent = 0 ); - virtual ~CustomPlaylistView(); - - virtual bool showFilter() const { return true; } - - virtual QString title() const; - virtual QPixmap pixmap() const; - virtual QString description() const; - virtual QString longDescription() const; - - virtual bool isTemporaryPage() const { return false; } - virtual bool isBeingPlayed() const; - virtual bool jumpToCurrentTrack(); - -private slots: - void tracksGenerated( QList tracks ); - - void socialAttributesChanged( const QString& ); - void sourceAdded( const Tomahawk::source_ptr& ); - -private: - void generateTracks(); - - PlaylistType m_type; - source_ptr m_source; - PlaylistModel* m_model; -}; - -} - -#endif // CUSTOMPLAYLISTVIEW_H diff --git a/src/libtomahawk/playlist/FlexibleHeader.cpp b/src/libtomahawk/playlist/FlexibleHeader.cpp new file mode 100644 index 000000000..e58a2ea02 --- /dev/null +++ b/src/libtomahawk/playlist/FlexibleHeader.cpp @@ -0,0 +1,156 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "FlexibleHeader.h" +#include "ui_PlaylistHeader.h" + +#include +#include +#include +#include +#include + +#include "playlist/FlexibleView.h" +#include "ViewManager.h" +#include "thirdparty/Qocoa/qsearchfield.h" +#include "utils/Closure.h" +#include "utils/TomahawkUtilsGui.h" +#include "utils/Logger.h" +#include "widgets/QueryLabel.h" +#include "Source.h" + +using namespace Tomahawk; + + +FlexibleHeader::FlexibleHeader( FlexibleView* parent ) + : QWidget( parent ) + , m_parent( parent ) + , ui( new Ui::PlaylistHeader ) +{ + ui->setupUi( this ); + + QPalette pal = palette(); + pal.setColor( QPalette::Foreground, Qt::white ); + + ui->captionLabel->setPalette( pal ); + ui->descLabel->setPalette( pal ); + + QFont font = ui->captionLabel->font(); + font.setPixelSize( 16 ); + font.setBold( true ); + ui->captionLabel->setFont( font ); + + font.setPixelSize( 11 ); + ui->descLabel->setFont( font ); + + ui->radioNormal->setFocusPolicy( Qt::NoFocus ); + ui->radioDetailed->setFocusPolicy( Qt::NoFocus ); + ui->radioCloud->setFocusPolicy( Qt::NoFocus ); + + QFile f( RESPATH "stylesheets/topbar-radiobuttons.css" ); + f.open( QFile::ReadOnly ); + QString css = QString::fromAscii( f.readAll() ); + f.close(); + + ui->modeWidget->setStyleSheet( css ); + + ui->radioNormal->setChecked( true ); + ui->filter->setPlaceholderText( tr( "Filter..." ) ); + + pal = palette(); + pal.setColor( QPalette::Window, QColor( "#454e59" ) ); + + setPalette( pal ); + setAutoFillBackground( true ); + + connect( &m_filterTimer, SIGNAL( timeout() ), SLOT( applyFilter() ) ); + connect( ui->filter, SIGNAL( textChanged( QString ) ), SLOT( onFilterEdited() ) ); + + NewClosure( ui->radioNormal, SIGNAL( clicked() ), const_cast< FlexibleView* >( parent ), SLOT( setCurrentMode( FlexibleViewMode ) ), FlexibleView::Flat )->setAutoDelete( false ); + NewClosure( ui->radioDetailed, SIGNAL( clicked() ), const_cast< FlexibleView* >( parent ), SLOT( setCurrentMode( FlexibleViewMode ) ), FlexibleView::Detailed )->setAutoDelete( false ); + NewClosure( ui->radioCloud, SIGNAL( clicked() ), const_cast< FlexibleView* >( parent ), SLOT( setCurrentMode( FlexibleViewMode ) ), FlexibleView::Grid )->setAutoDelete( false ); +} + + +FlexibleHeader::~FlexibleHeader() +{ + delete ui; +} + + +void +FlexibleHeader::setCaption( const QString& s ) +{ + ui->captionLabel->setText( s ); +} + + +void +FlexibleHeader::setDescription( const QString& s ) +{ + ui->descLabel->setText( s ); +} + + +void +FlexibleHeader::setPixmap( const QPixmap& p ) +{ + ui->imageLabel->setPixmap( p.scaledToHeight( ui->imageLabel->height(), Qt::SmoothTransformation ) ); +} + + +void +FlexibleHeader::setFilter( const QString& filter ) +{ + ui->filter->setText( filter ); +} + + +void +FlexibleHeader::onFilterEdited() +{ + m_filter = ui->filter->text(); + + m_filterTimer.stop(); + m_filterTimer.setInterval( 280 ); + m_filterTimer.setSingleShot( true ); + m_filterTimer.start(); +} + + +void +FlexibleHeader::applyFilter() +{ + emit filterTextChanged( ui->filter->text() ); +} + + +void +FlexibleHeader::changeEvent( QEvent* e ) +{ + QWidget::changeEvent( e ); + switch ( e->type() ) + { + case QEvent::LanguageChange: +// ui->retranslateUi( this ); + break; + + default: + break; + } +} diff --git a/src/libtomahawk/playlist/FlexibleHeader.h b/src/libtomahawk/playlist/FlexibleHeader.h new file mode 100644 index 000000000..623293cec --- /dev/null +++ b/src/libtomahawk/playlist/FlexibleHeader.h @@ -0,0 +1,68 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef FLEXIBLEHEADER_H +#define FLEXIBLEHEADER_H + +#include +#include + +#include "DllMacro.h" +#include "Artist.h" + +class FlexibleView; + +namespace Ui +{ + class PlaylistHeader; +} + +class DLLEXPORT FlexibleHeader : public QWidget +{ +Q_OBJECT + +public: + FlexibleHeader( FlexibleView* parent ); + ~FlexibleHeader(); + +public slots: + void setCaption( const QString& s ); + void setDescription( const QString& s ); + void setPixmap( const QPixmap& p ); + + void setFilter( const QString& filter ); + +signals: + void filterTextChanged( const QString& filter ); + +protected: + void changeEvent( QEvent* e ); + +private slots: + void onFilterEdited(); + void applyFilter(); + +private: + FlexibleView* m_parent; + Ui::PlaylistHeader* ui; + + QString m_filter; + QTimer m_filterTimer; +}; + +#endif diff --git a/src/libtomahawk/playlist/FlexibleView.cpp b/src/libtomahawk/playlist/FlexibleView.cpp index faf09383d..3a6d7534d 100644 --- a/src/libtomahawk/playlist/FlexibleView.cpp +++ b/src/libtomahawk/playlist/FlexibleView.cpp @@ -22,11 +22,11 @@ #include #include +#include "playlist/FlexibleHeader.h" #include "playlist/PlayableModel.h" #include "playlist/TrackView.h" #include "playlist/GridView.h" #include "playlist/PlaylistLargeItemDelegate.h" -#include "utils/Closure.h" #include "utils/TomahawkUtilsGui.h" #include "utils/Logger.h" @@ -35,6 +35,7 @@ using namespace Tomahawk; FlexibleView::FlexibleView( QWidget* parent ) : QWidget( parent ) + , m_header( new FlexibleHeader( this ) ) , m_trackView( new TrackView() ) , m_detailedView( new TrackView() ) , m_gridView( new GridView() ) @@ -51,54 +52,16 @@ FlexibleView::FlexibleView( QWidget* parent ) setLayout( new QVBoxLayout() ); TomahawkUtils::unmarginLayout( layout() ); - QWidget* modeBar = new QWidget(); - modeBar->setLayout( new QHBoxLayout() ); - TomahawkUtils::unmarginLayout( modeBar->layout() ); - - QWidget* modeWidget = new QWidget(); - modeWidget->setLayout( new QHBoxLayout() ); - modeWidget->setFixedSize( QSize( 87, 30 ) ); - TomahawkUtils::unmarginLayout( modeWidget->layout() ); - - QRadioButton* radioNormal = new QRadioButton(); - radioNormal->setObjectName( "radioNormal" ); - QRadioButton* radioDetailed = new QRadioButton(); - radioDetailed->setObjectName( "radioDetailed" ); - QRadioButton* radioCloud = new QRadioButton(); - radioCloud->setObjectName( "radioCloud" ); - - radioNormal->setFocusPolicy( Qt::NoFocus ); - radioDetailed->setFocusPolicy( Qt::NoFocus ); - radioCloud->setFocusPolicy( Qt::NoFocus ); - - QFile f( RESPATH "stylesheets/topbar-radiobuttons.css" ); - f.open( QFile::ReadOnly ); - QString css = QString::fromAscii( f.readAll() ); - f.close(); - - modeWidget->setStyleSheet( css ); - modeWidget->layout()->addWidget( radioNormal ); - modeWidget->layout()->addWidget( radioDetailed ); - modeWidget->layout()->addWidget( radioCloud ); - modeWidget->layout()->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - - modeBar->layout()->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - modeBar->layout()->addWidget( modeWidget ); - modeBar->layout()->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - - layout()->addWidget( modeBar ); + layout()->addWidget( m_header ); layout()->addWidget( m_stack ); m_stack->addWidget( m_trackView ); m_stack->addWidget( m_detailedView ); m_stack->addWidget( m_gridView ); - radioNormal->setChecked( true ); setCurrentMode( Flat ); - NewClosure( radioNormal, SIGNAL( clicked() ), const_cast< FlexibleView* >( this ), SLOT( setCurrentMode( FlexibleViewMode ) ), Flat )->setAutoDelete( false ); - NewClosure( radioDetailed, SIGNAL( clicked() ), const_cast< FlexibleView* >( this ), SLOT( setCurrentMode( FlexibleViewMode ) ), Detailed )->setAutoDelete( false ); - NewClosure( radioCloud, SIGNAL( clicked() ), const_cast< FlexibleView* >( this ), SLOT( setCurrentMode( FlexibleViewMode ) ), Grid )->setAutoDelete( false ); + connect( m_header, SIGNAL( filterTextChanged( QString ) ), SLOT( setFilter( QString ) ) ); } @@ -166,6 +129,10 @@ FlexibleView::setPlayableModel( PlayableModel* model ) m_trackView->proxyModel()->sort( -1 ); m_detailedView->proxyModel()->sort( -1 ); m_gridView->proxyModel()->sort( -1 ); + + m_header->setPixmap( m_pixmap ); + m_header->setCaption( model->title() ); + m_header->setDescription( model->description() ); } @@ -223,7 +190,7 @@ FlexibleView::description() const QPixmap FlexibleView::pixmap() const { - return m_trackView->pixmap(); + return m_pixmap; } @@ -238,13 +205,30 @@ FlexibleView::jumpToCurrentTrack() bool -FlexibleView::setFilter( const QString& filter ) +FlexibleView::setFilter( const QString& pattern ) { - ViewPage::setFilter( filter ); + ViewPage::setFilter( pattern ); - m_trackView->setFilter( filter ); - m_detailedView->setFilter( filter ); - m_gridView->setFilter( filter ); + m_trackView->setFilter( pattern ); + m_detailedView->setFilter( pattern ); + m_gridView->setFilter( pattern ); return true; } + + +void +FlexibleView::setEmptyTip( const QString& tip ) +{ + m_trackView->setEmptyTip( tip ); + m_detailedView->setEmptyTip( tip ); + m_gridView->setEmptyTip( tip ); +} + + +void +FlexibleView::setPixmap( const QPixmap& pixmap ) +{ + m_pixmap = pixmap; + m_header->setPixmap( pixmap ); +} diff --git a/src/libtomahawk/playlist/FlexibleView.h b/src/libtomahawk/playlist/FlexibleView.h index a18ab0ea9..3b502643a 100644 --- a/src/libtomahawk/playlist/FlexibleView.h +++ b/src/libtomahawk/playlist/FlexibleView.h @@ -28,6 +28,7 @@ class QStackedWidget; class GridView; class TrackView; class PlayableModel; +class FlexibleHeader; class DLLEXPORT FlexibleView : public QWidget, public Tomahawk::ViewPage { @@ -47,23 +48,34 @@ public: virtual QString description() const; virtual QPixmap pixmap() const; - virtual bool showFilter() const { return true; } - virtual bool setFilter( const QString& filter ); + virtual bool showInfoBar() const { return false; } virtual bool jumpToCurrentTrack(); + TrackView* trackView() const { return m_trackView; } + TrackView* detailedView() const { return m_detailedView; } + GridView* gridView() const { return m_gridView; } + void setTrackView( TrackView* view ); void setDetailedView( TrackView* view ); void setGridView( GridView* view ); + void setPixmap( const QPixmap& pixmap ); void setPlayableModel( PlayableModel* model ); + void setEmptyTip( const QString& tip ); public slots: void setCurrentMode( FlexibleViewMode mode ); + virtual bool setFilter( const QString& pattern ); signals: void modeChanged( FlexibleViewMode mode ); +private slots: + private: + FlexibleHeader* m_header; + QPixmap m_pixmap; + TrackView* m_trackView; TrackView* m_detailedView; GridView* m_gridView; diff --git a/src/libtomahawk/playlist/LovedTracksModel.cpp b/src/libtomahawk/playlist/LovedTracksModel.cpp new file mode 100644 index 000000000..b0552d76e --- /dev/null +++ b/src/libtomahawk/playlist/LovedTracksModel.cpp @@ -0,0 +1,133 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2012, Christian Muehlhaeuser + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "LovedTracksModel.h" + +#include +#include + +#include "Source.h" +#include "SourceList.h" +#include "database/Database.h" +#include "database/DatabaseCommand_GenericSelect.h" +#include "PlayableItem.h" +#include "utils/TomahawkUtils.h" +#include "utils/Logger.h" + +#define LOVED_TRACK_ITEMS 25 + +using namespace Tomahawk; + + +LovedTracksModel::LovedTracksModel( QObject* parent ) + : PlaylistModel( parent ) + , m_limit( LOVED_TRACK_ITEMS ) +{ +} + + +LovedTracksModel::~LovedTracksModel() +{ +} + + +void +LovedTracksModel::loadTracks() +{ + if ( rowCount( QModelIndex() ) ) + { + clear(); + } + startLoading(); + + QString sql; + if ( m_source.isNull() ) + { + sql = QString( "SELECT track.name, artist.name, source, COUNT(*) as counter " + "FROM social_attributes, track, artist " + "WHERE social_attributes.id = track.id AND artist.id = track.artist AND social_attributes.k = 'Love' AND social_attributes.v = 'true' " + "GROUP BY track.id " + "ORDER BY counter DESC, social_attributes.timestamp DESC LIMIT 0, 50" ); + } + else + { + sql = QString( "SELECT track.name, artist.name, COUNT(*) as counter " + "FROM social_attributes, track, artist " + "WHERE social_attributes.id = track.id AND artist.id = track.artist AND social_attributes.k = 'Love' AND social_attributes.v = 'true' AND social_attributes.source %1 " + "GROUP BY track.id " + "ORDER BY counter DESC, social_attributes.timestamp DESC " ).arg( m_source->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_source->id() ) ); + } + + DatabaseCommand_GenericSelect* cmd = new DatabaseCommand_GenericSelect( sql, DatabaseCommand_GenericSelect::Track, -1, 0 ); + connect( cmd, SIGNAL( tracks( QList ) ), this, SLOT( appendQueries( QList ) ) ); + Database::instance()->enqueue( QSharedPointer( cmd ) ); +} + + +void +LovedTracksModel::onSourcesReady() +{ + Q_ASSERT( m_source.isNull() ); + + loadTracks(); + + foreach ( const source_ptr& source, SourceList::instance()->sources() ) + onSourceAdded( source ); +} + + +void +LovedTracksModel::setSource( const Tomahawk::source_ptr& source ) +{ + m_source = source; + if ( source.isNull() ) + { + if ( SourceList::instance()->isReady() ) + onSourcesReady(); + else + connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) ); + + connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) ); + } + else + { + onSourceAdded( source ); + loadTracks(); + } +} + + +void +LovedTracksModel::onSourceAdded( const Tomahawk::source_ptr& source ) +{ + connect( source.data(), SIGNAL( socialAttributesChanged( QString ) ), SLOT( onTrackLoved() ), Qt::UniqueConnection ); +} + + +void +LovedTracksModel::onTrackLoved() +{ + loadTracks(); +} + + +bool +LovedTracksModel::isTemporary() const +{ + return true; +} diff --git a/src/libtomahawk/playlist/LovedTracksModel.h b/src/libtomahawk/playlist/LovedTracksModel.h new file mode 100644 index 000000000..6b3b40d1d --- /dev/null +++ b/src/libtomahawk/playlist/LovedTracksModel.h @@ -0,0 +1,58 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef LOVEDTRACKSMODEL_H +#define LOVEDTRACKSMODEL_H + +#include +#include + +#include "Typedefs.h" +#include "PlaylistModel.h" + +#include "DllMacro.h" + +class DLLEXPORT LovedTracksModel : public PlaylistModel +{ +Q_OBJECT + +public: + explicit LovedTracksModel( QObject* parent = 0 ); + ~LovedTracksModel(); + + unsigned int limit() const { return m_limit; } + void setLimit( unsigned int limit ) { m_limit = limit; } + + bool isTemporary() const; + +public slots: + void setSource( const Tomahawk::source_ptr& source ); + +private slots: + void onSourcesReady(); + void onSourceAdded( const Tomahawk::source_ptr& source ); + + void onTrackLoved(); + void loadTracks(); + +private: + Tomahawk::source_ptr m_source; + unsigned int m_limit; +}; + +#endif // LOVEDTRACKSMODEL_H diff --git a/src/libtomahawk/playlist/PlaylistHeader.ui b/src/libtomahawk/playlist/PlaylistHeader.ui new file mode 100644 index 000000000..a55ea5fd7 --- /dev/null +++ b/src/libtomahawk/playlist/PlaylistHeader.ui @@ -0,0 +1,282 @@ + + + PlaylistHeader + + + + 0 + 0 + 774 + 80 + + + + + 0 + 0 + + + + + 0 + 72 + + + + InfoBar + + + + 8 + + + + + + 0 + 0 + + + + + 64 + 64 + + + + + 64 + 64 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 16 + 20 + + + + + + + + 0 + + + 0 + + + 2 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Caption + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Description + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 156 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 87 + 30 + + + + + 87 + 30 + + + + + 0 + + + 0 + + + + + RadioButton + + + + + + + RadioButton + + + + + + + RadioButton + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 16 + 20 + + + + + + + + + 0 + 0 + + + + + 220 + 0 + + + + + 220 + 16777215 + + + + + + + + + ElidedLabel + QLabel +
widgets/ElidedLabel.h
+
+ + QSearchField + QLineEdit +
thirdparty/Qocoa/qsearchfield.h
+
+
+ + +
diff --git a/src/libtomahawk/playlist/QueueProxyModel.cpp b/src/libtomahawk/playlist/QueueProxyModel.cpp index 78a0f7cb0..c2023642a 100644 --- a/src/libtomahawk/playlist/QueueProxyModel.cpp +++ b/src/libtomahawk/playlist/QueueProxyModel.cpp @@ -33,7 +33,6 @@ QueueProxyModel::QueueProxyModel( TrackView* parent ) : PlayableProxyModel( parent ) { connect( parent, SIGNAL( itemActivated( QModelIndex ) ), SLOT( onIndexActivated( QModelIndex ) ) ); - connect( playlistInterface().data(), SIGNAL( sourceTrackCountChanged( unsigned int ) ), SLOT( onTrackCountChanged( unsigned int ) ) ); connect( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ) ); } @@ -52,7 +51,11 @@ QueueProxyModel::onPlaybackStarted( const Tomahawk::result_ptr& result ) PlayableItem* item = itemFromIndex( mapToSource( idx ) ); if ( item && item->query() && ( item->query()->results().contains( result ) || item->query()->equals( result->toQuery() ) ) ) + { removeIndex( idx ); + if ( !rowCount() ) + ViewManager::instance()->hideQueue(); + } } } @@ -62,12 +65,7 @@ QueueProxyModel::onIndexActivated( const QModelIndex& index ) { setCurrentIndex( QModelIndex() ); removeIndex( index ); -} - -void -QueueProxyModel::onTrackCountChanged( unsigned int count ) -{ - if ( count == 0 ) + if ( !rowCount() ) ViewManager::instance()->hideQueue(); } diff --git a/src/libtomahawk/playlist/QueueProxyModel.h b/src/libtomahawk/playlist/QueueProxyModel.h index 3c39a68dc..f2755a03a 100644 --- a/src/libtomahawk/playlist/QueueProxyModel.h +++ b/src/libtomahawk/playlist/QueueProxyModel.h @@ -37,7 +37,6 @@ public: private slots: void onIndexActivated( const QModelIndex& index ); - void onTrackCountChanged( unsigned int count ); void onPlaybackStarted( const Tomahawk::result_ptr& result ); }; diff --git a/src/libtomahawk/playlist/TreeProxyModel.cpp b/src/libtomahawk/playlist/TreeProxyModel.cpp index d95232261..5cf9d2a1f 100644 --- a/src/libtomahawk/playlist/TreeProxyModel.cpp +++ b/src/libtomahawk/playlist/TreeProxyModel.cpp @@ -204,7 +204,7 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent PlayableItem* ti = sourceModel()->itemFromIndex( sourceModel()->index( i, 0, sourceParent ) ); - if ( ti && ti->name() == item->name() ) + if ( ti && ti->name() == item->name() && !ti->query().isNull() ) { if ( ti->query()->albumpos() == item->query()->albumpos() || ti->query()->albumpos() == 0 || item->query()->albumpos() == 0 ) { diff --git a/src/libtomahawk/resolvers/ScriptResolver.cpp b/src/libtomahawk/resolvers/ScriptResolver.cpp index ebfd79672..b5d5742cc 100644 --- a/src/libtomahawk/resolvers/ScriptResolver.cpp +++ b/src/libtomahawk/resolvers/ScriptResolver.cpp @@ -353,6 +353,9 @@ ScriptResolver::resolve( const Tomahawk::query_ptr& query ) m.insert( "artist", query->artist() ); m.insert( "track", query->track() ); m.insert( "qid", query->id() ); + + if ( !query->resultHint().isEmpty() ) + m.insert( "resultHint", query->resultHint() ); } const QByteArray msg = m_serializer.serialize( QVariant( m ) ); diff --git a/src/libtomahawk/utils/SpotifyParser.cpp b/src/libtomahawk/utils/SpotifyParser.cpp index 7c37e1ed2..d312934c2 100644 --- a/src/libtomahawk/utils/SpotifyParser.cpp +++ b/src/libtomahawk/utils/SpotifyParser.cpp @@ -97,31 +97,50 @@ void SpotifyParser::lookupSpotifyBrowse( const QString& linkRaw ) { tLog() << "Parsing Spotify Browse URI:" << linkRaw; - QString browseUri = linkRaw; - if ( browseUri.contains( "open.spotify.com/" ) ) // convert to a URI + m_browseUri = linkRaw; + + if ( m_browseUri.contains( "open.spotify.com/" ) ) // convert to a URI { - browseUri.replace( "http://open.spotify.com/", "" ); - browseUri.replace( "/", ":" ); - browseUri = "spotify:" + browseUri; + m_browseUri.replace( "http://open.spotify.com/", "" ); + m_browseUri.replace( "/", ":" ); + m_browseUri = "spotify:" + m_browseUri; + } + + if ( m_browseUri.contains( "playlist" ) && + Tomahawk::Accounts::SpotifyAccount::instance() != 0 && + Tomahawk::Accounts::SpotifyAccount::instance()->loggedIn() ) + { + // Do a playlist lookup locally + // Running resolver, so do the lookup through that + qDebug() << Q_FUNC_INFO << "Doing playlist lookup through spotify resolver:" << m_browseUri; + QVariantMap message; + message[ "_msgtype" ] = "playlistListing"; + message[ "id" ] = m_browseUri; + + QMetaObject::invokeMethod( Tomahawk::Accounts::SpotifyAccount::instance(), "sendMessage", Qt::QueuedConnection, Q_ARG( QVariantMap, message ), + Q_ARG( QObject*, this ), + Q_ARG( QString, "playlistListingResult" ) ); + + return; } DropJob::DropType type; - if ( browseUri.contains( "spotify:user" ) ) + if ( m_browseUri.contains( "spotify:user" ) ) type = DropJob::Playlist; - if ( browseUri.contains( "spotify:artist" ) ) + if ( m_browseUri.contains( "spotify:artist" ) ) type = DropJob::Artist; - if ( browseUri.contains( "spotify:album" ) ) + if ( m_browseUri.contains( "spotify:album" ) ) type = DropJob::Album; - if ( browseUri.contains( "spotify:track" ) ) + if ( m_browseUri.contains( "spotify:track" ) ) type = DropJob::Track; QUrl url; if( type != DropJob::Artist ) - url = QUrl( QString( SPOTIFY_PLAYLIST_API_URL "/browse/%1" ).arg( browseUri ) ); + url = QUrl( QString( SPOTIFY_PLAYLIST_API_URL "/browse/%1" ).arg( m_browseUri ) ); else - url = QUrl( QString( SPOTIFY_PLAYLIST_API_URL "/browse/%1/%2" ).arg( browseUri ) + url = QUrl( QString( SPOTIFY_PLAYLIST_API_URL "/browse/%1/%2" ).arg( m_browseUri ) .arg ( m_limit ) ); tDebug() << "Looking up URL..." << url.toString(); @@ -216,6 +235,9 @@ SpotifyParser::spotifyBrowseFinished() if ( q.isNull() ) continue; + tLog() << "Setting resulthint to " << trackResult.value( "trackuri" ); + q->setResultHint( trackResult.value( "trackuri" ).toString() ); + m_tracks << q; } } @@ -279,7 +301,11 @@ SpotifyParser::spotifyTrackLookupFinished() Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), m_trackMode ); if ( !q.isNull() ) + { + q->setResultHint( t.value( "trackuri" ).toString() ); + m_tracks << q; + } } else { @@ -293,6 +319,31 @@ SpotifyParser::spotifyTrackLookupFinished() } +void +SpotifyParser::playlistListingResult( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ) +{ + Q_ASSERT( msgType == "playlistListing" ); + + m_title = msg.value( "name" ).toString(); + m_single = false; + m_creator = msg.value( "creator" ).toString(); + + const QVariantList tracks = msg.value( "tracks" ).toList(); + foreach ( const QVariant& blob, tracks ) + { + QVariantMap trackMap = blob.toMap(); + const query_ptr q = Query::get( trackMap.value( "artist" ).toString(), trackMap.value( "track" ).toString(), trackMap.value( "album" ).toString(), uuid(), false ); + + if ( q.isNull() ) + continue; + + m_tracks << q; + } + + checkBrowseFinished(); +} + + void SpotifyParser::checkBrowseFinished() { @@ -304,6 +355,7 @@ SpotifyParser::checkBrowseFinished() if ( m_createNewPlaylist && !m_tracks.isEmpty() ) { + m_playlist = Playlist::create( SourceList::instance()->getLocal(), uuid(), m_title, @@ -311,10 +363,30 @@ SpotifyParser::checkBrowseFinished() m_creator, false, m_tracks ); + connect( m_playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistCreated() ) ); + + if ( Accounts::SpotifyAccount::instance() && Accounts::SpotifyAccount::instance()->loggedIn() ) + { + SpotifyPlaylistUpdater* updater = new SpotifyPlaylistUpdater( + Accounts::SpotifyAccount::instance(), m_playlist->currentrevision(), m_browseUri, m_playlist ); + + QVariantHash creds = Accounts::SpotifyAccount::instance()->credentials(); + + // If the user isnt dropping a playlist the he owns, its subscribeable + if ( !m_browseUri.contains( creds.value( "username" ).toString() ) ) + updater->setCanSubscribe( true ); + + // Just register the infos + Accounts::SpotifyAccount::instance()->registerPlaylistInfo( m_title, m_browseUri, m_browseUri, false, false ); + Accounts::SpotifyAccount::instance()->registerUpdaterForPlaylist( m_browseUri, updater ); + + + Accounts::SpotifyAccount::instance()->setSubscribedForPlaylist( m_playlist, true ); + + } return; } - else if ( m_single && !m_tracks.isEmpty() ) emit track( m_tracks.first() ); else if ( !m_single && !m_tracks.isEmpty() ) diff --git a/src/libtomahawk/utils/SpotifyParser.h b/src/libtomahawk/utils/SpotifyParser.h index 7f5c65b61..3675489ca 100644 --- a/src/libtomahawk/utils/SpotifyParser.h +++ b/src/libtomahawk/utils/SpotifyParser.h @@ -24,7 +24,8 @@ #include "Typedefs.h" #include "Query.h" #include "jobview/JobStatusItem.h" - +#include "accounts/spotify/SpotifyPlaylistUpdater.h" +#include "accounts/spotify/SpotifyAccount.h" #include #include #include @@ -38,6 +39,8 @@ */ class QNetworkReply; +class SpotifyAccount; +class SpotifyPlaylistUpdater; namespace Tomahawk { @@ -57,6 +60,9 @@ public: // the single track signal void setSingleMode( bool single ) { m_single = single; } +public slots: + void playlistListingResult( const QString& msgType, const QVariantMap& msg, const QVariant& extraData ); + signals: void track( const Tomahawk::query_ptr& track ); void tracks( const QList< Tomahawk::query_ptr > tracks ); @@ -84,7 +90,7 @@ private: QString m_title, m_info, m_creator; Tomahawk::playlist_ptr m_playlist; DropJobNotifier* m_browseJob; - + QString m_browseUri; static QPixmap* s_pixmap; }; diff --git a/src/sourcetree/SourceTreeView.cpp b/src/sourcetree/SourceTreeView.cpp index ce9911c08..55a97a338 100644 --- a/src/sourcetree/SourceTreeView.cpp +++ b/src/sourcetree/SourceTreeView.cpp @@ -609,7 +609,6 @@ SourceTreeView::dragEnterEvent( QDragEnterEvent* event ) m_dropRect = QRect(); m_dropIndex = QPersistentModelIndex(); - qDebug() << Q_FUNC_INFO << "Accepting Drag Event"; event->setDropAction( Qt::CopyAction ); event->acceptProposedAction(); } diff --git a/src/sourcetree/SourcesModel.cpp b/src/sourcetree/SourcesModel.cpp index a2fe261ae..c800a13e1 100644 --- a/src/sourcetree/SourcesModel.cpp +++ b/src/sourcetree/SourcesModel.cpp @@ -30,6 +30,7 @@ #include "sourcetree/items/GroupItem.h" #include "sourcetree/items/GenericPageItems.h" #include "sourcetree/items/HistoryItem.h" +#include "sourcetree/items/LovedTracksItem.h" #include "SourceList.h" #include "Playlist.h" #include "Collection.h" @@ -293,9 +294,7 @@ SourcesModel::appendGroups() sc->setSortValue( 1 ); // browse section - GenericPageItem* loved = new GenericPageItem( this, browse, tr( "Top Loved Tracks" ), QIcon( RESPATH "images/loved_playlist.png" ), - boost::bind( &ViewManager::showTopLovedPage, ViewManager::instance() ), - boost::bind( &ViewManager::topLovedWidget, ViewManager::instance() ) ); + LovedTracksItem* loved = new LovedTracksItem( this, browse ); loved->setSortValue( 2 ); GenericPageItem* recent = new GenericPageItem( this, browse, tr( "Recently Played" ), QIcon( RESPATH "images/recently-played.png" ), diff --git a/src/sourcetree/items/HistoryItem.cpp b/src/sourcetree/items/HistoryItem.cpp index 0f941ec3f..93be20dc1 100644 --- a/src/sourcetree/items/HistoryItem.cpp +++ b/src/sourcetree/items/HistoryItem.cpp @@ -23,7 +23,6 @@ #include "GenericPageItems.h" #include "utils/TomahawkUtilsGui.h" #include "utils/Logger.h" -#include "playlist/CustomPlaylistView.h" #include "TemporaryPageItem.h" #include "SourceList.h" diff --git a/src/sourcetree/items/LovedTracksItem.cpp b/src/sourcetree/items/LovedTracksItem.cpp index 8b468b99c..4623b3437 100644 --- a/src/sourcetree/items/LovedTracksItem.cpp +++ b/src/sourcetree/items/LovedTracksItem.cpp @@ -24,7 +24,9 @@ #include "DropJob.h" #include "ViewManager.h" -#include "playlist/CustomPlaylistView.h" +#include "playlist/FlexibleView.h" +#include "playlist/TrackView.h" +#include "playlist/LovedTracksModel.h" #include "playlist/PlaylistLargeItemDelegate.h" using namespace Tomahawk; @@ -33,6 +35,7 @@ using namespace Tomahawk; LovedTracksItem::LovedTracksItem( SourcesModel* mdl, SourceTreeItem* parent ) : SourceTreeItem( mdl, parent, SourcesModel::LovedTracksPage ) , m_lovedTracksPage( 0 ) + , m_sortValue( -150 ) { } @@ -42,23 +45,49 @@ LovedTracksItem::~LovedTracksItem() } +QString +LovedTracksItem::text() const +{ + SourceItem* par = dynamic_cast< SourceItem* >( parent() ); + + if ( !par ) + return QString( tr( "Top Loved Tracks" ) ); + else + return QString( tr( "Loved Tracks" ) ); +} + + void LovedTracksItem::activate() { if ( !m_lovedTracksPage ) { SourceItem* par = dynamic_cast< SourceItem* >( parent() ); + FlexibleView* pv = new FlexibleView( ViewManager::instance()->widget() ); + pv->setPixmap( QPixmap( RESPATH "images/loved_playlist.png" ) ); + + LovedTracksModel* raModel = new LovedTracksModel( pv ); + raModel->setTitle( text() ); + + PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::LovedTracks, pv->trackView(), pv->trackView()->proxyModel() ); + connect( del, SIGNAL( updateIndex( QModelIndex ) ), pv->trackView(), SLOT( update( QModelIndex ) ) ); + pv->trackView()->setItemDelegate( del ); + + pv->setEmptyTip( tr( "Sorry, we could not find any loved tracks!" ) ); if ( !par ) - return; + raModel->setDescription( tr( "The most loved tracks from all your friends" ) ); + else + { + if ( par->source()->isLocal() ) + raModel->setDescription( tr( "All of your loved tracks" ) ); + else + raModel->setDescription( tr( "All of %1's loved tracks" ).arg( par->source()->friendlyName() ) ); + } - CustomPlaylistView* view = new CustomPlaylistView( par->source().isNull() ? CustomPlaylistView::TopLovedTracks : - CustomPlaylistView::SourceLovedTracks, par->source(), ViewManager::instance()->widget() ); - PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate(PlaylistLargeItemDelegate::LovedTracks, view, view->proxyModel() ); - connect( del, SIGNAL( updateIndex( QModelIndex ) ), view, SLOT( update( QModelIndex ) ) ); - view->setItemDelegate( del ); - view->setEmptyTip( tr( "Sorry, we could not find any loved tracks!" ) ); + pv->setPlayableModel( raModel ); + raModel->setSource( !par ? source_ptr() : par->source() ); - m_lovedTracksPage = view; + m_lovedTracksPage = pv; } ViewManager::instance()->show( m_lovedTracksPage ); diff --git a/src/sourcetree/items/LovedTracksItem.h b/src/sourcetree/items/LovedTracksItem.h index e2bec4ce1..81dae6016 100644 --- a/src/sourcetree/items/LovedTracksItem.h +++ b/src/sourcetree/items/LovedTracksItem.h @@ -33,20 +33,23 @@ public: LovedTracksItem( SourcesModel* model, SourceTreeItem* parent ); virtual ~LovedTracksItem(); - virtual QString text() const { return QString( tr( "Loved Tracks" ) ); } + virtual QString text() const; virtual QIcon icon() const { return QIcon( RESPATH "images/loved_playlist.png" ); } - virtual int peerSortValue() const { return -150; } + virtual int peerSortValue() const { return m_sortValue; } virtual void activate(); virtual bool willAcceptDrag( const QMimeData* data ) const; virtual DropTypes supportedDropTypes( const QMimeData* data ) const; virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action ); + void setSortValue( int value ) { m_sortValue = value; } + private slots: void loveDroppedTracks( QList< Tomahawk::query_ptr > qrys ); private: Tomahawk::ViewPage* m_lovedTracksPage; + int m_sortValue; }; #endif diff --git a/src/sourcetree/items/PlaylistItems.cpp b/src/sourcetree/items/PlaylistItems.cpp index f4806abf3..8fb322915 100644 --- a/src/sourcetree/items/PlaylistItems.cpp +++ b/src/sourcetree/items/PlaylistItems.cpp @@ -170,6 +170,34 @@ PlaylistItem::willAcceptDrag( const QMimeData* data ) const PlaylistItem::DropTypes PlaylistItem::supportedDropTypes( const QMimeData* data ) const { + if ( data->hasFormat( "application/tomahawk.mixed" ) ) + { + // If this is mixed but only queries/results, we can still handle them + bool mixedQueries = true; + + QByteArray itemData = data->data( "application/tomahawk.mixed" ); + QDataStream stream( &itemData, QIODevice::ReadOnly ); + QString mimeType; + qlonglong val; + + while ( !stream.atEnd() ) + { + stream >> mimeType; + if ( mimeType != "application/tomahawk.query.list" && + mimeType != "application/tomahawk.result.list" ) + { + mixedQueries = false; + break; + } + stream >> val; + } + + if ( mixedQueries ) + return DropTypeThisTrack | DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50; + else + return DropTypesNone; + } + if ( data->hasFormat( "application/tomahawk.query.list" ) ) return DropTypeThisTrack | DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50; else if ( data->hasFormat( "application/tomahawk.result.list" ) ) @@ -178,10 +206,6 @@ PlaylistItem::supportedDropTypes( const QMimeData* data ) const return DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50; else if ( data->hasFormat( "application/tomahawk.metadata.artist" ) ) return DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50; - else if ( data->hasFormat( "application/tomahawk.mixed" ) ) - { - return DropTypesNone; - } else if ( data->hasFormat( "text/plain" ) ) { return DropTypesNone; diff --git a/src/sourcetree/items/SourceItem.cpp b/src/sourcetree/items/SourceItem.cpp index 8275f9f81..a70e4228c 100644 --- a/src/sourcetree/items/SourceItem.cpp +++ b/src/sourcetree/items/SourceItem.cpp @@ -28,7 +28,7 @@ #include "utils/TomahawkUtilsGui.h" #include "utils/Logger.h" #include "widgets/SocialPlaylistWidget.h" -#include "playlist/CustomPlaylistView.h" +#include "playlist/FlexibleView.h" #include "playlist/PlaylistView.h" #include "playlist/RecentlyAddedModel.h" #include "playlist/RecentlyPlayedModel.h" @@ -508,12 +508,10 @@ SourceItem::latestAdditionsClicked() { if ( !m_latestAdditionsPage ) { - TrackView* cv = new TrackView( ViewManager::instance()->widget() ); - cv->setFrameShape( QFrame::NoFrame ); - cv->setAttribute( Qt::WA_MacShowFocusRect, 0 ); + FlexibleView* pv = new FlexibleView( ViewManager::instance()->widget() ); + pv->setPixmap( QPixmap( RESPATH "images/new-additions.png" ) ); - RecentlyAddedModel* raModel = new RecentlyAddedModel( cv ); - cv->proxyModel()->setStyle( PlayableProxyModel::Large ); + RecentlyAddedModel* raModel = new RecentlyAddedModel( pv ); raModel->setTitle( tr( "Latest Additions" ) ); if ( m_source->isLocal() ) @@ -521,17 +519,17 @@ SourceItem::latestAdditionsClicked() else raModel->setDescription( tr( "Latest additions to %1's collection" ).arg( m_source->friendlyName() ) ); - PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::LatestAdditions, cv, cv->proxyModel() ); - connect( del, SIGNAL( updateIndex( QModelIndex ) ), cv, SLOT( update( QModelIndex ) ) ); - cv->setItemDelegate( del ); - - cv->setPlayableModel( raModel ); - cv->sortByColumn( PlayableModel::Age, Qt::DescendingOrder ); - cv->setEmptyTip( tr( "Sorry, we could not find any recent additions!" ) ); + PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::LatestAdditions, pv->trackView(), pv->trackView()->proxyModel() ); + connect( del, SIGNAL( updateIndex( QModelIndex ) ), pv->trackView(), SLOT( update( QModelIndex ) ) ); + pv->trackView()->setItemDelegate( del ); + pv->setPlayableModel( raModel ); + pv->trackView()->sortByColumn( PlayableModel::Age, Qt::DescendingOrder ); + pv->detailedView()->sortByColumn( PlayableModel::Age, Qt::DescendingOrder ); + pv->setEmptyTip( tr( "Sorry, we could not find any recent additions!" ) ); raModel->setSource( m_source ); - m_latestAdditionsPage = cv; + m_latestAdditionsPage = pv; } ViewManager::instance()->show( m_latestAdditionsPage ); @@ -551,12 +549,10 @@ SourceItem::recentPlaysClicked() { if ( !m_recentPlaysPage ) { - PlaylistView* pv = new PlaylistView( ViewManager::instance()->widget() ); - pv->setFrameShape( QFrame::NoFrame ); - pv->setAttribute( Qt::WA_MacShowFocusRect, 0 ); + FlexibleView* pv = new FlexibleView( ViewManager::instance()->widget() ); + pv->setPixmap( QPixmap( RESPATH "images/recently-played.png" ) ); RecentlyPlayedModel* raModel = new RecentlyPlayedModel( pv ); - pv->proxyModel()->setStyle( PlayableProxyModel::Large ); raModel->setTitle( tr( "Recently Played Tracks" ) ); if ( m_source->isLocal() ) @@ -564,11 +560,11 @@ SourceItem::recentPlaysClicked() else raModel->setDescription( tr( "%1's recently played tracks" ).arg( m_source->friendlyName() ) ); - PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::RecentlyPlayed, pv, pv->proxyModel() ); - connect( del, SIGNAL( updateIndex( QModelIndex ) ), pv, SLOT( update( QModelIndex ) ) ); - pv->setItemDelegate( del ); + PlaylistLargeItemDelegate* del = new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::RecentlyPlayed, pv->trackView(), pv->trackView()->proxyModel() ); + connect( del, SIGNAL( updateIndex( QModelIndex ) ), pv->trackView(), SLOT( update( QModelIndex ) ) ); + pv->trackView()->setItemDelegate( del ); - pv->setPlaylistModel( raModel ); + pv->setPlayableModel( raModel ); pv->setEmptyTip( tr( "Sorry, we could not find any recent plays!" ) ); raModel->setSource( m_source ); diff --git a/src/web/Api_v1.cpp b/src/web/Api_v1.cpp index 4f8f78c9f..060ea0e1b 100644 --- a/src/web/Api_v1.cpp +++ b/src/web/Api_v1.cpp @@ -235,6 +235,11 @@ Api_v1::statResult( const QString& clientToken, const QString& name, bool valid { Q_UNUSED( clientToken ) Q_UNUSED( name ) + + Q_ASSERT( m_storedEvent ); + if ( !m_storedEvent ) + return; + QVariantMap m; m.insert( "name", "playdar" ); m.insert( "version", "0.1.1" ); // TODO (needs to be >=0.1.1 for JS to work)