diff --git a/ChangeLog b/ChangeLog index e45fc3a3e..ae7c5afa0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,16 @@ Version 0.1.0: + * Fixed stations so they resolve against all available sources instead of + only local and friend's collections. + * Add a Song seed for stations and automatic playlists, and allow dragging of + any tracks to the New Stations entry to create a pre-seeded station. + * Added auto-completion for artists while filling in a station or automatic + playlist. * SOCKS5 proxy support. Noproxy hosts are also supported but no wildcard support (yet). + * Support loading of - and exporting to - .xspf playlists + * Added Tomahawk:// protocol support and share links for many things including + tracks, playlists, and stations. + * Autoload automatically detected resolvers on startup. * Fix issue where track resolving spinner never stopped if tracks were removed from playlist while resolving. * Twitter & Jabber profile pictures are shown. @@ -9,18 +19,26 @@ Version 0.1.0: * Add new Google account type that is a thin wrapper around a Jabber plugin. * Overhaul the settings dialog interface. * Resolvers can now be enabled and disabled, and some can be configured - directly in Tomahawk. + directly in Tomahawk, for example the new Spotify resolver. * Split playlists and stations in sources sidebar. Show Recently Played as a node under the Super Collection. * Fix massive speed bottleneck on startup in the case of many recently played playlists. + * Removed filter and song view from Super Collection, coming back in the next + release. * Browse and play collections in our snappy tree-mode, which also shows images for artists and albums. * Fixed crash that could occur when playing a track from a browser. - * Fixed a crash caused by sources going on- or offline. + * Fixed a crash caused by sources going on or offline. + * Huge optimizations in the resolving pipeline. + * Improved the handling of automatic status messages for Google Talk + * Switch to Phonon sound system, allowing us to support a wide variety + of audio formats. + * UI tweaks and cleanup. * (OS X) Open configuration dialogs as sliding sheets. * (OS X) Increase our available file watches to the maximum that the system reports. + * (OS X) Added 'Window' menu with zoom/minimize actions Version 0.0.3: * Show spinner while resolving playlists. diff --git a/admin/mac/deposx.sh b/admin/mac/deposx.sh index 596fbcc0c..8da4cd3e0 100755 --- a/admin/mac/deposx.sh +++ b/admin/mac/deposx.sh @@ -85,8 +85,8 @@ function deplib_change install_name_tool -change $ORIGROOT/libtomahawk_sipzeroconf.dylib @executable_path/libtomahawk_sipzeroconf.dylib $1 install_name_tool -change $ORIGROOT/libtomahawk_qtweetlib.dylib @executable_path/libtomahawk_qtweetlib.dylib $1 install_name_tool -change $ORIGROOT/libtomahawk_portfwd.dylib @executable_path/libtomahawk_portfwd.dylib $1 - install_name_tool -change $ORIGROOT/libjreen.0.dylib @executable_path/libjreen.0.dylib $1 - install_name_tool -change /usr/local/Cellar/jreen/HEAD/lib/libjreen.dylib @executable_path/libjreen.0.dylib $1 + install_name_tool -change $ORIGROOT/libjreen.dylib @executable_path/libjreen.dylib $1 + install_name_tool -change /usr/local/Cellar/jreen/HEAD/lib/libjreen.dylib @executable_path/libjreen.dylib $1 install_name_tool -change /usr/local/Cellar/qca/2.0.2/lib/qca.framework/Versions/2/qca @executable_path/../Frameworks/qca.framework/Versions/2/qca $1 install_name_tool -change /usr/local/Cellar/gettext/0.18.1.1/lib/libintl.8.dylib @executable_path/libintl.8.dylib $1 install_name_tool -change /usr/local/Cellar/vlc-git/HEAD/lib/libvlc.5.dylib @executable_path/libvlc.5.dylib $1 @@ -127,7 +127,7 @@ import_lib /usr/local/Cellar/vlc-git/HEAD/lib/libvlc.5.dylib import_lib /usr/local/Cellar/vlc-git/HEAD/lib/libvlccore.4.dylib import_lib /usr/local/Cellar/gettext/0.18.1.1/lib/libintl.8.dylib -import_lib $ORIGROOT/libjreen.0.dylib +import_lib $ORIGROOT/libjreen.dylib import_lib $ORIGROOT/libtomahawklib.dylib import_lib $ORIGROOT/libtomahawk_sipjabber.dylib import_lib $ORIGROOT/libtomahawk_sipgoogle.dylib diff --git a/admin/win/nsi/tomahawk.nsi b/admin/win/nsi/tomahawk.nsi index 9f33b5472..dbed64660 100644 --- a/admin/win/nsi/tomahawk.nsi +++ b/admin/win/nsi/tomahawk.nsi @@ -15,9 +15,10 @@ ;----------------------------------------------------------------------------- ; Some paths. ;----------------------------------------------------------------------------- -!define MING_PATH "/usr/i686-w64-mingw32/sys-root/mingw" +!ifndef MING_PATH + !define MING_PATH "/usr/i686-w64-mingw32/sys-root/mingw" +!endif !define MING_BIN "${MING_PATH}/bin" -!define MING_DLL_PATH "${MING_BIN}" !define MING_LIB "${MING_PATH}/lib" !define ROOT_PATH "..\..\.." ; assuming the script is in ROOT/admin/win/nsi !define BUILD_PATH "${ROOT_PATH}\build" @@ -316,20 +317,20 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER SetOutPath "$INSTDIR" ;Cygwin/c++ stuff - ;File "${MING_DLL_PATH}\cygmad-0.dll" - ;File "${MING_DLL_PATH}\libgcc_s_dw2-1.dll" - ;File "${MING_DLL_PATH}\mingwm10.dll" - File "${MING_DLL_PATH}\libgcc_s_sjlj-1.dll" - File "${MING_DLL_PATH}\libstdc++-6.dll" + ;File "${MING_BIN}\cygmad-0.dll" + ;File "${MING_BIN}\libgcc_s_dw2-1.dll" + ;File "${MING_BIN}\mingwm10.dll" + File "${MING_BIN}\libgcc_s_sjlj-1.dll" + File "${MING_BIN}\libstdc++-6.dll" ;Phonon stuff ;Fix the phonon build to not use Dbus File "${QT_DLL_PATH}\QtDbus4.dll" - File "${MING_DLL_PATH}\libdbus-1-3.dll" - File "${MING_DLL_PATH}\dbus-daemon.exe" + File "${MING_BIN}\libdbus-1-3.dll" + File "${MING_BIN}\dbus-daemon.exe" - File "${MING_DLL_PATH}\libphonon.dll" + File "${MING_BIN}\libphonon.dll" SetOutPath "$INSTDIR\phonon_backend" File "${MING_BIN}\phonon_backend\phonon_vlc.dll" SetOutPath "$INSTDIR" @@ -350,13 +351,13 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER ; Other - File "${MING_DLL_PATH}\libqjson.dll" - File "${MING_DLL_PATH}\libtag.dll" - File "${MING_DLL_PATH}\libpng15-15.dll" - File "${MING_DLL_PATH}\libjpeg-8.dll" - File "${MING_DLL_PATH}\zlib1.dll" + File "${MING_BIN}\libqjson.dll" + File "${MING_BIN}\libtag.dll" + File "${MING_BIN}\libpng15-15.dll" + File "${MING_BIN}\libjpeg-8.dll" + File "${MING_BIN}\zlib1.dll" - File "${MING_DLL_PATH}\libechonest.dll" + File "${MING_BIN}\libechonest.dll" File "${MING_BIN}\libQTweetLib.dll" ; Jabber diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index aa987dde4..cabd0be68 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -162,6 +162,7 @@ set( libSources utils/xspfgenerator.cpp widgets/newplaylistwidget.cpp + widgets/playlisttypeselectordlg.cpp widgets/welcomewidget.cpp widgets/welcomeplaylistmodel.cpp widgets/overlaywidget.cpp @@ -326,6 +327,7 @@ set( libHeaders utils/xspfgenerator.h widgets/newplaylistwidget.h + widgets/playlisttypeselectordlg.h widgets/welcomewidget.h widgets/welcomeplaylistmodel.h widgets/overlaywidget.h @@ -341,6 +343,7 @@ set( libHeaders_NoMOC playlist/dynamic/GeneratorInterface.h ) set( libUI ${libUI} + widgets/playlisttypeselectordlg.ui widgets/newplaylistwidget.ui widgets/welcomewidget.ui widgets/infowidgets/sourceinfowidget.ui diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index a64c8abac..51f1aea1a 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -64,7 +64,8 @@ AudioEngine::~AudioEngine() { qDebug() << Q_FUNC_INFO; - stop(); + m_mediaObject->stop(); +// stop(); delete m_audioOutput; delete m_mediaObject; @@ -300,6 +301,12 @@ void AudioEngine::onStateChanged( Phonon::State newState, Phonon::State oldState ) { qDebug() << Q_FUNC_INFO << oldState << newState; + + if ( newState == Phonon::ErrorState ) + { + qDebug() << "Phonon Error:" << m_mediaObject->errorString() << m_mediaObject->errorType(); + } + if ( oldState == Phonon::PlayingState && newState == Phonon::StoppedState ) { if ( !m_expectStop ) diff --git a/src/libtomahawk/database/databasecommand_resolve.cpp b/src/libtomahawk/database/databasecommand_resolve.cpp index e420f79bb..18975a8a5 100644 --- a/src/libtomahawk/database/databasecommand_resolve.cpp +++ b/src/libtomahawk/database/databasecommand_resolve.cpp @@ -42,7 +42,10 @@ DatabaseCommand_Resolve::exec( DatabaseImpl* lib ) qDebug() << "Using result-hint to speed up resolving:" << m_query->resultHint(); Tomahawk::result_ptr result = lib->resultFromHint( m_query ); - if ( !result.isNull() && result->collection()->source()->isOnline() ) +/* qDebug() << "Result null:" << result.isNull(); + qDebug() << "Collection null:" << result->collection().isNull(); + qDebug() << "Source null:" << result->collection()->source().isNull();*/ + if ( !result.isNull() && !result->collection().isNull() && result->collection()->source()->isOnline() ) { res << result; emit results( m_query->id(), res ); diff --git a/src/libtomahawk/infosystem/infosystem.cpp b/src/libtomahawk/infosystem/infosystem.cpp index 332493cfb..5e3ab4c4e 100644 --- a/src/libtomahawk/infosystem/infosystem.cpp +++ b/src/libtomahawk/infosystem/infosystem.cpp @@ -86,30 +86,26 @@ InfoSystem::~InfoSystem() if ( !m_worker.isNull() ) { - if( m_infoSystemWorkerThreadController ) - { - m_worker.clear(); - m_infoSystemWorkerThreadController->quit(); - m_infoSystemWorkerThreadController->wait( 60000 ); - delete m_infoSystemWorkerThreadController; - qDebug() << Q_FUNC_INFO << " worker thread controller finished, deleting worker"; - m_infoSystemWorkerThreadController = 0; - } - } + m_infoSystemWorkerThreadController->quit(); + m_infoSystemWorkerThreadController->wait( 60000 ); + delete m_worker.data(); + delete m_infoSystemWorkerThreadController; + m_infoSystemWorkerThreadController = 0; + } qDebug() << Q_FUNC_INFO << " done deleting worker"; if( m_infoSystemCacheThreadController ) { - m_cache.clear(); m_infoSystemCacheThreadController->quit(); m_infoSystemCacheThreadController->wait( 60000 ); + + delete m_cache.data(); delete m_infoSystemCacheThreadController; - qDebug() << Q_FUNC_INFO << " cache thread controller finished, deleting cache"; m_infoSystemCacheThreadController = 0; } - qDebug() << Q_FUNC_INFO << " done deleting cache, exiting"; + qDebug() << Q_FUNC_INFO << " done deleting cache"; } diff --git a/src/libtomahawk/playlist/dynamic/DynamicModel.cpp b/src/libtomahawk/playlist/dynamic/DynamicModel.cpp index 6e7a16de8..74d1fb2cc 100644 --- a/src/libtomahawk/playlist/dynamic/DynamicModel.cpp +++ b/src/libtomahawk/playlist/dynamic/DynamicModel.cpp @@ -64,7 +64,10 @@ DynamicModel::loadPlaylist( const Tomahawk::dynplaylist_ptr& playlist, bool load QString DynamicModel::description() const { - return m_playlist->generator()->sentenceSummary(); + if( !m_playlist.isNull() && !m_playlist->generator().isNull() ) + return m_playlist->generator()->sentenceSummary(); + else + return QString(); } diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicControlList.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicControlList.cpp index 5128562af..e041c38ae 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicControlList.cpp +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicControlList.cpp @@ -63,7 +63,11 @@ DynamicControlList::init() m_layout->setColumnStretch( 2, 1 ); m_layout->setMargin( 0 ); m_layout->setVerticalSpacing( 0 ); +#ifdef Q_WS_MAC // on OS X we don't want the right edge of the toolbuttons against the window + m_layout->setContentsMargins( 0, 0, 3, 0 ); +#else m_layout->setContentsMargins( 0, 0, 0, 0 ); +#endif m_layout->setSizeConstraint( QLayout::SetMinimumSize ); m_collapseLayout = new QHBoxLayout(); @@ -139,7 +143,7 @@ void DynamicControlList::addNewControl() m_layout->removeItem( m_collapseLayout ); dyncontrol_ptr control = m_generator->createControl(); - m_controls.append( new DynamicControlWrapper( control, m_layout, m_controls.size(), this ) ); + m_controls.append( new DynamicControlWrapper( control, m_layout, m_layout->rowCount(), this ) ); connect( m_controls.last(), SIGNAL( removeControl() ), this, SLOT( removeControl() ) ); connect( m_controls.last(), SIGNAL( changed() ), this, SLOT( controlChanged() ) ); diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.cpp index c3ed4fed6..79fb4e87c 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.cpp +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicControlWrapper.cpp @@ -41,7 +41,6 @@ DynamicControlWrapper::DynamicControlWrapper( const Tomahawk::dyncontrol_ptr& co , m_typeSelector( 0 ) , m_layout( QWeakPointer< QGridLayout >( layout ) ) { - qDebug() << "CREATING DYNAMIC CONTROL WRAPPER WITH ROW:" << row << layout; m_typeSelector = new QComboBox( m_parent ); @@ -74,8 +73,6 @@ DynamicControlWrapper::DynamicControlWrapper( const Tomahawk::dyncontrol_ptr& co m_layout.data()->addLayout( m_plusL, m_row, 3, Qt::AlignCenter ); m_plusL->setCurrentIndex( 0 ); - - } DynamicControlWrapper::~DynamicControlWrapper() diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp index 197334459..28ca29566 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp @@ -424,6 +424,7 @@ DynamicWidget::onDeleted() void DynamicWidget::onChanged() { - if( !m_playlist.isNull() ) + if( !m_playlist.isNull() && + ViewManager::instance()->currentPage() == this ) emit nameChanged( m_playlist->title() ); } diff --git a/src/libtomahawk/playlist/playlistmodel.cpp b/src/libtomahawk/playlist/playlistmodel.cpp index 1e1ee0889..65c157d9c 100644 --- a/src/libtomahawk/playlist/playlistmodel.cpp +++ b/src/libtomahawk/playlist/playlistmodel.cpp @@ -34,6 +34,7 @@ using namespace Tomahawk; PlaylistModel::PlaylistModel( QObject* parent ) : TrackModel( parent ) , m_waitForUpdate( false ) + , m_isTemporary( false ) { qDebug() << Q_FUNC_INFO; @@ -91,6 +92,7 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn setTitle( playlist->title() ); setDescription( tr( "A playlist by %1" ).arg( playlist->author()->isLocal() ? tr( "you" ) : playlist->author()->friendlyName() ) ); + m_isTemporary = false; if ( !loadEntries ) return; @@ -192,6 +194,12 @@ PlaylistModel::append( const Tomahawk::album_ptr& album ) connect( album.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ), SLOT( onTracksAdded( QList<Tomahawk::query_ptr> ) ) ); + if( rowCount( QModelIndex() ) == 0 ) { + setTitle( album->name() ); + setDescription( tr( "All tracks by %1 on album %2" ).arg( album->artist()->name() ).arg( album->name() ) ); + m_isTemporary = true; + } + onTracksAdded( album->tracks() ); } @@ -205,6 +213,12 @@ PlaylistModel::append( const Tomahawk::artist_ptr& artist ) connect( artist.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ), SLOT( onTracksAdded( QList<Tomahawk::query_ptr> ) ) ); + if( rowCount( QModelIndex() ) == 0 ) { + setTitle( artist->name() ); + setDescription( tr( "All tracks by %1" ).arg( artist->name() ) ); + m_isTemporary = true; + } + onTracksAdded( artist->tracks() ); } @@ -494,3 +508,9 @@ PlaylistModel::removeIndex( const QModelIndex& index, bool moreToCome ) onPlaylistChanged(); } } + +bool +PlaylistModel::isTemporary() const +{ + return m_isTemporary; +} diff --git a/src/libtomahawk/playlist/playlistmodel.h b/src/libtomahawk/playlist/playlistmodel.h index 96cfb72ce..30af9f4ea 100644 --- a/src/libtomahawk/playlist/playlistmodel.h +++ b/src/libtomahawk/playlist/playlistmodel.h @@ -67,6 +67,7 @@ public: void remove( unsigned int row, bool moreToCome = false ); virtual void removeIndex( const QModelIndex& index, bool moreToCome = false ); + bool isTemporary() const; signals: void repeatModeChanged( PlaylistInterface::RepeatMode mode ); void shuffleModeChanged( bool enabled ); @@ -90,7 +91,7 @@ private: QList<Tomahawk::plentry_ptr> playlistEntries() const; Tomahawk::playlist_ptr m_playlist; - bool m_waitForUpdate; + bool m_waitForUpdate, m_isTemporary; QList< Tomahawk::Query* > m_waitingForResolved; }; diff --git a/src/libtomahawk/playlist/playlistview.cpp b/src/libtomahawk/playlist/playlistview.cpp index 47dd6e863..5000bd80c 100644 --- a/src/libtomahawk/playlist/playlistview.cpp +++ b/src/libtomahawk/playlist/playlistview.cpp @@ -24,6 +24,7 @@ #include "playlist/playlistproxymodel.h" #include "widgets/overlaywidget.h" +#include "viewmanager.h" using namespace Tomahawk; @@ -70,8 +71,12 @@ PlaylistView::setPlaylistModel( PlaylistModel* model ) if ( !m_model->playlist().isNull() ) setGuid( QString( "playlistview/%1" ).arg( m_model->playlist()->guid() ) ); else + { setGuid( "playlistview" ); + m_model->title(); + m_model->description(); + } connect( m_model, SIGNAL( trackCountChanged( unsigned int ) ), SLOT( onTrackCountChanged( unsigned int ) ) ); connect( m_model, SIGNAL( playlistDeleted() ), SLOT( onDeleted() ) ); connect( m_model, SIGNAL( playlistChanged() ), SLOT( onChanged() ) ); @@ -134,7 +139,7 @@ PlaylistView::keyPressEvent( QKeyEvent* event ) if ( !model() ) return; - if ( event->key() == Qt::Key_Delete && !model()->isReadOnly() ) + if ( ( event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace ) && !model()->isReadOnly() ) { qDebug() << "Removing selected items"; proxyModel()->removeIndexes( selectedIndexes() ); @@ -186,6 +191,17 @@ PlaylistView::onDeleted() void PlaylistView::onChanged() { - if ( m_model && !m_model->playlist().isNull() ) + if ( m_model && !m_model->playlist().isNull() && + ViewManager::instance()->currentPage() == this ) emit nameChanged( m_model->playlist()->title() ); } + +bool +PlaylistView::isTemporaryPage() const +{ + if ( m_model ) { + return m_model->isTemporary(); + } else { + return false; + } +} diff --git a/src/libtomahawk/playlist/playlistview.h b/src/libtomahawk/playlist/playlistview.h index fe845d5b8..c42ff1248 100644 --- a/src/libtomahawk/playlist/playlistview.h +++ b/src/libtomahawk/playlist/playlistview.h @@ -52,6 +52,7 @@ public: virtual QPixmap pixmap() const { return QPixmap( RESPATH "images/playlist-icon.png" ); } virtual bool jumpToCurrentTrack(); + virtual bool isTemporaryPage() const; signals: void nameChanged( const QString& title ); @@ -75,6 +76,8 @@ private: PlaylistModel* m_model; QMenu m_itemMenu; + QString m_customTitle; + QString m_customDescripton; QAction* m_playItemAction; QAction* m_addItemsToQueueAction; diff --git a/src/libtomahawk/utils/tomahawkutils.h b/src/libtomahawk/utils/tomahawkutils.h index ebe2562b4..331afa931 100644 --- a/src/libtomahawk/utils/tomahawkutils.h +++ b/src/libtomahawk/utils/tomahawkutils.h @@ -37,23 +37,6 @@ class QNetworkProxy; namespace TomahawkUtils { - class DLLEXPORT Sleep : public QThread - { - public: - static void sleep( unsigned long secs ) - { - QThread::sleep( secs ); - } - static void msleep( unsigned long msecs ) - { - QThread::msleep( msecs ); - } - static void usleep( unsigned long usecs ) - { - QThread::usleep( usecs ); - } - }; - class DLLEXPORT NetworkProxyFactory : public QNetworkProxyFactory { public: diff --git a/src/libtomahawk/viewmanager.cpp b/src/libtomahawk/viewmanager.cpp index efb2ca5ad..6b9380aef 100644 --- a/src/libtomahawk/viewmanager.cpp +++ b/src/libtomahawk/viewmanager.cpp @@ -599,24 +599,12 @@ ViewManager::setPage( ViewPage* page, bool trackHistory ) setHistoryPosition( m_pageHistory.count() - 1 ); } - if ( !playlistForInterface( currentPlaylistInterface() ).isNull() ) - emit playlistActivated( playlistForInterface( currentPlaylistInterface() ) ); - - else if ( dynamicPlaylistForInterface( currentPlaylistInterface() ) ) - emit dynamicPlaylistActivated( dynamicPlaylistForInterface( currentPlaylistInterface() ) ); - else if ( collectionForInterface( currentPlaylistInterface() ) ) - emit collectionActivated( collectionForInterface( currentPlaylistInterface() ) ); - else if ( isSuperCollectionVisible() ) - emit superCollectionActivated(); - else if( isNewPlaylistPageVisible() ) - emit newPlaylistActivated(); - /* TODO refactor. now we have rows in the sourcetreeview that are connected to pages, e.g. Stations, Recently Updated, etc - else if ( !currentPlaylistInterface() ) - emit tempPageActivated();*/ - qDebug() << "View page shown:" << page->title(); emit viewPageActivated( page ); + if( page->isTemporaryPage() ) + emit tempPageActivated( page ); + if ( !AudioEngine::instance()->playlist() ) AudioEngine::instance()->setPlaylist( currentPlaylistInterface() ); diff --git a/src/libtomahawk/viewmanager.h b/src/libtomahawk/viewmanager.h index 0070f95e8..234e9c846 100644 --- a/src/libtomahawk/viewmanager.h +++ b/src/libtomahawk/viewmanager.h @@ -111,13 +111,7 @@ signals: void historyBackAvailable( bool avail ); void historyForwardAvailable( bool avail ); - void tempPageActivated(); - void superCollectionActivated(); - void collectionActivated( const Tomahawk::collection_ptr& collection ); - void playlistActivated( const Tomahawk::playlist_ptr& playlist ); - void dynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ); - - void newPlaylistActivated(); + void tempPageActivated( Tomahawk::ViewPage* ); void viewPageActivated( Tomahawk::ViewPage* ); public slots: diff --git a/src/libtomahawk/viewpage.h b/src/libtomahawk/viewpage.h index 0921998b2..31e18ba3e 100644 --- a/src/libtomahawk/viewpage.h +++ b/src/libtomahawk/viewpage.h @@ -51,7 +51,10 @@ public: virtual bool jumpToCurrentTrack() = 0; + virtual bool isTemporaryPage() const { return false; } + /** subclasses implementing ViewPage can emit the following signals: + * nameChanged( const QString& ) * descriptionChanged( const QString& ) * destroyed( QWidget* widget ); * diff --git a/src/libtomahawk/widgets/newplaylistwidget.ui b/src/libtomahawk/widgets/newplaylistwidget.ui index 6a2701ee8..e3a145050 100644 --- a/src/libtomahawk/widgets/newplaylistwidget.ui +++ b/src/libtomahawk/widgets/newplaylistwidget.ui @@ -10,6 +10,9 @@ <height>460</height> </rect> </property> + <property name="focusPolicy"> + <enum>Qt::TabFocus</enum> + </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="QLabel" name="label_2"> @@ -31,6 +34,9 @@ <height>26</height> </size> </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> </widget> </item> <item> diff --git a/src/libtomahawk/widgets/playlisttypeselectordlg.cpp b/src/libtomahawk/widgets/playlisttypeselectordlg.cpp new file mode 100644 index 000000000..4458bcd9f --- /dev/null +++ b/src/libtomahawk/widgets/playlisttypeselectordlg.cpp @@ -0,0 +1,88 @@ +/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> === + * + * Copyright 2011, Christopher Reichert <creichert07@gmail.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "widgets/newplaylistwidget.h" +#include "viewmanager.h" +#include "viewpage.h" +#include "sourcelist.h" + +#include "playlisttypeselectordlg.h" +#include "ui_playlisttypeselectordlg.h" + + +PlaylistTypeSelectorDlg::PlaylistTypeSelectorDlg( QWidget* parent, Qt::WindowFlags f ) + : QDialog( parent, f ) + , ui( new Ui::PlaylistTypeSelectorDlg ) +{ + ui->setupUi( this ); + +#ifdef Q_WS_MAC +// ui-> + ui->horizontalLayout_2->setContentsMargins( 4, 4, 4, 4 ); + + setSizeGripEnabled( false ); + setMinimumSize( size() ); + setMaximumSize( size() ); // to remove the resize grip on osx this is the only way +#endif + + m_isAutoPlaylist = false; + m_playlistName = ""; + + connect( ui->manualPlaylistButton, SIGNAL( clicked() ), + this, SLOT( createNormalPlaylist() )); + connect( ui->autoPlaylistButton, SIGNAL( clicked() ), + this, SLOT( createAutomaticPlaylist() )); + connect( ui->autoPlaylistNameLine, SIGNAL( textChanged( const QString& )), + this, SLOT( enableAutoPlaylistButton( const QString& ))); +} + +PlaylistTypeSelectorDlg::~PlaylistTypeSelectorDlg() +{ + delete ui; +} + +void +PlaylistTypeSelectorDlg::createNormalPlaylist() +{ + m_isAutoPlaylist = false; + done( QDialog::Accepted ); // return code is used to vaidate we did not exit out of the Dialog +} + +void PlaylistTypeSelectorDlg::createAutomaticPlaylist() { m_isAutoPlaylist = true; + m_playlistName = ui->autoPlaylistNameLine->text(); + done( QDialog::Accepted ); // return code is used to vaidate we did not exit out of the Dialog successfully +} + +QString +PlaylistTypeSelectorDlg::playlistName() const +{ + return m_playlistName; +} + +bool +PlaylistTypeSelectorDlg::playlistTypeIsAuto() const +{ + return m_isAutoPlaylist; +} + +void +PlaylistTypeSelectorDlg::enableAutoPlaylistButton( const QString &text ) +{ + ui->autoPlaylistButton->setEnabled( !text.isEmpty() ); +} + diff --git a/src/libtomahawk/widgets/playlisttypeselectordlg.h b/src/libtomahawk/widgets/playlisttypeselectordlg.h new file mode 100644 index 000000000..de00c1504 --- /dev/null +++ b/src/libtomahawk/widgets/playlisttypeselectordlg.h @@ -0,0 +1,55 @@ +/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> === + * + * Copyright 2011, Christopher Reichert <creichert07@gmail.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef PLAYLISTTYPESELECTORDLG_H +#define PLAYLISTTYPESELECTORDLG_H + +#include <QDialog> + +#include "dllmacro.h" + +namespace Ui +{ + class PlaylistTypeSelectorDlg; +} + +class DLLEXPORT PlaylistTypeSelectorDlg : public QDialog +{ +Q_OBJECT + +public: + PlaylistTypeSelectorDlg( QWidget* parent = 0, Qt::WindowFlags = 0 ); + ~PlaylistTypeSelectorDlg(); + bool playlistTypeIsNormal() const; + bool playlistTypeIsAuto() const; + QString playlistName() const; + +private slots: + void createNormalPlaylist(); + void createAutomaticPlaylist(); + void enableAutoPlaylistButton( const QString& ); + +private: + bool m_isAutoPlaylist; // if not an auto playlist then its a normal playlist + + Ui::PlaylistTypeSelectorDlg *ui; + QString m_playlistName; + +}; + +#endif // PlaylistTypeSelectorDlg_H diff --git a/src/libtomahawk/widgets/playlisttypeselectordlg.ui b/src/libtomahawk/widgets/playlisttypeselectordlg.ui new file mode 100644 index 000000000..bc4cb8e32 --- /dev/null +++ b/src/libtomahawk/widgets/playlisttypeselectordlg.ui @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PlaylistTypeSelectorDlg</class> + <widget class="QDialog" name="PlaylistTypeSelectorDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>554</width> + <height>169</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>482</width> + <height>145</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>10000</width> + <height>10000</height> + </size> + </property> + <property name="windowTitle"> + <string>New Playlist</string> + </property> + <property name="modal"> + <bool>false</bool> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,1,0"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>2</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="minimumSize"> + <size> + <width>221</width> + <height>40</height> + </size> + </property> + <property name="text"> + <string>Just a regular old playlist... Give it a name, drag in some tracks, and go!</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="margin"> + <number>2</number> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>28</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="manualPlaylistButton"> + <property name="text"> + <string>Create Manual Playlist</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>1</number> + </property> + <item> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Don't know exactly what you want? Give Tomahawk a few pointers and let it build a playlist for you!</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="margin"> + <number>1</number> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Name:</string> + </property> + <property name="margin"> + <number>1</number> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="autoPlaylistNameLine"> + <property name="placeholderText"> + <string>New Playlist...</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="autoPlaylistButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Create Automatic Playlist</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/musicscanner.cpp b/src/musicscanner.cpp index d74316c31..695eed4a0 100644 --- a/src/musicscanner.cpp +++ b/src/musicscanner.cpp @@ -162,28 +162,12 @@ MusicScanner::~MusicScanner() if ( !m_dirLister.isNull() ) { - m_dirLister.data()->setIsDeleting(); - QMetaObject::invokeMethod( m_dirLister.data(), "deleteLater", Qt::DirectConnection ); - while( !m_dirLister.isNull() ) - { - qDebug() << Q_FUNC_INFO << " scanner not deleted"; - TomahawkUtils::Sleep::msleep( 50 ); - } + m_dirListerThreadController->quit();; + m_dirListerThreadController->wait( 60000 ); - if ( m_dirListerThreadController ) - m_dirListerThreadController->quit(); - - if( m_dirListerThreadController ) - { - while( !m_dirListerThreadController->isFinished() ) - { - qDebug() << Q_FUNC_INFO << " scanner thread controller not finished"; - TomahawkUtils::Sleep::msleep( 50 ); - } - - delete m_dirListerThreadController; - m_dirListerThreadController = 0; - } + delete m_dirLister.data(); + delete m_dirListerThreadController; + m_dirListerThreadController = 0; } } diff --git a/src/scanmanager.cpp b/src/scanmanager.cpp index 4d923001f..25573b581 100644 --- a/src/scanmanager.cpp +++ b/src/scanmanager.cpp @@ -71,27 +71,12 @@ ScanManager::~ScanManager() if ( !m_scanner.isNull() ) { - QMetaObject::invokeMethod( m_scanner.data(), "deleteLater", Qt::DirectConnection ); - while( !m_scanner.isNull() ) - { - qDebug() << Q_FUNC_INFO << " scanner not deleted"; - TomahawkUtils::Sleep::msleep( 50 ); - } + m_musicScannerThreadController->quit(); + m_musicScannerThreadController->wait( 60000 ); - if ( m_musicScannerThreadController ) - m_musicScannerThreadController->quit(); - - if( m_musicScannerThreadController ) - { - while( !m_musicScannerThreadController->isFinished() ) - { - qDebug() << Q_FUNC_INFO << " scanner thread controller not finished"; - TomahawkUtils::Sleep::msleep( 50 ); - } - - delete m_musicScannerThreadController; - m_musicScannerThreadController = 0; - } + delete m_scanner.data(); + delete m_musicScannerThreadController; + m_musicScannerThreadController = 0; } qDebug() << Q_FUNC_INFO << " scanner thread controller finished, exiting ScanManager"; } @@ -180,27 +165,12 @@ ScanManager::scannerFinished() { if ( !m_scanner.isNull() ) { - QMetaObject::invokeMethod( m_scanner.data(), "deleteLater", Qt::DirectConnection ); - while( !m_scanner.isNull() ) - { - qDebug() << Q_FUNC_INFO << " scanner not deleted"; - TomahawkUtils::Sleep::msleep( 50 ); - } + m_musicScannerThreadController->quit(); + m_musicScannerThreadController->wait( 60000 ); - if ( m_musicScannerThreadController ) - m_musicScannerThreadController->quit(); - - if( m_musicScannerThreadController ) - { - while( !m_musicScannerThreadController->isFinished() ) - { - qDebug() << Q_FUNC_INFO << " scanner thread controller not finished"; - TomahawkUtils::Sleep::msleep( 50 ); - } - - delete m_musicScannerThreadController; - m_musicScannerThreadController = 0; - } + delete m_scanner.data(); + delete m_musicScannerThreadController; + m_musicScannerThreadController = 0; } emit finished(); } diff --git a/src/sourcetree/items/categoryitems.cpp b/src/sourcetree/items/categoryitems.cpp index a66e54719..82064636e 100644 --- a/src/sourcetree/items/categoryitems.cpp +++ b/src/sourcetree/items/categoryitems.cpp @@ -19,6 +19,7 @@ #include "tomahawkapp.h" #include "utils/tomahawkutils.h" #include "widgets/newplaylistwidget.h" +#include "widgets/playlisttypeselectordlg.h" #include "viewmanager.h" #include "viewpage.h" #include "sourcelist.h" @@ -59,13 +60,30 @@ CategoryAddItem::activate() { switch( m_categoryType ) { - case SourcesModel::PlaylistsCategory: - // only show if none is shown yet - if( !ViewManager::instance()->isNewPlaylistPageVisible() ) { - ViewPage* p = ViewManager::instance()->show( new NewPlaylistWidget() ); - model()->linkSourceItemToPage( this, p ); + case SourcesModel::PlaylistsCategory: { + + PlaylistTypeSelectorDlg playlistSelectorDlg( TomahawkApp::instance()->mainWindow() ); + int successfulReturn = playlistSelectorDlg.exec(); + + if ( !playlistSelectorDlg.playlistTypeIsAuto() && successfulReturn ) { + + // only show if none is shown yet + if( !ViewManager::instance()->isNewPlaylistPageVisible() ) { + //fix this namespace resolution problem, was not there before + Tomahawk::ViewPage* p = ViewManager::instance()->show( new NewPlaylistWidget() ); + model()->linkSourceItemToPage( this, p ); + } + + } else if ( playlistSelectorDlg.playlistTypeIsAuto() && successfulReturn ) { + // create Auto Playlist + QString playlistName = playlistSelectorDlg.playlistName(); + APP->mainWindow()->createAutomaticPlaylist( playlistName ); + } else if ( !successfulReturn ) { + model()->viewPageActivated( ViewManager::instance()->currentPage() ); } + break; + } case SourcesModel::StationsCategory: APP->mainWindow()->createStation(); break; @@ -218,4 +236,5 @@ CategoryItem::activate() if( m_category == SourcesModel::StationsCategory ) { // TODO activate stations page } + } diff --git a/src/sourcetree/items/collectionitem.cpp b/src/sourcetree/items/collectionitem.cpp index a559fbc83..4aa76867b 100644 --- a/src/sourcetree/items/collectionitem.cpp +++ b/src/sourcetree/items/collectionitem.cpp @@ -21,6 +21,7 @@ #include "playlistitems.h" #include "viewmanager.h" #include "playlist.h" +#include "genericpageitems.h" /// CollectionItem @@ -31,8 +32,12 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons , m_source( source ) , m_playlists( 0 ) , m_stations( 0 ) + , m_tempItem( 0 ) + , m_curTempPage( 0 ) { if( m_source.isNull() ) { // super collection + connect( ViewManager::instance(), SIGNAL( tempPageActivated( Tomahawk::ViewPage*) ), this, SLOT( tempPageActivated( Tomahawk::ViewPage* ) ) ); + return; } // create category items if there are playlists to show, or stations to show @@ -264,3 +269,40 @@ CollectionItem::onStationsDeleted( const QList< dynplaylist_ptr >& stations ) { playlistsDeletedInternal( m_stations, stations ); } + +void +CollectionItem::tempPageActivated( Tomahawk::ViewPage* v ) +{ + QString name = v->title(); + m_curTempPage = v; + if( !m_tempItem ) { + emit beginRowsAdded( children().count(), children().count() ); + m_tempItem = new GenericPageItem( model(), this, name, QIcon( RESPATH "images/playlist-icon.png" ), + boost::bind( &CollectionItem::tempItemClicked, this ), + boost::bind( &CollectionItem::getTempPage, this ) + ); + emit endRowsAdded(); + } else { + m_tempItem->setText( name ); + } + + model()->linkSourceItemToPage( m_tempItem, v ); + emit selectRequest( m_tempItem ); +} + +ViewPage* +CollectionItem::tempItemClicked() +{ + if( m_curTempPage ) { + // show the last temporary page the user displayed + return ViewManager::instance()->show( m_curTempPage ); + } + + return 0; +} + +ViewPage* +CollectionItem::getTempPage() const +{ + return m_curTempPage; +} diff --git a/src/sourcetree/items/collectionitem.h b/src/sourcetree/items/collectionitem.h index 1cb99e0cb..8bb23bee7 100644 --- a/src/sourcetree/items/collectionitem.h +++ b/src/sourcetree/items/collectionitem.h @@ -19,7 +19,11 @@ #include "sourcetreeitem.h" +class GenericPageItem; class CategoryItem; +namespace Tomahawk { + class ViewPage; +} class CollectionItem : public SourceTreeItem { @@ -38,6 +42,7 @@ public: CategoryItem* playlistsCategory() const { return m_playlists; } void setStationsCategory( CategoryItem* item ) { m_stations = item; } void setPlaylistsCategory( CategoryItem* item ) { m_playlists = item; } + private slots: void onPlaylistsAdded( const QList<Tomahawk::playlist_ptr>& playlists ); void onPlaylistsDeleted( const QList<Tomahawk::playlist_ptr>& playlists ); @@ -46,6 +51,10 @@ private slots: void onStationsAdded( const QList<Tomahawk::dynplaylist_ptr>& stations ); void onStationsDeleted( const QList<Tomahawk::dynplaylist_ptr>& stations ); + void tempPageActivated( Tomahawk::ViewPage* ); + Tomahawk::ViewPage* tempItemClicked(); + Tomahawk::ViewPage* getTempPage() const; + private: void playlistsAddedInternal( SourceTreeItem* parent, const QList< Tomahawk::dynplaylist_ptr >& playlists ); template< typename T > @@ -54,6 +63,9 @@ private: Tomahawk::source_ptr m_source; CategoryItem* m_playlists; CategoryItem* m_stations; + + GenericPageItem* m_tempItem; + Tomahawk::ViewPage* m_curTempPage; }; diff --git a/src/sourcetree/items/genericpageitems.cpp b/src/sourcetree/items/genericpageitems.cpp index 47f05605d..3739fa7cb 100644 --- a/src/sourcetree/items/genericpageitems.cpp +++ b/src/sourcetree/items/genericpageitems.cpp @@ -63,3 +63,10 @@ GenericPageItem::willAcceptDrag(const QMimeData* data) const { return false; } + +void +GenericPageItem::setText( const QString &text ) +{ + m_text = text; + emit updated(); +} diff --git a/src/sourcetree/items/genericpageitems.h b/src/sourcetree/items/genericpageitems.h index 1c0e954e4..5a980f7c3 100644 --- a/src/sourcetree/items/genericpageitems.h +++ b/src/sourcetree/items/genericpageitems.h @@ -36,6 +36,7 @@ public: virtual bool willAcceptDrag( const QMimeData* data ) const; virtual QIcon icon() const; + void setText( const QString& text ); signals: void activated(); diff --git a/src/sourcetree/items/sourcetreeitem.cpp b/src/sourcetree/items/sourcetreeitem.cpp index f1169cc28..ffe039ee6 100644 --- a/src/sourcetree/items/sourcetreeitem.cpp +++ b/src/sourcetree/items/sourcetreeitem.cpp @@ -30,7 +30,7 @@ SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, Sou connect( this, SIGNAL( childRowsAdded() ), m_model, SLOT( onItemRowsAddedDone() ) ); connect( this, SIGNAL( childRowsRemoved() ), m_model, SLOT( onItemRowsRemovedDone() ) ); connect( this, SIGNAL( updated() ), m_model, SLOT( itemUpdated() ) ); - + connect( this, SIGNAL( selectRequest( SourceTreeItem* ) ), m_model, SLOT( itemSelectRequest( SourceTreeItem* ) ) ); if( !m_parent ) return; diff --git a/src/sourcetree/items/sourcetreeitem.h b/src/sourcetree/items/sourcetreeitem.h index 290e72f15..57553988e 100644 --- a/src/sourcetree/items/sourcetreeitem.h +++ b/src/sourcetree/items/sourcetreeitem.h @@ -62,6 +62,7 @@ public: signals: void updated(); + void selectRequest( SourceTreeItem* ); void beginChildRowsAdded( int fromRow, int toRow ); void childRowsAdded(); diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp index 9bc01f52c..04384ae9c 100644 --- a/src/sourcetree/sourcesmodel.cpp +++ b/src/sourcetree/sourcesmodel.cpp @@ -35,6 +35,7 @@ using namespace Tomahawk; SourcesModel::SourcesModel( QObject* parent ) : QAbstractItemModel( parent ) + , m_rootItem( 0 ) , m_viewPageDelayedCacheItem( 0 ) { m_rootItem = new SourceTreeItem( this, 0, Invalid ); @@ -193,7 +194,7 @@ SourcesModel::mimeData( const QModelIndexList& ) const bool SourcesModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent ) { - SourceTreeItem* item; + SourceTreeItem* item = 0; qDebug() << "Got mime data dropped:" << row << column << parent << itemFromIndex( parent )->text(); if( row == -1 && column == -1 ) item = itemFromIndex( parent ); @@ -389,7 +390,6 @@ SourcesModel::linkSourceItemToPage( SourceTreeItem* item, ViewPage* p ) m_viewPageDelayedCacheItem = 0; } - SourceTreeItem* SourcesModel::itemFromIndex( const QModelIndex& idx ) const { @@ -448,3 +448,9 @@ SourcesModel::rowForItem( SourceTreeItem* item ) const { return item->parent()->children().indexOf( item ); } + +void +SourcesModel::itemSelectRequest( SourceTreeItem* item ) +{ + emit selectRequest( indexFromItem( item ) ); +} diff --git a/src/sourcetree/sourcesmodel.h b/src/sourcetree/sourcesmodel.h index 0ea3579e5..c702b4b4b 100644 --- a/src/sourcetree/sourcesmodel.h +++ b/src/sourcetree/sourcesmodel.h @@ -90,16 +90,6 @@ public: QModelIndex indexFromItem( SourceTreeItem* item ) const; -signals: - void selectRequest( const QModelIndex& idx ); - -private slots: - void onSourcesAdded( const QList<Tomahawk::source_ptr>& sources ); - void onSourceAdded( const Tomahawk::source_ptr& source ); - void onSourceRemoved( const Tomahawk::source_ptr& source ); - - void viewPageActivated( Tomahawk::ViewPage* ); - public slots: void loadSources(); @@ -108,6 +98,18 @@ public slots: void onItemRowsAddedDone(); void onItemRowsRemovedBegin( int first, int last ); void onItemRowsRemovedDone(); + + void viewPageActivated( Tomahawk::ViewPage* ); + + void itemSelectRequest( SourceTreeItem* item ); +signals: + void selectRequest( const QModelIndex& idx ); + +private slots: + void onSourcesAdded( const QList<Tomahawk::source_ptr>& sources ); + void onSourceAdded( const Tomahawk::source_ptr& source ); + void onSourceRemoved( const Tomahawk::source_ptr& source ); + private: SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const; int rowForItem( SourceTreeItem* item ) const; diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index 0529caac7..fe94ff5e9 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -198,9 +198,11 @@ SourceTreeView::onItemExpanded( const QModelIndex& idx ) void SourceTreeView::selectRequest( const QModelIndex& idx ) { - if( !selectionModel()->selectedIndexes().contains( idx ) ) + if ( !selectionModel()->selectedIndexes().contains( idx ) ) + { + scrollTo( idx, QTreeView::EnsureVisible ); selectionModel()->select( idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current ); - + } } @@ -212,23 +214,23 @@ SourceTreeView::loadPlaylist() void -SourceTreeView::deletePlaylist() +SourceTreeView::deletePlaylist( const QModelIndex& idxIn ) { qDebug() << Q_FUNC_INFO; - QModelIndex idx = m_contextMenuIndex; + QModelIndex idx = idxIn.isValid() ? idxIn : m_contextMenuIndex; if ( !idx.isValid() ) return; - SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt(); + SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( idx, SourcesModel::SourceTreeItemTypeRole ).toInt(); if ( type == SourcesModel::StaticPlaylist ) { - PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); + PlaylistItem* item = itemFromIndex< PlaylistItem >( idx ); playlist_ptr playlist = item->playlist(); Playlist::remove( playlist ); } else if( type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) { - DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( m_contextMenuIndex ); + DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( idx ); dynplaylist_ptr playlist = item->dynPlaylist(); DynamicPlaylist::remove( playlist ); } @@ -358,6 +360,25 @@ SourceTreeView::dropEvent( QDropEvent* event ) m_dragging = false; } +void +SourceTreeView::keyPressEvent( QKeyEvent *event ) +{ + if( ( event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace ) && !selectionModel()->selectedIndexes().isEmpty() ) + { + QModelIndex idx = selectionModel()->selectedIndexes().first(); + if ( model()->data( idx, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist || + model()->data( idx, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::AutomaticPlaylist || + model()->data( idx, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Station ) + { + PlaylistItem* item = itemFromIndex< PlaylistItem >( idx ); + Q_ASSERT( item ); + + if( item->playlist()->author()->isLocal() ) { + deletePlaylist( idx ); + } + } + } +} void SourceTreeView::paintEvent( QPaintEvent* event ) diff --git a/src/sourcetree/sourcetreeview.h b/src/sourcetree/sourcetreeview.h index 8058195a0..d3d6eb97e 100644 --- a/src/sourcetree/sourcetreeview.h +++ b/src/sourcetree/sourcetreeview.h @@ -52,7 +52,7 @@ private slots: void selectRequest( const QModelIndex& idx ); void loadPlaylist(); - void deletePlaylist(); + void deletePlaylist( const QModelIndex& = QModelIndex() ); void copyPlaylistLink(); void onCustomContextMenu( const QPoint& pos ); @@ -66,6 +66,7 @@ protected: virtual void dragLeaveEvent( QDragLeaveEvent* event ) { Q_UNUSED( event ); m_dragging = false; setDirtyRegion( m_dropRect ); } virtual void dragMoveEvent( QDragMoveEvent* event ); virtual void dropEvent( QDropEvent* event ); + virtual void keyPressEvent( QKeyEvent* event ); private: void setupMenus(); diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index f76c191a1..956ac47c7 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -324,12 +324,19 @@ TomahawkApp::~TomahawkApp() delete m_audioEngine; #endif - delete SipHandler::instance(); - Pipeline::instance()->stop(); - - delete m_database; delete m_infoSystem; + //FIXME: delete GeneratorFactory::registerFactory( "echonest", new EchonestFactory ); ? + + delete SipHandler::instance(); + delete m_servent; + + delete m_scanManager; + delete m_database; + + Pipeline::instance()->stop(); + delete Pipeline::instance(); + qDebug() << "Finished shutdown."; } diff --git a/src/tomahawkwindow.cpp b/src/tomahawkwindow.cpp index 445ae6c26..e261885f9 100644 --- a/src/tomahawkwindow.cpp +++ b/src/tomahawkwindow.cpp @@ -50,6 +50,7 @@ #include "utils/widgetdragfilter.h" #include "utils/xspfloader.h" #include "widgets/newplaylistwidget.h" +#include "widgets/playlisttypeselectordlg.h" #include "audiocontrols.h" #include "settingsdialog.h" @@ -275,7 +276,6 @@ TomahawkWindow::setupSignals() connect( ui->actionRescanCollection, SIGNAL( triggered() ), SLOT( rescanCollectionManually() ) ); connect( ui->actionLoadXSPF, SIGNAL( triggered() ), SLOT( loadSpiff() )); connect( ui->actionCreatePlaylist, SIGNAL( triggered() ), SLOT( createPlaylist() )); - connect( ui->actionCreateAutomaticPlaylist, SIGNAL( triggered() ), SLOT( createAutomaticPlaylist() )); connect( ui->actionCreate_New_Station, SIGNAL( triggered() ), SLOT( createStation() )); connect( ui->actionAboutTomahawk, SIGNAL( triggered() ), SLOT( showAboutTomahawk() ) ); connect( ui->actionExit, SIGNAL( triggered() ), qApp, SLOT( quit() ) ); @@ -453,11 +453,11 @@ TomahawkWindow::loadSpiff() void -TomahawkWindow::createAutomaticPlaylist() +TomahawkWindow::createAutomaticPlaylist( QString playlistName ) { - bool ok; - QString name = QInputDialog::getText( this, tr( "Create New Automatic Playlist" ), tr( "Name:" ), QLineEdit::Normal, tr( "New Automatic Playlist" ), &ok ); - if ( !ok || name.isEmpty() ) + QString name = playlistName; + + if ( name.isEmpty() ) return; source_ptr author = SourceList::instance()->getLocal(); @@ -493,7 +493,21 @@ TomahawkWindow::createStation() void TomahawkWindow::createPlaylist() { - ViewManager::instance()->show( new NewPlaylistWidget() ); + PlaylistTypeSelectorDlg playlistSelectorDlg; + int successfulReturn = playlistSelectorDlg.exec(); + + if ( !playlistSelectorDlg.playlistTypeIsAuto() && successfulReturn ) { + + // only show if none is shown yet + if( !ViewManager::instance()->isNewPlaylistPageVisible() ) { + ViewManager::instance()->show( new NewPlaylistWidget() ); + } + + } else if ( playlistSelectorDlg.playlistTypeIsAuto() && successfulReturn ) { + // create Auto Playlist + QString playlistName = playlistSelectorDlg.playlistName(); + APP->mainWindow()->createAutomaticPlaylist( playlistName ); + } } diff --git a/src/tomahawkwindow.h b/src/tomahawkwindow.h index b79acfbc9..30778dc30 100644 --- a/src/tomahawkwindow.h +++ b/src/tomahawkwindow.h @@ -61,7 +61,7 @@ protected: void hideEvent( QHideEvent* e ); public slots: - void createAutomaticPlaylist(); + void createAutomaticPlaylist( QString ); void createStation(); void createPlaylist(); void loadSpiff(); diff --git a/src/tomahawkwindow.ui b/src/tomahawkwindow.ui index a1a4f3985..48024e480 100644 --- a/src/tomahawkwindow.ui +++ b/src/tomahawkwindow.ui @@ -35,7 +35,7 @@ <x>0</x> <y>0</y> <width>1000</width> - <height>20</height> + <height>21</height> </rect> </property> <widget class="QMenu" name="menuSettings"> @@ -56,16 +56,6 @@ <addaction name="separator"/> <addaction name="actionExit"/> </widget> - <widget class="QMenu" name="menuPlaylist"> - <property name="title"> - <string>&Playlist</string> - </property> - <addaction name="actionCreatePlaylist"/> - <addaction name="actionCreateAutomaticPlaylist"/> - <addaction name="actionCreate_New_Station"/> - <addaction name="separator"/> - <addaction name="actionLoadXSPF"/> - </widget> <widget class="QMenu" name="menuNetwork"> <property name="title"> <string>&Network</string> @@ -87,6 +77,15 @@ <addaction name="actionDiagnostics"/> <addaction name="actionAboutTomahawk"/> </widget> + <widget class="QMenu" name="menuPlaylist"> + <property name="title"> + <string>&Playlist</string> + </property> + <addaction name="actionCreatePlaylist"/> + <addaction name="actionCreate_New_Station"/> + <addaction name="separator"/> + <addaction name="actionLoadXSPF"/> + </widget> <addaction name="menuApp"/> <addaction name="menuPlaylist"/> <addaction name="menuNetwork"/> @@ -108,7 +107,7 @@ </action> <action name="actionToggleConnect"> <property name="text"> - <string>Go &online</string> + <string>Go &Online</string> </property> </action> <action name="actionAddFriendManually"> diff --git a/thirdparty/jreen b/thirdparty/jreen index a231a2b38..8f995f246 160000 --- a/thirdparty/jreen +++ b/thirdparty/jreen @@ -1 +1 @@ -Subproject commit a231a2b3868baf32312d65cb7e371828212d7745 +Subproject commit 8f995f246637f533feb7124744e113034a32b505