diff --git a/CMakeLists.txt b/CMakeLists.txt index cb4b1e856..94f9e89dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" ) SET( TOMAHAWK_VERSION_MAJOR 0 ) SET( TOMAHAWK_VERSION_MINOR 2 ) -SET( TOMAHAWK_VERSION_PATCH 1 ) +SET( TOMAHAWK_VERSION_PATCH 99 ) #SET( TOMAHAWK_VERSION_RC 0 ) @@ -72,6 +72,10 @@ ELSE() LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" ) ENDIF() +IF( BUILD_GUI AND UNIX AND NOT APPLE ) + FIND_PACKAGE( X11 ) +ENDIF() + macro_optional_find_package(Qt4 4.7.0 COMPONENTS ${NEEDED_QT4_COMPONENTS} ) macro_log_feature(QT4_FOUND "Qt" "A cross-platform application and UI framework" "http://qt.nokia.com" TRUE "" "If you see this, although libqt4-devel is installed, check whether \n the qtwebkit-devel package is installed as well") diff --git a/CMakeModules/NSIS.template.in b/CMakeModules/NSIS.template.in index 25e273363..0417adfef 100644 --- a/CMakeModules/NSIS.template.in +++ b/CMakeModules/NSIS.template.in @@ -203,7 +203,7 @@ Function PageReinstall IntCmp $R0 ${VER_MINOR} build_check new_version older_version build_check: ReadRegDWORD $R0 HKLM "Software\Tomahawk" "VersionBuild" - IntCmp $R0 ${VER_BUILD} new_version older_version + IntCmp $R0 ${VER_BUILD} same_version new_version older_version new_version: !insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" "An older version of Tomahawk is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue." diff --git a/ChangeLog b/ChangeLog index 3591ccab6..8edf7301a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,17 @@ Version 0.3.0: * Added MPRIS 2.1 support. +Version 0.2.3: + * Fixed issue where artist bio could be referring to a different artist. + Version 0.2.2: + * Fixed crash when pressing previous and next when playing a song from the Queue. + * Fixed issue where wrench for newly added resolvers would not show up immediately. + * Fixed sidebar statistics not updating after collection scan finished. + * Fixed omitting a few tracks in the Collection tree-view. * Fixed sidebar & track sorting issues. * Seek- & volume sliders now directly jump to the position you clicked on. - * Fixed dragging artists and albums within Tomahawk. + * Added ability to drag artists and albums within Tomahawk (to playlists, queue, etc.). Version 0.2.1: * Fixed crashing trying to play an unavailable track. diff --git a/data/icons/tomahawk-icon.svg b/data/icons/tomahawk-icon.svg index b1ceb1bc3..49f1a86b5 100644 --- a/data/icons/tomahawk-icon.svg +++ b/data/icons/tomahawk-icon.svg @@ -1,60 +1,60 @@ - + - - + + - - + - + - - + + - - - + + @@ -64,29 +64,30 @@ - - + + - - + - + - - + + + @@ -94,11 +95,11 @@ - + - + @@ -106,10 +107,10 @@ - + - + @@ -117,10 +118,10 @@ - + - + @@ -128,21 +129,22 @@ - - + + - - - + + + + @@ -150,9 +152,10 @@ - - + + + @@ -160,37 +163,36 @@ - - - + + + - - + - + - - - + + - + @@ -199,40 +201,38 @@ - - + + - + - + - - + - - - + + + @@ -242,10 +242,10 @@ - - + @@ -253,27 +253,29 @@ - - + + - + - + - + + @@ -281,10 +283,10 @@ - + - + @@ -293,10 +295,10 @@ - - + - + diff --git a/data/images/album-icon.png b/data/images/album-icon.png new file mode 100644 index 000000000..51c54e8ca Binary files /dev/null and b/data/images/album-icon.png differ diff --git a/data/images/artist-icon.png b/data/images/artist-icon.png new file mode 100644 index 000000000..87d8fd48e Binary files /dev/null and b/data/images/artist-icon.png differ diff --git a/data/images/charts.png b/data/images/charts.png new file mode 100644 index 000000000..f0e2f9472 Binary files /dev/null and b/data/images/charts.png differ diff --git a/data/images/search-icon.png b/data/images/search-icon.png new file mode 100644 index 000000000..05ea58db8 Binary files /dev/null and b/data/images/search-icon.png differ diff --git a/data/icons/audio-x-generic-16x16.png b/data/images/track-icon-16x16.png similarity index 100% rename from data/icons/audio-x-generic-16x16.png rename to data/images/track-icon-16x16.png diff --git a/data/icons/audio-x-generic-22x22.png b/data/images/track-icon-22x22.png similarity index 100% rename from data/icons/audio-x-generic-22x22.png rename to data/images/track-icon-22x22.png diff --git a/data/icons/audio-x-generic-32x32.png b/data/images/track-icon-32x32.png similarity index 100% rename from data/icons/audio-x-generic-32x32.png rename to data/images/track-icon-32x32.png diff --git a/resources.qrc b/resources.qrc index b5af8fbd7..d70b6902e 100644 --- a/resources.qrc +++ b/resources.qrc @@ -88,6 +88,12 @@ data/images/whats-hot.png data/images/loved_playlist.png data/images/dashboard.png + data/images/artist-icon.png + data/images/album-icon.png + data/images/search-icon.png + data/images/track-icon-22x22.png + data/images/track-icon-32x32.png + data/images/track-icon-16x16.png data/stylesheets/topbar-radiobuttons.css data/icons/tomahawk-icon-16x16.png data/icons/tomahawk-icon-32x32.png @@ -95,9 +101,6 @@ data/icons/tomahawk-icon-128x128.png data/icons/tomahawk-icon-256x256.png data/icons/tomahawk-icon-512x512.png - data/icons/audio-x-generic-22x22.png - data/icons/audio-x-generic-32x32.png - data/icons/audio-x-generic-16x16.png data/www/auth.html data/www/auth.na.html data/www/tomahawk_banner_small.png diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 57253016c..e4553c2b4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -122,6 +122,8 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui} resolversmodel.h delegateconfigwrapper.h tomahawkwindow.h + + Qocoa/qsearchfield.h ) SET( tomahawkUI ${tomahawkUI} @@ -129,7 +131,6 @@ SET( tomahawkUI ${tomahawkUI} diagnosticsdialog.ui stackedsettingsdialog.ui proxydialog.ui - searchbox.ui audiocontrols.ui ) @@ -173,12 +174,13 @@ IF( APPLE ) INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/thirdparty/SPMediaKeyTap ) SET( tomahawkHeaders ${tomahawkHeaders} mac/tomahawkapp_mac.h mac/macshortcuthandler.h ) - SET( tomahawkSources ${tomahawkSources} mac/tomahawkapp_mac.mm mac/macshortcuthandler.cpp ) + SET( tomahawkSources ${tomahawkSources} mac/tomahawkapp_mac.mm mac/macshortcuthandler.cpp Qocoa/qsearchfield_mac.mm ) IF(HAVE_SPARKLE) SET( tomahawkHeaders ${tomahawkHeaders} ${SPARKLE}/Headers ) ENDIF(HAVE_SPARKLE) - +ELSE( APPLE ) + SET( tomahawkSources ${tomahawkSources} Qocoa/qsearchfield.cpp ) ENDIF( APPLE ) IF(GLOOX_FOUND) diff --git a/src/Qocoa/qocoa_mac.h b/src/Qocoa/qocoa_mac.h new file mode 100644 index 000000000..d86f9ad27 --- /dev/null +++ b/src/Qocoa/qocoa_mac.h @@ -0,0 +1,51 @@ +/* +Copyright (C) 2011 by Mike McQuaid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef QCOCOA_MAC_H +#define QCOCOA_MAC_H + +#include +#include +#include +#include + +static inline NSString* fromQString(const QString &string) +{ + char* cString = string.toUtf8().data(); + return [[NSString alloc] initWithUTF8String:cString]; +} + +static inline QString toQString(NSString *string) +{ + if (!string) + return QString(); + return QString::fromUtf8([string UTF8String]); +} + +static inline void zeroLayout(void *cocoaView, QWidget *parent) +{ + QVBoxLayout *layout = new QVBoxLayout(parent); + layout->setMargin(0); + layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent)); +} + +#endif diff --git a/src/Qocoa/qsearchfield.cpp b/src/Qocoa/qsearchfield.cpp new file mode 100644 index 000000000..316b31ca0 --- /dev/null +++ b/src/Qocoa/qsearchfield.cpp @@ -0,0 +1,78 @@ +/* +Copyright (C) 2011 by Mike McQuaid +Copyright (C) 2011 by Leo Franchi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "qsearchfield.h" + +#include +#include + +#include "playlist/topbar/searchlineedit.h" +#include "utils/tomahawkutils.h" + +class QSearchFieldPrivate +{ +public: + QSearchFieldPrivate(SearchLineEdit *lineEdit) : lineEdit(lineEdit) {} + SearchLineEdit *lineEdit; +}; + +QSearchField::QSearchField(QWidget *parent) : QWidget(parent) +{ + SearchLineEdit *lineEdit = new SearchLineEdit(this); + connect(lineEdit, SIGNAL(textChanged(QString)), + this, SIGNAL(textChanged(QString))); + connect(lineEdit, SIGNAL(returnPressed()), + this, SIGNAL(returnPressed())); + + pimpl = new QSearchFieldPrivate(lineEdit); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(lineEdit); + TomahawkUtils::unmarginLayout(layout); + setContentsMargins(0, 0, 0, 0); + + lineEdit->setStyleSheet( "QLineEdit { border: 1px solid gray; border-radius: 6px; margin-right: 2px; }" ); + lineEdit->setContentsMargins(0, 0, 0, 0); + lineEdit->setMinimumHeight(27); + setFixedHeight(27); +} + +void QSearchField::setText(const QString &text) +{ + pimpl->lineEdit->setText(text); +} + +void QSearchField::setPlaceholderText(const QString& text) +{ + pimpl->lineEdit->setInactiveText( text ); +} + +void QSearchField::clear() +{ + pimpl->lineEdit->clear(); +} + +QString QSearchField::text() const +{ + return pimpl->lineEdit->text(); +} diff --git a/src/Qocoa/qsearchfield.h b/src/Qocoa/qsearchfield.h new file mode 100644 index 000000000..4e2ba42fa --- /dev/null +++ b/src/Qocoa/qsearchfield.h @@ -0,0 +1,29 @@ +#ifndef QSEARCHFIELD_H +#define QSEARCHFIELD_H + +#include + +class QSearchFieldPrivate; +class QSearchField : public QWidget +{ + Q_OBJECT +public: + explicit QSearchField(QWidget* parent); + + QString text() const; + +public slots: + void setText(const QString &text); + void setPlaceholderText(const QString& text); + + void clear(); +signals: + void textChanged(const QString &text); + void returnPressed(); + +private: + friend class QSearchFieldPrivate; + QSearchFieldPrivate *pimpl; +}; + +#endif // QSEARCHFIELD_H diff --git a/src/Qocoa/qsearchfield_mac.mm b/src/Qocoa/qsearchfield_mac.mm new file mode 100644 index 000000000..5f60cf1e8 --- /dev/null +++ b/src/Qocoa/qsearchfield_mac.mm @@ -0,0 +1,118 @@ +/* +Copyright (C) 2011 by Mike McQuaid +Copyright (C) 2011 by Leo Franchi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "qsearchfield.h" + +#include "qocoa_mac.h" + +#include "qsearchfield.h" + +#import "Foundation/NSAutoreleasePool.h" +#import "Foundation/NSNotification.h" +#import "AppKit/NSSearchField.h" + +class QSearchFieldPrivate +{ +public: + QSearchFieldPrivate(QSearchField *qSearchField, NSSearchField *nsSearchField) + : qSearchField(qSearchField), nsSearchField(nsSearchField) {} + + void textDidChange(const QString &text) + { + emit qSearchField->textChanged(text); + } + + void textDidEndEditing() + { + emit qSearchField->returnPressed(); + } + + QSearchField *qSearchField; + NSSearchField *nsSearchField; +}; + +@interface QSearchFieldDelegate : NSObject +{ +@public + QSearchFieldPrivate* pimpl; +} +-(void)controlTextDidChange:(NSNotification*)notification; +-(void)controlTextDidEndEditing:(NSNotification*)aNotification; +@end + +@implementation QSearchFieldDelegate +-(void)controlTextDidChange:(NSNotification*)notification { + pimpl->textDidChange(toQString([[notification object] stringValue])); +} + +-(void)controlTextDidEndEditing:(NSNotification*)notification { + pimpl->textDidEndEditing(); +} +@end + +QSearchField::QSearchField(QWidget *parent) : QWidget(parent) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSSearchField *search = [[NSSearchField alloc] init]; + pimpl = new QSearchFieldPrivate(this, search); + + QSearchFieldDelegate *delegate = [[QSearchFieldDelegate alloc] init]; + delegate->pimpl = pimpl; + [search setDelegate:delegate]; + + zeroLayout(search, this); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + layout()->setContentsMargins(2, 0, 2, 0); + setStyleSheet( "* { background: #DDE4EB; }" ); + + setMinimumSize(layout()->sizeHint().width(), 20); + + [search release]; + [pool drain]; +} + +void QSearchField::setText(const QString &text) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [pimpl->nsSearchField setStringValue:fromQString(text)]; + [pool drain]; +} + +void QSearchField::setPlaceholderText(const QString& text) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [[pimpl->nsSearchField cell] setPlaceholderString:fromQString(text)]; + [pool drain]; +} + +void QSearchField::clear() +{ + [pimpl->nsSearchField setStringValue:@""]; +} + +QString QSearchField::text() const +{ + return toQString([pimpl->nsSearchField stringValue]); +} diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index bce5067d7..71f392dcf 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -435,6 +435,10 @@ IF( UNIX AND NOT APPLE ) infosystem/infoplugins/unix/mprispluginplayeradaptor.h infosystem/infoplugins/unix/mprisplugin.h infosystem/infoplugins/unix/fdonotifyplugin.h ) + + IF( BUILD_GUI AND X11_FOUND ) + SET( LINK_LIBRARIES ${LINK_LIBRARIES} ${X11_LIBRARIES} ) + ENDIF() ENDIF( UNIX AND NOT APPLE ) IF( WIN32 ) @@ -460,11 +464,9 @@ IF( APPLE ) SET( libSources ${libSources} infosystem/infoplugins/mac/adium.mm infosystem/infoplugins/mac/adiumplugin.cpp - widgets/maclineedit.mm utils/tomahawkutils_mac.mm ) SET( libHeaders ${libHeaders} - widgets/maclineedit.h infosystem/infoplugins/mac/adium.h infosystem/infoplugins/mac/adiumplugin.h ) diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index 9310ea43d..d14731106 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -137,7 +137,7 @@ AudioEngine::play() QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) ); } else - loadNextTrack(); + next(); } @@ -204,6 +204,11 @@ AudioEngine::next() bool AudioEngine::canGoNext() { + tDebug( LOGEXTRA ) << Q_FUNC_INFO; + + if ( m_queue && m_queue->trackCount() ) + return true; + if ( m_playlist.isNull() ) return false; @@ -212,14 +217,15 @@ AudioEngine::canGoNext() return false; if ( !m_currentTrack.isNull() && !m_playlist.data()->hasNextItem() && - m_currentTrack->id() == m_playlist.data()->currentItem()->id() ) + ( m_playlist.data()->currentItem().isNull() || ( m_currentTrack->id() == m_playlist.data()->currentItem()->id() ) ) ) { //For instance, when doing a catch-up while listening along, but the person //you're following hasn't started a new track yet...don't do anything + tDebug( LOGEXTRA ) << Q_FUNC_INFO << "catch up"; return false; } - - return true; + + return m_playlist.data()->hasNextItem(); } bool @@ -332,11 +338,16 @@ AudioEngine::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, return; } + if ( m_currentTrack.isNull() || + m_currentTrack->track().isNull() || + m_currentTrack->artist().isNull() ) + return; + QVariantMap playInfo; - playInfo["message"] = QString( "Tomahawk is playing \"%1\" by %2 on album %3." ) - .arg( m_currentTrack->track() ) - .arg( m_currentTrack->artist()->name() ) - .arg( m_currentTrack->album()->name() ); + playInfo["message"] = tr( "Tomahawk is playing \"%1\" by %2%3." ) + .arg( m_currentTrack->track() ) + .arg( m_currentTrack->artist()->name() ) + .arg( m_currentTrack->album().isNull() ? QString() : tr( " on album %1" ).arg( m_currentTrack->album()->name() ) ); if ( !output.isNull() && output.isValid() ) { QVariantMap returnedData = output.value< QVariantMap >(); @@ -495,11 +506,15 @@ AudioEngine::loadNextTrack() if ( !m_playlist.isNull() && result.isNull() ) { + tDebug( LOGEXTRA ) << Q_FUNC_INFO << " loading playlist's next item"; result = m_playlist.data()->nextItem(); } if ( !result.isNull() ) + { + tDebug( LOGEXTRA ) << Q_FUNC_INFO << " got next item, loading track"; loadTrack( result ); + } else { if ( !m_playlist.isNull() && m_playlist.data()->retryMode() == Tomahawk::PlaylistInterface::Retry ) @@ -589,7 +604,7 @@ AudioEngine::onStateChanged( Phonon::State newState, Phonon::State oldState ) { m_expectStop = false; tDebug( LOGEXTRA ) << "Finding next track."; - loadNextTrack(); + next(); } } } @@ -621,10 +636,15 @@ void AudioEngine::setPlaylist( PlaylistInterface* playlist ) { if ( !m_playlist.isNull() ) + { + if ( m_playlist.data()->object() && m_playlist.data()->retryMode() == PlaylistInterface::Retry ) + disconnect( m_playlist.data()->object(), SIGNAL( nextTrackReady() ) ); m_playlist.data()->reset(); + } if ( !playlist ) return; + m_playlist = playlist->getSharedPointer(); if ( m_playlist.data()->object() && m_playlist.data()->retryMode() == PlaylistInterface::Retry ) diff --git a/src/libtomahawk/database/databasecommand_addfiles.cpp b/src/libtomahawk/database/databasecommand_addfiles.cpp index 03511b951..2a9df9c74 100644 --- a/src/libtomahawk/database/databasecommand_addfiles.cpp +++ b/src/libtomahawk/database/databasecommand_addfiles.cpp @@ -27,6 +27,7 @@ #include "databasecommand_collectionstats.h" #include "databaseimpl.h" #include "network/controlconnection.h" +#include "sourcelist.h" #include "utils/logger.h" @@ -72,7 +73,15 @@ DatabaseCommand_AddFiles::postCommitHook() emit notify( m_queries ); if( source()->isLocal() ) + { Servent::instance()->triggerDBSync(); + + // Re-calculate local db stats + DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() ); + connect( cmd, SIGNAL( done( QVariantMap ) ), + SourceList::instance()->getLocal().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection ); + Database::instance()->enqueue( QSharedPointer( cmd ) ); + } } diff --git a/src/libtomahawk/database/databasecommand_allalbums.cpp b/src/libtomahawk/database/databasecommand_allalbums.cpp index f57bde620..cd6784864 100644 --- a/src/libtomahawk/database/databasecommand_allalbums.cpp +++ b/src/libtomahawk/database/databasecommand_allalbums.cpp @@ -74,8 +74,7 @@ DatabaseCommand_AllAlbums::execForArtist( DatabaseImpl* dbi ) al << album; } - if ( al.count() ) - emit albums( al, data() ); + emit albums( al, data() ); emit done(); } @@ -124,8 +123,7 @@ DatabaseCommand_AllAlbums::execForCollection( DatabaseImpl* dbi ) al << album; } - if ( al.count() ) - emit albums( al, data() ); + emit albums( al, data() ); emit done(); } diff --git a/src/libtomahawk/database/databasecommand_logplayback.cpp b/src/libtomahawk/database/databasecommand_logplayback.cpp index d0ea76350..3c1ad731c 100644 --- a/src/libtomahawk/database/databasecommand_logplayback.cpp +++ b/src/libtomahawk/database/databasecommand_logplayback.cpp @@ -45,11 +45,13 @@ DatabaseCommand_LogPlayback::postCommitHook() if ( m_action == Finished ) { + tDebug( LOGEXTRA ) << Q_FUNC_INFO << " logging finished from source " << source().data()->id(); emit trackPlayed( q ); } // if the play time is more than 10 minutes in the past, ignore else if ( m_action == Started && QDateTime::fromTime_t( playtime() ).secsTo( QDateTime::currentDateTime() ) < 600 ) { + tDebug( LOGEXTRA ) << Q_FUNC_INFO << " logging started from source " << source().data()->id(); emit trackPlaying( q ); } diff --git a/src/libtomahawk/dropjob.cpp b/src/libtomahawk/dropjob.cpp index be59f0166..3de1ea050 100644 --- a/src/libtomahawk/dropjob.cpp +++ b/src/libtomahawk/dropjob.cpp @@ -96,7 +96,24 @@ DropJob::acceptsMimeData( const QMimeData* data, bool tracksOnly ) void -DropJob::tracksFromMimeData( const QMimeData* data ) +DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates ) +{ + m_allowDuplicates = allowDuplicates; + + parseMimeData( data ); + + if ( m_queryCount == 0 ) + { + if ( !allowDuplicates ) + removeDuplicates(); + + emit tracks( m_resultList ); + deleteLater(); + } +} + +void +DropJob::parseMimeData( const QMimeData *data ) { QList< query_ptr > results; if ( data->hasFormat( "application/tomahawk.query.list" ) ) @@ -116,11 +133,7 @@ DropJob::tracksFromMimeData( const QMimeData* data ) handleTrackUrls ( plainData ); } - if ( !results.isEmpty() ) - { - emit tracks( results ); - deleteLater(); - } + m_resultList.append( results ); } QList< query_ptr > @@ -267,7 +280,7 @@ DropJob::tracksFromMixedData( const QMimeData *data ) } singleMimeData.setData( mimeType, singleData ); - tracksFromMimeData( &singleMimeData ); + parseMimeData( &singleMimeData ); } return queries; } @@ -282,14 +295,17 @@ DropJob::handleTrackUrls( const QString& urls ) tDebug() << "Got a list of spotify urls!" << tracks; SpotifyParser* spot = new SpotifyParser( tracks, this ); - connect( spot, SIGNAL( tracks( QList ) ), this, SIGNAL( tracks( QList ) ) ); + connect( spot, SIGNAL( tracks( QList ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) ); + m_queryCount++; } else if ( urls.contains( "rdio.com" ) ) { QStringList tracks = urls.split( "\n" ); tDebug() << "Got a list of rdio urls!" << tracks; RdioParser* rdio = new RdioParser( this ); - connect( rdio, SIGNAL( tracks( QList ) ), this, SIGNAL( tracks( QList ) ) ); + connect( rdio, SIGNAL( tracks( QList ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) ); + m_queryCount++; + rdio->parse( tracks ); } else if ( urls.contains( "bit.ly" ) || urls.contains( "j.mp" ) || @@ -301,6 +317,7 @@ DropJob::handleTrackUrls( const QString& urls ) tDebug() << "Got a list of shortened urls!" << tracks; ShortenedLinkParser* parser = new ShortenedLinkParser( tracks, this ); connect( parser, SIGNAL( urls( QStringList ) ), this, SLOT( expandedUrls( QStringList ) ) ); + m_queryCount++; } } @@ -308,14 +325,39 @@ DropJob::handleTrackUrls( const QString& urls ) void DropJob::expandedUrls( QStringList urls ) { + m_queryCount--; handleTrackUrls( urls.join( "\n" ) ); } void DropJob::onTracksAdded( const QList& tracksList ) { - qDebug() << "here i am with" << tracksList.count() << "tracks"; - emit tracks( tracksList ); + m_resultList.append( tracksList ); + if ( --m_queryCount == 0 ) + { + if ( !m_allowDuplicates ) + removeDuplicates(); + + emit tracks( m_resultList ); deleteLater(); + } +} + +void +DropJob::removeDuplicates() +{ + QList< Tomahawk::query_ptr > list; + foreach ( const Tomahawk::query_ptr& item, m_resultList ) + { + bool contains = false; + foreach( const Tomahawk::query_ptr &tmpItem, list ) + if ( item->album() == tmpItem->album() + && item->artist() == tmpItem->artist() + && item->track() == tmpItem->track() ) + contains = true; + if ( !contains ) + list.append( item ); + } + m_resultList = list; } diff --git a/src/libtomahawk/dropjob.h b/src/libtomahawk/dropjob.h index ea48ccea3..186417f9b 100644 --- a/src/libtomahawk/dropjob.h +++ b/src/libtomahawk/dropjob.h @@ -43,7 +43,7 @@ public: */ static bool acceptsMimeData( const QMimeData* data, bool tracksOnly = true ); static QStringList mimeTypes(); - void tracksFromMimeData( const QMimeData* data ); + void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false ); signals: /// QMimeData parsing results @@ -56,6 +56,8 @@ private slots: private: /// handle parsing mime data + void parseMimeData( const QMimeData* data ); + void handleTrackUrls( const QString& urls ); QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d ); QList< Tomahawk::query_ptr > tracksFromResultList( const QMimeData* d ); @@ -63,7 +65,12 @@ private: QList< Tomahawk::query_ptr > tracksFromAlbumMetaData( const QMimeData* d ); QList< Tomahawk::query_ptr > tracksFromMixedData( const QMimeData* d ); + void removeDuplicates(); + int m_queryCount; + bool m_allowDuplicates; + + QList< Tomahawk::query_ptr > m_resultList; }; #endif // DROPJOB_H diff --git a/src/libtomahawk/globalactionmanager.cpp b/src/libtomahawk/globalactionmanager.cpp index 9adaea326..eb3841e74 100644 --- a/src/libtomahawk/globalactionmanager.cpp +++ b/src/libtomahawk/globalactionmanager.cpp @@ -357,6 +357,8 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q if( queueSpotify( parts, queryItems ) ) return true; + else if( queueRdio( parts, queryItems ) ) + return true; QPair< QString, QString > pair; @@ -427,6 +429,26 @@ GlobalActionManager::queueSpotify( const QStringList& , const QList< QPair< QStr return true; } +bool +GlobalActionManager::queueRdio( const QStringList& , const QList< QPair< QString, QString > >& queryItems ) +{ + QString url; + + QPair< QString, QString > pair; + foreach( pair, queryItems ) { + if( pair.first == "rdioURL" ) + url = pair.second; + else if( pair.first == "rdioURI" ) + url = pair.second; + } + + if( url.isEmpty() ) + return false; + + openRdioLink( url ); + + return true; +} bool GlobalActionManager::handleSearchCommand( const QUrl& url ) @@ -617,6 +639,8 @@ GlobalActionManager::handlePlayCommand( const QUrl& url ) if( parts[ 0 ] == "track" ) { if( playSpotify( url ) ) return true; + else if( playRdio( url ) ) + return true; QPair< QString, QString > pair; QString title, artist, album, urlStr; @@ -652,13 +676,13 @@ GlobalActionManager::playSpotify( const QUrl& url ) QString spotifyUrl = url.hasQueryItem( "spotifyURI" ) ? url.queryItemValue( "spotifyURI" ) : url.queryItemValue( "spotifyURL" ); SpotifyParser* p = new SpotifyParser( spotifyUrl, this ); - connect( p, SIGNAL( track( Tomahawk::query_ptr ) ), this, SLOT( spotifyToPlay( Tomahawk::query_ptr ) ) ); + connect( p, SIGNAL( track( Tomahawk::query_ptr ) ), this, SLOT( playNow( Tomahawk::query_ptr ) ) ); return true; } void -GlobalActionManager::spotifyToPlay( const query_ptr& q ) +GlobalActionManager::playNow( const query_ptr& q ) { Pipeline::instance()->resolve( q, true ); @@ -666,6 +690,21 @@ GlobalActionManager::spotifyToPlay( const query_ptr& q ) connect( q.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( waitingForResolved( bool ) ) ); } +bool +GlobalActionManager::playRdio( const QUrl& url ) +{ + if( !url.hasQueryItem( "rdioURI" ) && !url.hasQueryItem( "rdioURL" ) ) + return false; + + + QString rdioUrl = url.hasQueryItem( "rdioURI" ) ? url.queryItemValue( "spotifyURI" ) : url.queryItemValue( "rdioURL" ); + RdioParser* p = new RdioParser( this ); + p->parse( rdioUrl ); + connect( p, SIGNAL( track( Tomahawk::query_ptr ) ), this, SLOT( playNow( Tomahawk::query_ptr ) ) ); + + return true; +} + bool GlobalActionManager::handleBookmarkCommand(const QUrl& url) { diff --git a/src/libtomahawk/globalactionmanager.h b/src/libtomahawk/globalactionmanager.h index 438b7676f..5c04502be 100644 --- a/src/libtomahawk/globalactionmanager.h +++ b/src/libtomahawk/globalactionmanager.h @@ -65,7 +65,7 @@ private slots: void xspfCreated( const QByteArray& xspf ); - void spotifyToPlay( const Tomahawk::query_ptr& ); + void playNow( const Tomahawk::query_ptr& ); private: explicit GlobalActionManager( QObject* parent = 0 ); void doBookmark( const Tomahawk::playlist_ptr& pl, const Tomahawk::query_ptr& q ); @@ -84,6 +84,8 @@ private: bool playSpotify( const QUrl& url ); bool queueSpotify( const QStringList& parts, const QList< QPair< QString, QString > >& queryItems ); + bool playRdio( const QUrl& url ); + bool queueRdio( const QStringList& parts, const QList< QPair< QString, QString > >& queryItems ); QString hostname() const; diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp index 73acc8f3b..875428b6b 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp @@ -493,7 +493,7 @@ MprisPlugin::audioStarted( const QVariant &input ) return; m_playbackStatus = "Playing"; - //notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata"); + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata"); //hash["artist"]; //hash["title"]; @@ -576,15 +576,16 @@ MprisPlugin::onTrackCountChanged( unsigned int tracks ) void MprisPlugin::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ) { + // If the caller for the request was not us, or not the type of info we are seeking, ignore it if ( requestData.caller != s_mpInfoIdentifier || requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt ) { - notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); + //notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); return; } if ( !output.canConvert< QVariantMap >() ) { - notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); + //notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); tDebug( LOGINFO ) << "Cannot convert fetched art from a QByteArray"; return; } @@ -610,7 +611,8 @@ MprisPlugin::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, // delete the old tempfile and make new one, to avoid caching of filename by mpris clients if( m_coverTempFile ) delete m_coverTempFile; - m_coverTempFile = new QTemporaryFile( hash["artist"] + "_" + hash["album"] + "_tomahawk_cover.png" ); + m_coverTempFile = new QTemporaryFile( QDir::toNativeSeparators( + QDir::tempPath() + "/" + hash["artist"] + "_" + hash["album"] + "_tomahawk_cover.png" ) ); if( !m_coverTempFile->open() ) { qDebug() << "WARNING: could not write temporary file for cover art!"; @@ -622,11 +624,16 @@ MprisPlugin::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, { qDebug() << Q_FUNC_INFO << "Image saving successful, notifying"; qDebug() << "Saving to: " << QFileInfo( *m_coverTempFile ).absoluteFilePath(); + m_coverTempFile->close(); + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); } else + { qDebug() << Q_FUNC_INFO << " failed to save image!"; + m_coverTempFile->close(); + } + - m_coverTempFile->close(); /* if( m_coverTempFile->open() ) @@ -638,8 +645,6 @@ MprisPlugin::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, } */ } - - notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); } diff --git a/src/libtomahawk/network/servent.cpp b/src/libtomahawk/network/servent.cpp index cad2cafb4..b6b2df215 100644 --- a/src/libtomahawk/network/servent.cpp +++ b/src/libtomahawk/network/servent.cpp @@ -153,7 +153,7 @@ Servent::startListening( QHostAddress ha, bool upnp, int port ) if ( qApp->arguments().contains( "--lanhack" ) ) { - qDebug() << "LANHACK: set external address to lan address" << ha.toString(); + tLog() << "LANHACK: set external address to lan address" << ha.toString(); QMetaObject::invokeMethod( this, "setExternalAddress", Qt::QueuedConnection, Q_ARG( QHostAddress, ha ), Q_ARG( unsigned int, m_port ) ); } else @@ -191,7 +191,7 @@ Servent::createConnectionKey( const QString& name, const QString &nodeid, const cc->setId( nodeid ); cc->setOnceOnly( onceOnly ); - qDebug() << "Creating connection key with name of " << cc->name() << " and id of " << cc->id() << " and key of " << _key << "; key is once only? : " << (onceOnly ? "true" : "false"); + qDebug() << "Creating connection key with name of" << cc->name() << "and id of" << cc->id() << "and key of" << _key << "; key is once only? :" << (onceOnly ? "true" : "false"); registerOffer( _key, cc ); return _key; } @@ -229,7 +229,7 @@ Servent::setExternalAddress( QHostAddress ha, unsigned int port ) qDebug() << m_externalHostname << m_externalPort; } else - qDebug() << "No external access, LAN and outbound connections only!"; + tLog() << "No external access, LAN and outbound connections only!"; } m_ready = true; @@ -354,7 +354,7 @@ Servent::readyRead() // qDebug() << con->socket() << sock; if( con->id() == nodeid ) { - qDebug() << "Duplicate control connection detected, dropping:" << nodeid << conntype; + tLog() << "Duplicate control connection detected, dropping:" << nodeid << conntype; goto closeconnection; } } @@ -378,7 +378,7 @@ Servent::readyRead() Connection* conn = claimOffer( cc, nodeid, key, sock->peerAddress() ); if( !conn ) { - qDebug() << "claimOffer FAILED, key:" << key; + tLog() << "claimOffer FAILED, key:" << key; goto closeconnection; } qDebug() << "claimOffer OK:" << key; @@ -396,7 +396,7 @@ Servent::readyRead() // fallthru to cleanup: closeconnection: - qDebug() << "Closing incoming connection, something was wrong."; + tLog() << "Closing incoming connection, something was wrong."; sock->_msg.clear(); sock->disconnectFromHost(); } @@ -411,7 +411,7 @@ Servent::createParallelConnection( Connection* orig_conn, Connection* new_conn, // if we can connect to them directly: if( orig_conn && orig_conn->outbound() ) { - qDebug() << "Connecting directly"; + tLog() << "Connecting directly"; connectToPeer( orig_conn->socket()->peerAddress().toString(), orig_conn->peerPort(), key, @@ -420,7 +420,7 @@ Servent::createParallelConnection( Connection* orig_conn, Connection* new_conn, else // ask them to connect to us: { QString tmpkey = uuid(); - qDebug() << "Asking them to connect to us using" << tmpkey ; + tLog() << "Asking them to connect to us using" << tmpkey ; registerOffer( tmpkey, new_conn ); QVariantMap m; @@ -476,12 +476,12 @@ Servent::socketError( QAbstractSocket::SocketError e ) QTcpSocketExtra* sock = (QTcpSocketExtra*)sender(); if( !sock ) { - qDebug() << "SocketError, sock is null"; + tLog() << "SocketError, sock is null"; return; } Connection* conn = sock->_conn; - qDebug() << "Servent::SocketError:" << e << conn->id() << conn->name(); + tLog() << "Servent::SocketError:" << e << conn->id() << conn->name(); if( !sock->_disowned ) { // connection will delete if we already transferred ownership, otherwise: @@ -607,7 +607,7 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString } if( !authed ) { - qDebug() << "File transfer request rejected, invalid source IP"; + tLog() << "File transfer request rejected, invalid source IP"; return NULL; } } @@ -641,7 +641,7 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString // This can happen if it's a streamconnection, but the audioengine has // already closed the iodevice, causing the connection to be deleted before // the peer connects and provides the first byte - qDebug() << Q_FUNC_INFO << "invalid/expired offer:" << key; + tLog() << Q_FUNC_INFO << "invalid/expired offer:" << key; return NULL; } @@ -650,12 +650,12 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString // If there isn't a nodeid it's not the first connection and will already have been stopped if( !checkACL( conn, nodeid, true ) ) { - qDebug() << "Connection not allowed due to ACL"; + tLog() << "Connection not allowed due to ACL"; return NULL; } } - qDebug() << "ACL has allowed the connection"; + tLog() << "ACL has allowed the connection"; if( conn->onceOnly() ) { @@ -676,7 +676,7 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString } else { - qDebug() << "Invalid offer key:" << key; + tLog() << "Invalid offer key:" << key; return NULL; } } @@ -829,7 +829,6 @@ Servent::isIPWhitelisted( QHostAddress ip ) bool Servent::connectedToSession( const QString& session ) { - qDebug() << Q_FUNC_INFO; // qDebug() << "Checking against" << session; foreach( ControlConnection* cc, m_controlconnections ) { @@ -845,8 +844,6 @@ Servent::connectedToSession( const QString& session ) void Servent::triggerDBSync() { - qDebug() << Q_FUNC_INFO; - // tell peers we have new stuff they should sync QList sources = SourceList::instance()->sources(); foreach( const source_ptr& src, sources ) @@ -872,7 +869,6 @@ Servent::registerIODeviceFactory( const QString &proto, boost::function Servent::getIODeviceForUrl( const Tomahawk::result_ptr& result ) { - qDebug() << Q_FUNC_INFO << thread(); QSharedPointer sp; QRegExp rx( "^([a-zA-Z0-9]+)://(.+)$" ); @@ -903,7 +899,6 @@ Servent::localFileIODeviceFactory( const Tomahawk::result_ptr& result ) QSharedPointer Servent::httpIODeviceFactory( const Tomahawk::result_ptr& result ) { - qDebug() << Q_FUNC_INFO << result->url(); QNetworkRequest req( result->url() ); QNetworkReply* reply = TomahawkUtils::nam()->get( req ); return QSharedPointer( reply, &QObject::deleteLater ); diff --git a/src/libtomahawk/pipeline.cpp b/src/libtomahawk/pipeline.cpp index 3e055d512..fc9789b6e 100644 --- a/src/libtomahawk/pipeline.cpp +++ b/src/libtomahawk/pipeline.cpp @@ -116,11 +116,13 @@ Pipeline::resolve( const QList& qlist, bool prioritized, bool tempora int i = 0; foreach( const query_ptr& q, qlist ) { - if ( !m_qids.contains( q->id() ) ) - m_qids.insert( q->id(), q ); - if ( m_queries_pending.contains( q ) ) continue; + if ( m_qidsState.contains( q->id() ) ) + continue; + + if ( !m_qids.contains( q->id() ) ) + m_qids.insert( q->id(), q ); if ( prioritized ) m_queries_pending.insert( i++, q ); @@ -169,8 +171,7 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results ) if ( !m_qids.contains( qid ) ) { - qDebug() << "reportResults called for unknown QID" << qid; - Q_ASSERT( false ); + tDebug() << "Result arrived too late for:" << qid; return; } @@ -183,35 +184,14 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results ) m_rids.insert( r->id(), r ); } - if ( q->solved() && !q->isFullTextQuery() ) + if ( q->playable() && !q->isFullTextQuery() ) { - q->onResolvingFinished(); - setQIDState( q, 0 ); - if ( m_qidsTimeout.contains( q->id() ) ) - m_qidsTimeout.remove( q->id() ); - - shuntNext(); return; } } - if ( decQIDState( q ) == 0 ) - { - if ( !q->solved() || q->isFullTextQuery() ) - q->onResolvingFinished(); - - if ( !m_queries_temporary.contains( q ) ) - m_qids.remove( q->id() ); - if ( m_qidsTimeout.contains( q->id() ) ) - m_qidsTimeout.remove( q->id() ); - - shuntNext(); - } - else - { - new FuncTimeout( 0, boost::bind( &Pipeline::timeoutShunt, this, q ), this ); - } + decQIDState( q ); } @@ -247,7 +227,6 @@ Pipeline::shuntNext() } setQIDState( q, rc ); - new FuncTimeout( 0, boost::bind( &Pipeline::shunt, this, q ), this ); } @@ -260,8 +239,7 @@ Pipeline::timeoutShunt( const query_ptr& q ) // are we still waiting for a timeout? if ( m_qidsTimeout.contains( q->id() ) ) { - m_qidsTimeout.remove( q->id() ); - shunt( q ); + decQIDState( q ); } } @@ -278,7 +256,7 @@ Pipeline::shunt( const query_ptr& q ) if ( r ) { - qDebug() << "Dispatching to resolver" << r->name() << q->toString() << q->solved() << q->id(); + tDebug() << "Dispatching to resolver" << r->name() << q->toString() << q->solved() << q->id(); q->setCurrentResolver( r ); r->resolve( q ); @@ -291,7 +269,9 @@ Pipeline::shunt( const query_ptr& q ) } else { + // we get here if we disable a resolver while a query is resolving setQIDState( q, 0 ); + return; } shuntNext(); @@ -327,14 +307,24 @@ Pipeline::setQIDState( const Tomahawk::query_ptr& query, int state ) { QMutexLocker lock( &m_mut ); + if ( m_qidsTimeout.contains( query->id() ) ) + m_qidsTimeout.remove( query->id() ); + if ( state > 0 ) { m_qidsState.insert( query->id(), state ); + + new FuncTimeout( 0, boost::bind( &Pipeline::shunt, this, query ), this ); } else { m_qidsState.remove( query->id() ); -// qDebug() << "Queries running:" << m_qidsState.count(); + query->onResolvingFinished(); + + if ( !m_queries_temporary.contains( query ) ) + m_qids.remove( query->id() ); + + new FuncTimeout( 0, boost::bind( &Pipeline::shuntNext, this ), this ); } } @@ -358,22 +348,17 @@ Pipeline::incQIDState( const Tomahawk::query_ptr& query ) int Pipeline::decQIDState( const Tomahawk::query_ptr& query ) { - QMutexLocker lock( &m_mut ); - - if ( !m_qidsState.contains( query->id() ) ) - return 0; - - int state = m_qidsState.value( query->id() ) - 1; - if ( state ) + int state = 0; { - m_qidsState.insert( query->id(), state ); - } - else - { - m_qidsState.remove( query->id() ); -// qDebug() << "Queries running:" << m_qidsState.count(); + QMutexLocker lock( &m_mut ); + + if ( !m_qidsState.contains( query->id() ) ) + return 0; + + state = m_qidsState.value( query->id() ) - 1; } + setQIDState( query, state ); return state; } diff --git a/src/libtomahawk/playlist.cpp b/src/libtomahawk/playlist.cpp index 2712bbe30..1b5f037aa 100644 --- a/src/libtomahawk/playlist.cpp +++ b/src/libtomahawk/playlist.cpp @@ -119,7 +119,7 @@ Playlist::Playlist( const source_ptr& src, , m_currentItem( 0 ) , m_busy( false ) { -// qDebug() << Q_FUNC_INFO << "1"; + qDebug() << Q_FUNC_INFO << "1" << title; init(); } @@ -144,7 +144,7 @@ Playlist::Playlist( const source_ptr& author, , m_initEntries( entries ) , m_busy( false ) { -// qDebug() << Q_FUNC_INFO << "2"; + qDebug() << Q_FUNC_INFO << "2" << title; init(); } diff --git a/src/libtomahawk/playlist/albummodel.cpp b/src/libtomahawk/playlist/albummodel.cpp index f721e79b5..ebb2bb002 100644 --- a/src/libtomahawk/playlist/albummodel.cpp +++ b/src/libtomahawk/playlist/albummodel.cpp @@ -35,6 +35,7 @@ using namespace Tomahawk; AlbumModel::AlbumModel( QObject* parent ) : QAbstractItemModel( parent ) , m_rootItem( new AlbumItem( 0, this ) ) + , m_overwriteOnAdd( false ) { qDebug() << Q_FUNC_INFO; @@ -236,13 +237,14 @@ AlbumModel::removeIndexes( const QList& indexes ) void -AlbumModel::addCollection( const collection_ptr& collection ) +AlbumModel::addCollection( const collection_ptr& collection, bool overwrite ) { qDebug() << Q_FUNC_INFO << collection->name() << collection->source()->id() << collection->source()->userName(); DatabaseCommand_AllAlbums* cmd = new DatabaseCommand_AllAlbums( collection ); + m_overwriteOnAdd = overwrite; connect( cmd, SIGNAL( albums( QList, QVariant ) ), SLOT( addAlbums( QList ) ) ); @@ -254,7 +256,7 @@ AlbumModel::addCollection( const collection_ptr& collection ) void -AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order ) +AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order, bool overwrite ) { /* qDebug() << Q_FUNC_INFO << collection->name() << collection->source()->id() @@ -265,6 +267,7 @@ AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned in cmd->setLimit( amount ); cmd->setSortOrder( order ); cmd->setSortDescending( true ); + m_overwriteOnAdd = overwrite; connect( cmd, SIGNAL( albums( QList, QVariant ) ), SLOT( addAlbums( QList ) ) ); @@ -284,6 +287,9 @@ AlbumModel::addAlbums( const QList& albums ) if ( !albums.count() ) return; + if ( m_overwriteOnAdd ) + clear(); + int c = rowCount( QModelIndex() ); QPair< int, int > crows; crows.first = c; @@ -347,7 +353,8 @@ AlbumModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, Q if ( !pm.isNull() ) ai->cover = pm; - emit dataChanged( ai->index, ai->index.sibling( ai->index.row(), columnCount( QModelIndex() ) - 1 ) ); + if ( ai->index.isValid() ) + emit dataChanged( ai->index, ai->index.sibling( ai->index.row(), columnCount( QModelIndex() ) - 1 ) ); } } diff --git a/src/libtomahawk/playlist/albummodel.h b/src/libtomahawk/playlist/albummodel.h index 3730acde4..18945f4f4 100644 --- a/src/libtomahawk/playlist/albummodel.h +++ b/src/libtomahawk/playlist/albummodel.h @@ -63,8 +63,8 @@ public: virtual QStringList mimeTypes() const; virtual Qt::ItemFlags flags( const QModelIndex& index ) const; - void addCollection( const Tomahawk::collection_ptr& collection ); - void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order ); + void addCollection( const Tomahawk::collection_ptr& collection, bool overwrite = false ); + void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order, bool overwrite = false ); void clear(); @@ -109,6 +109,7 @@ private: QString m_title; QString m_description; + bool m_overwriteOnAdd; }; #endif // ALBUMMODEL_H diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp index 22dafb554..2b72fce03 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp @@ -412,7 +412,7 @@ query_ptr EchonestGenerator::queryFromSong( const Echonest::Song& song ) { // track[ "album" ] = song.release(); // TODO should we include it? can be quite specific - return Query::get( song.artistName(), song.title(), QString(), uuid() ); + return Query::get( song.artistName(), song.title(), QString(), uuid(), false ); } diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp index 872d09726..8da3b345a 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp @@ -452,7 +452,6 @@ void DynamicWidget::onDeleted() { emit destroyed( widget() ); - deleteLater(); } diff --git a/src/libtomahawk/playlist/playlistview.cpp b/src/libtomahawk/playlist/playlistview.cpp index 3ffe81a0c..a34c60650 100644 --- a/src/libtomahawk/playlist/playlistview.cpp +++ b/src/libtomahawk/playlist/playlistview.cpp @@ -62,8 +62,10 @@ PlaylistView::setPlaylistModel( PlaylistModel* model ) TrackView::setTrackModel( m_model ); setColumnHidden( TrackModel::Age, true ); // Hide age column per default - if ( !m_model->playlist().isNull() ) + if ( guid().isEmpty() && !m_model->playlist().isNull() ) + { setGuid( QString( "playlistview/%1/%2" ).arg( m_model->columnCount() ).arg( m_model->playlist()->guid() ) ); + } else { setGuid( QString( "playlistview/%1" ).arg( m_model->columnCount() ) ); @@ -125,7 +127,6 @@ PlaylistView::onDeleted() { qDebug() << Q_FUNC_INFO; emit destroyed( widget() ); - deleteLater(); } diff --git a/src/libtomahawk/playlist/topbar/searchbutton.cpp b/src/libtomahawk/playlist/topbar/searchbutton.cpp index eae909119..779c75911 100644 --- a/src/libtomahawk/playlist/topbar/searchbutton.cpp +++ b/src/libtomahawk/playlist/topbar/searchbutton.cpp @@ -110,6 +110,7 @@ void SearchButton::paintEvent(QPaintEvent *event) if (m_cache.isNull()) m_cache = generateSearchImage(m_showMenuTriangle); QPainter painter(this); + painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.drawImage(QPoint(0, 0), m_cache); } diff --git a/src/libtomahawk/playlist/trackheader.cpp b/src/libtomahawk/playlist/trackheader.cpp index cfaf0801e..38893e85b 100644 --- a/src/libtomahawk/playlist/trackheader.cpp +++ b/src/libtomahawk/playlist/trackheader.cpp @@ -71,11 +71,11 @@ TrackHeader::visibleSectionCount() const } -void +bool TrackHeader::checkState() { if ( !count() || m_init ) - return; + return false; QByteArray state = TomahawkSettings::instance()->playlistColumnSizes( m_parent->guid() ); if ( !state.isEmpty() ) @@ -88,7 +88,7 @@ TrackHeader::checkState() else { QList< double > m_columnWeights; - m_columnWeights << 0.20 << 0.20 << 0.18 << 0.05 << 0.05 << 0.05 << 0.05 << 0.05 << 0.10; // << 0.05; + m_columnWeights << 0.18 << 0.18 << 0.17 << 0.05 << 0.05 << 0.05 << 0.05 << 0.05 << 0.10 << 0.05; // << 0.05; for ( int i = 0; i < count() - 1; i++ ) { @@ -102,6 +102,7 @@ TrackHeader::checkState() } m_init = true; + return true; } diff --git a/src/libtomahawk/playlist/trackheader.h b/src/libtomahawk/playlist/trackheader.h index 49aa0ec7a..6bed2492a 100644 --- a/src/libtomahawk/playlist/trackheader.h +++ b/src/libtomahawk/playlist/trackheader.h @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -40,7 +40,7 @@ public: public slots: void toggleVisibility( int index ); - void checkState(); + bool checkState(); protected: void contextMenuEvent( QContextMenuEvent* e ); diff --git a/src/libtomahawk/playlist/trackmodel.cpp b/src/libtomahawk/playlist/trackmodel.cpp index 96c7cbc93..458c618f7 100644 --- a/src/libtomahawk/playlist/trackmodel.cpp +++ b/src/libtomahawk/playlist/trackmodel.cpp @@ -93,7 +93,7 @@ TrackModel::columnCount( const QModelIndex& parent ) const case Detailed: default: - return 10; + return 11; break; } } @@ -205,6 +205,10 @@ TrackModel::data( const QModelIndex& index, int role ) const case Score: return query->results().first()->score(); break; + + case AlbumPos: + return query->results().first()->albumpos(); + break; } } @@ -217,7 +221,7 @@ TrackModel::headerData( int section, Qt::Orientation orientation, int role ) con { Q_UNUSED( orientation ); QStringList headers; - headers << tr( "Artist" ) << tr( "Track" ) << tr( "Album" ) << tr( "Duration" ) << tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Score" ); + headers << tr( "Artist" ) << tr( "Title" ) << tr( "Album" ) << tr( "Duration" ) << tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Score" ) << tr( "Track" ); if ( role == Qt::DisplayRole && section >= 0 ) { return headers.at( section ); diff --git a/src/libtomahawk/playlist/trackmodel.h b/src/libtomahawk/playlist/trackmodel.h index 6266d41d2..9a81c970f 100644 --- a/src/libtomahawk/playlist/trackmodel.h +++ b/src/libtomahawk/playlist/trackmodel.h @@ -49,7 +49,8 @@ public: Year = 6, Filesize = 7, Origin = 8, - Score = 9 + Score = 9, + AlbumPos = 10 }; explicit TrackModel( QObject* parent = 0 ); diff --git a/src/libtomahawk/playlist/trackproxymodel.cpp b/src/libtomahawk/playlist/trackproxymodel.cpp index cf1c5bd94..db02960af 100644 --- a/src/libtomahawk/playlist/trackproxymodel.cpp +++ b/src/libtomahawk/playlist/trackproxymodel.cpp @@ -177,7 +177,7 @@ Tomahawk::result_ptr TrackProxyModel::currentItem() const { TrackModelItem* item = itemFromIndex( mapToSource( currentIndex() ) ); - if ( item && item->query()->playable() ) + if ( item && !item->query().isNull() && item->query()->playable() ) return item->query()->results().at( 0 ); return Tomahawk::result_ptr(); } @@ -318,8 +318,8 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c unsigned int albumpos1 = 0, albumpos2 = 0; unsigned int bitrate1 = 0, bitrate2 = 0; unsigned int mtime1 = 0, mtime2 = 0; - unsigned int id1 = 0, id2 = 0; unsigned int size1 = 0, size2 = 0; + qint64 id1 = 0, id2 = 0; if ( q1->numResults() ) { @@ -346,6 +346,13 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c size2 = r->size(); } + // This makes it a stable sorter and prevents items from randomly jumping about. + if ( id1 == id2 ) + { + id1 = (qint64)&q1; + id2 = (qint64)&q2; + } + if ( left.column() == TrackModel::Artist ) // sort by artist { if ( artist1 == artist2 ) diff --git a/src/libtomahawk/playlist/trackview.cpp b/src/libtomahawk/playlist/trackview.cpp index 444512a22..99c1d4cbc 100644 --- a/src/libtomahawk/playlist/trackview.cpp +++ b/src/libtomahawk/playlist/trackview.cpp @@ -62,8 +62,7 @@ TrackView::TrackView( QWidget* parent ) setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); setRootIsDecorated( false ); setUniformRowHeights( true ); - setMinimumWidth( 300 ); - // setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn ); + setMinimumWidth( 200 ); setHeader( m_header ); setSortingEnabled( true ); @@ -204,7 +203,15 @@ void TrackView::resizeEvent( QResizeEvent* event ) { QTreeView::resizeEvent( event ); - m_header->checkState(); + + int sortSection = m_header->sortIndicatorSection(); + Qt::SortOrder sortOrder = m_header->sortIndicatorOrder(); + + if ( m_header->checkState() && sortSection >= 0 ) + { + // restoreState keeps overwriting our previous sort-order + sortByColumn( sortSection, sortOrder ); + } } diff --git a/src/libtomahawk/playlist/treemodel.cpp b/src/libtomahawk/playlist/treemodel.cpp index 03c0a36a3..eb1d1c63e 100644 --- a/src/libtomahawk/playlist/treemodel.cpp +++ b/src/libtomahawk/playlist/treemodel.cpp @@ -526,6 +526,8 @@ void TreeModel::onAlbumsAdded( const QList& albums, const QVariant& data ) { qDebug() << Q_FUNC_INFO << albums.count() << data.toInt(); + + emit loadingFinished(); if ( !albums.count() ) return; @@ -568,8 +570,6 @@ TreeModel::onAlbumsAdded( const QList& albums, const QVaria emit endInsertRows(); else emit dataChanged( albumitem->index, albumitem->index.sibling( albumitem->index.row(), columnCount( QModelIndex() ) - 1 ) ); - - emit loadingFinished(); } @@ -577,6 +577,8 @@ void TreeModel::onTracksAdded( const QList& tracks, const QVariant& data ) { qDebug() << Q_FUNC_INFO << tracks.count(); + + emit loadingFinished(); if ( !tracks.count() ) return; @@ -610,8 +612,6 @@ TreeModel::onTracksAdded( const QList& tracks, const QVaria emit endInsertRows(); emit dataChanged( item->index.sibling( 0, 0 ), item->index.sibling( item->index.row(), columnCount( QModelIndex() ) - 1 ) ); - - emit loadingFinished(); } diff --git a/src/libtomahawk/playlist/treeproxymodel.cpp b/src/libtomahawk/playlist/treeproxymodel.cpp index a19f39af2..4dbd8e0c3 100644 --- a/src/libtomahawk/playlist/treeproxymodel.cpp +++ b/src/libtomahawk/playlist/treeproxymodel.cpp @@ -81,8 +81,11 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent QList< Tomahawk::result_ptr > rl = m_cache.values( sourceParent ); foreach ( const Tomahawk::result_ptr& result, rl ) { - if ( result->track() == pi->result()->track() ) + if ( result->track() == pi->result()->track() && + ( result->albumpos() == pi->result()->albumpos() || result->albumpos() == 0 ) ) + { return ( result.data() == pi->result().data() ); + } } for ( int i = 0; i < sourceModel()->rowCount( sourceParent ); i++ ) @@ -91,7 +94,9 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent continue; TreeModelItem* ti = sourceModel()->itemFromIndex( sourceModel()->index( i, 0, sourceParent ) ); - if ( ti->result()->track() == pi->result()->track() ) + + if ( ti->result()->track() == pi->result()->track() && + ( ti->result()->albumpos() == pi->result()->albumpos() || ti->result()->albumpos() == 0 ) ) { if ( !pi->result()->isOnline() && ti->result()->isOnline() ) return false; @@ -142,7 +147,7 @@ TreeProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) co return p1->result()->albumpos() < p2->result()->albumpos(); if ( lefts == rights ) - return p1->result()->dbid() < p2->result()->dbid(); + return (qint64)&p1 < (qint64)&p2; } return QString::localeAwareCompare( lefts, rights ) < 0; diff --git a/src/libtomahawk/query.cpp b/src/libtomahawk/query.cpp index 6215d7286..ad0f7ad7d 100644 --- a/src/libtomahawk/query.cpp +++ b/src/libtomahawk/query.cpp @@ -176,6 +176,8 @@ Query::onResolvingFinished() if ( !m_resolveFinished ) { m_resolveFinished = true; + m_resolvers.clear(); + emit resolvingFinished( m_solved ); } } diff --git a/src/libtomahawk/sourceplaylistinterface.cpp b/src/libtomahawk/sourceplaylistinterface.cpp index 02b9e3c4b..2226bf309 100644 --- a/src/libtomahawk/sourceplaylistinterface.cpp +++ b/src/libtomahawk/sourceplaylistinterface.cpp @@ -47,16 +47,16 @@ SourcePlaylistInterface::siblingItem( int itemsAway ) Tomahawk::result_ptr SourcePlaylistInterface::nextItem() { - qDebug() << Q_FUNC_INFO; + tDebug( LOGEXTRA ) << Q_FUNC_INFO; if ( m_source.isNull() || m_source->currentTrack().isNull() || m_source->currentTrack()->results().isEmpty() ) { - qDebug() << Q_FUNC_INFO << " Results were empty for current track or source no longer valid"; + tDebug( LOGEXTRA ) << Q_FUNC_INFO << " Results were empty for current track or source no longer valid"; m_currentItem = Tomahawk::result_ptr(); return m_currentItem; } else if ( !m_gotNextItem ) { - qDebug() << Q_FUNC_INFO << " This song was already fetched"; + tDebug( LOGEXTRA ) << Q_FUNC_INFO << " This song was already fetched"; return Tomahawk::result_ptr(); } @@ -69,6 +69,7 @@ SourcePlaylistInterface::nextItem() bool SourcePlaylistInterface::hasNextItem() { + tDebug( LOGEXTRA ) << Q_FUNC_INFO; if ( m_source.isNull() || m_source->currentTrack().isNull() || m_source->currentTrack()->results().isEmpty() ) return false; @@ -96,7 +97,7 @@ SourcePlaylistInterface::reset() void SourcePlaylistInterface::onSourcePlaybackStarted( const Tomahawk::query_ptr& query ) { - qDebug() << Q_FUNC_INFO; + tDebug( LOGEXTRA ) << Q_FUNC_INFO; connect( query.data(), SIGNAL( resolvingFinished( bool ) ), SLOT( resolvingFinished( bool ) ) ); Pipeline::instance()->resolve( query, true ); m_gotNextItem = true; @@ -106,7 +107,7 @@ SourcePlaylistInterface::onSourcePlaybackStarted( const Tomahawk::query_ptr& que void SourcePlaylistInterface::resolvingFinished( bool hasResults ) { - qDebug() << Q_FUNC_INFO << " and has results? : " << (hasResults ? "true" : "false"); + tDebug( LOGEXTRA ) << Q_FUNC_INFO << " and has results? : " << (hasResults ? "true" : "false"); if ( hasResults ) emit nextTrackReady(); } \ No newline at end of file diff --git a/src/libtomahawk/utils/rdioparser.cpp b/src/libtomahawk/utils/rdioparser.cpp index a10ab2462..8be1a40d2 100644 --- a/src/libtomahawk/utils/rdioparser.cpp +++ b/src/libtomahawk/utils/rdioparser.cpp @@ -20,6 +20,7 @@ #include #include +#include "shortenedlinkparser.h" using namespace Tomahawk; @@ -55,6 +56,13 @@ RdioParser::parse( const QStringList& urls ) void RdioParser::parseUrl( const QString& url ) { + if ( url.contains( "rd.io" ) ) // shortened + { + ShortenedLinkParser* p = new ShortenedLinkParser( QStringList() << url, this ); + connect( p, SIGNAL( urls( QStringList ) ), this, SLOT( expandedLinks( QStringList ) ) ); + return; + } + query_ptr query; m_count++; @@ -99,3 +107,13 @@ RdioParser::parseUrl( const QString& url ) emit track( query ); } +void +RdioParser::expandedLinks( const QStringList& urls ) +{ + foreach( const QString& url, urls ) + { + if ( url.contains( "rdio.com" ) || url.contains( "rd.io" ) ) + parseUrl( url ); + } +} + diff --git a/src/libtomahawk/utils/rdioparser.h b/src/libtomahawk/utils/rdioparser.h index 8d2cece5b..669905f97 100644 --- a/src/libtomahawk/utils/rdioparser.h +++ b/src/libtomahawk/utils/rdioparser.h @@ -49,6 +49,9 @@ signals: void track( const Tomahawk::query_ptr& track ); void tracks( const QList< Tomahawk::query_ptr > tracks ); +private slots: + void expandedLinks( const QStringList& ); + private: void parseUrl( const QString& url ); diff --git a/src/libtomahawk/utils/tomahawkutils.cpp b/src/libtomahawk/utils/tomahawkutils.cpp index 3c792f63e..eb5e0a40d 100644 --- a/src/libtomahawk/utils/tomahawkutils.cpp +++ b/src/libtomahawk/utils/tomahawkutils.cpp @@ -18,15 +18,17 @@ #include "tomahawkutils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "headlesscheck.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include #ifdef WIN32 #include @@ -38,6 +40,18 @@ #include #endif +#ifndef TOMAHAWK_HEADLESS + #include + #include + + #ifdef Q_WS_X11 + extern "C" { + #include + } + #endif +#endif + + #include #include "utils/logger.h" #include "config.h" @@ -331,7 +345,7 @@ createDragPixmap( int itemCount ) int y = 0; for( int i = 0; i < itemCount; ++i ) { - const QPixmap pixmap = QPixmap( QString( ":/data/icons/audio-x-generic-%2x%2.png" ).arg( size ) ); + const QPixmap pixmap = QPixmap( QString( ":/data/images/track-icon-%2x%2.png" ).arg( size ) ); painter.drawPixmap( x, y, pixmap ); x += size + 1; @@ -505,15 +519,51 @@ setNam( QNetworkAccessManager* nam ) s_nam = QWeakPointer< QNetworkAccessManager >( nam ); } +#ifndef TOMAHAWK_HEADLESS + #if defined(Q_WS_X11) + void + bringToFront() + { + qDebug() << Q_FUNC_INFO; + QWidgetList widgetList = qApp->topLevelWidgets(); + int i = 0; + while( !widgetList.at( i )->isWindow() ) + i++; + QWidget *widget = widgetList.at( i ); -#ifndef Q_OS_MAC -void -bringToFront() -{ -} + WId winId = widget->winId(); + Display *display = XOpenDisplay( NULL ); + if ( !display ) + { + qDebug() << Q_FUNC_INFO << "Could not find display to raise"; + return; + } + + XRaiseWindow( display, winId ); + XSetInputFocus( display, winId, RevertToNone, CurrentTime ); + //widget->activateWindow(); + //widget->raise(); + } + #elif defined(Q_WS_WIN) + void + bringToFront() + { + } + #else + #ifndef Q_OS_MAC + void + bringToFront() + { + } + #endif + #endif +#else + void + bringToFront() + { + } #endif - QPixmap createAvatarFrame( const QPixmap &avatar ) { diff --git a/src/libtomahawk/utils/tomahawkutils.h b/src/libtomahawk/utils/tomahawkutils.h index aef43d509..1fe759bc5 100644 --- a/src/libtomahawk/utils/tomahawkutils.h +++ b/src/libtomahawk/utils/tomahawkutils.h @@ -21,11 +21,11 @@ #include "dllmacro.h" -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #define RESPATH ":/data/" diff --git a/src/libtomahawk/viewmanager.cpp b/src/libtomahawk/viewmanager.cpp index de59744a0..06679d1ab 100644 --- a/src/libtomahawk/viewmanager.cpp +++ b/src/libtomahawk/viewmanager.cpp @@ -75,7 +75,6 @@ ViewManager::ViewManager( QObject* parent ) { s_instance = this; - setHistoryPosition( -1 ); m_widget->setLayout( new QVBoxLayout() ); m_topbar = new TopBar(); @@ -176,13 +175,14 @@ Tomahawk::ViewPage* ViewManager::show( const Tomahawk::playlist_ptr& playlist ) { PlaylistView* view; - if ( !m_playlistViews.contains( playlist ) ) + + if ( !m_playlistViews.contains( playlist ) || m_playlistViews.value( playlist ).isNull() ) { view = createPageForPlaylist( playlist ); } else { - view = m_playlistViews.value( playlist ); + view = m_playlistViews.value( playlist ).data(); } setPage( view ); @@ -196,14 +196,14 @@ ViewManager::show( const Tomahawk::playlist_ptr& playlist ) Tomahawk::ViewPage* ViewManager::show( const Tomahawk::dynplaylist_ptr& playlist ) { - if ( !m_dynamicWidgets.contains( playlist ) ) + if ( !m_dynamicWidgets.contains( playlist ) || m_dynamicWidgets.value( playlist ).isNull() ) { m_dynamicWidgets[ playlist ] = new Tomahawk::DynamicWidget( playlist, m_stack ); playlist->resolve(); } - setPage( m_dynamicWidgets.value( playlist ) ); + setPage( m_dynamicWidgets.value( playlist ).data() ); if ( playlist->mode() == Tomahawk::OnDemand ) m_queueView->hide(); @@ -212,7 +212,7 @@ ViewManager::show( const Tomahawk::dynplaylist_ptr& playlist ) emit numSourcesChanged( SourceList::instance()->count() ); - return m_dynamicWidgets.value( playlist ); + return m_dynamicWidgets.value( playlist ).data(); } @@ -220,14 +220,14 @@ Tomahawk::ViewPage* ViewManager::show( const Tomahawk::artist_ptr& artist ) { ArtistInfoWidget* swidget; - if ( !m_artistViews.contains( artist ) ) + if ( !m_artistViews.contains( artist ) || m_artistViews.value( artist ).isNull() ) { swidget = new ArtistInfoWidget( artist ); m_artistViews.insert( artist, swidget ); } else { - swidget = m_artistViews.value( artist ); + swidget = m_artistViews.value( artist ).data(); } setPage( swidget ); @@ -239,14 +239,14 @@ Tomahawk::ViewPage* ViewManager::show( const Tomahawk::album_ptr& album ) { AlbumInfoWidget* swidget; - if ( !m_albumViews.contains( album ) ) + if ( !m_albumViews.contains( album ) || m_albumViews.value( album ).isNull() ) { swidget = new AlbumInfoWidget( album ); m_albumViews.insert( album, swidget ); } else { - swidget = m_albumViews.value( album ); + swidget = m_albumViews.value( album ).data(); } setPage( swidget ); @@ -263,7 +263,7 @@ ViewManager::show( const Tomahawk::collection_ptr& collection ) if ( m_currentMode == PlaylistInterface::Flat ) { CollectionView* view; - if ( !m_collectionViews.contains( collection ) ) + if ( !m_collectionViews.contains( collection ) || m_collectionViews.value( collection ).isNull() ) { view = new CollectionView(); CollectionFlatModel* model = new CollectionFlatModel(); @@ -277,7 +277,7 @@ ViewManager::show( const Tomahawk::collection_ptr& collection ) } else { - view = m_collectionViews.value( collection ); + view = m_collectionViews.value( collection ).data(); } shown = view; @@ -287,7 +287,7 @@ ViewManager::show( const Tomahawk::collection_ptr& collection ) if ( m_currentMode == PlaylistInterface::Tree ) { ArtistView* view; - if ( !m_treeViews.contains( collection ) ) + if ( !m_treeViews.contains( collection ) || m_treeViews.value( collection ).isNull() ) { view = new ArtistView(); TreeModel* model = new TreeModel(); @@ -301,7 +301,7 @@ ViewManager::show( const Tomahawk::collection_ptr& collection ) } else { - view = m_treeViews.value( collection ); + view = m_treeViews.value( collection ).data(); } shown = view; @@ -311,7 +311,7 @@ ViewManager::show( const Tomahawk::collection_ptr& collection ) if ( m_currentMode == PlaylistInterface::Album ) { AlbumView* aview; - if ( !m_collectionAlbumViews.contains( collection ) ) + if ( !m_collectionAlbumViews.contains( collection ) || m_collectionAlbumViews.value( collection ).isNull() ) { aview = new AlbumView(); AlbumModel* amodel = new AlbumModel( aview ); @@ -324,7 +324,7 @@ ViewManager::show( const Tomahawk::collection_ptr& collection ) } else { - aview = m_collectionAlbumViews.value( collection ); + aview = m_collectionAlbumViews.value( collection ).data(); } shown = aview; @@ -341,14 +341,14 @@ Tomahawk::ViewPage* ViewManager::show( const Tomahawk::source_ptr& source ) { SourceInfoWidget* swidget; - if ( !m_sourceViews.contains( source ) ) + if ( !m_sourceViews.contains( source ) || m_sourceViews.value( source ).isNull() ) { swidget = new SourceInfoWidget( source ); m_sourceViews.insert( source, swidget ); } else { - swidget = m_sourceViews.value( source ); + swidget = m_sourceViews.value( source ).data(); } setPage( swidget ); @@ -517,37 +517,13 @@ ViewManager::hideQueue() void ViewManager::historyBack() { - if ( m_historyPosition < 1 ) - return; + ViewPage* oldPage = m_pageHistory.takeFirst(); - showHistory( m_historyPosition - 1 ); -} + ViewPage* newPage = m_pageHistory.first(); + qDebug() << "Showing page after moving backwards in history:" << newPage->widget()->metaObject()->className(); + setPage( newPage, false ); - -void -ViewManager::historyForward() -{ - if ( m_historyPosition >= m_pageHistory.count() - 1 ) - return; - - showHistory( m_historyPosition + 1 ); -} - - -void -ViewManager::showHistory( int historyPosition ) -{ - if ( historyPosition < 0 || historyPosition >= m_pageHistory.count() ) - { - qDebug() << "History position out of bounds!" << historyPosition << m_pageHistory.count(); - Q_ASSERT( false ); - return; - } - - setHistoryPosition( historyPosition ); - ViewPage* page = m_pageHistory.at( historyPosition ); - qDebug() << "Showing page after a deleting:" << page->widget()->metaObject()->className(); - setPage( page, false ); + delete oldPage; } void @@ -556,10 +532,11 @@ ViewManager::removeFromHistory ( ViewPage* p ) if ( currentPage() == p ) { historyBack(); - m_pageHistory.removeAll( p ); } else - if ( m_pageHistory.removeAll( p ) ) - setHistoryPosition( m_historyPosition - 1 ); + { + m_pageHistory.removeAll( p ); + delete p; + } } @@ -607,8 +584,7 @@ ViewManager::setPage( ViewPage* page, bool trackHistory ) if ( trackHistory ) { - m_pageHistory << page; - setHistoryPosition( m_pageHistory.count() - 1 ); + m_pageHistory.insert( 0, page ); } qDebug() << "View page shown:" << page->title(); @@ -779,6 +755,8 @@ ViewManager::onWidgetDestroyed( QWidget* widget ) for ( int i = 0; i < m_pageHistory.count(); i++ ) { ViewPage* page = m_pageHistory.at( i ); + if ( page->widget() != widget ) + continue; if ( !playlistForInterface( page->playlistInterface() ).isNull() ) { @@ -789,12 +767,9 @@ ViewManager::onWidgetDestroyed( QWidget* widget ) m_dynamicWidgets.remove( dynamicPlaylistForInterface( page->playlistInterface() ) ); } - if ( page->widget() == widget ) + if ( page->widget() == widget && !resetWidget ) { m_pageHistory.removeAt( i ); - if ( m_historyPosition > i ) - m_historyPosition--; - break; } } @@ -802,8 +777,7 @@ ViewManager::onWidgetDestroyed( QWidget* widget ) if ( resetWidget ) { - if ( m_pageHistory.count() ) - showHistory( m_pageHistory.count() - 1 ); + historyBack(); } } @@ -847,21 +821,21 @@ ViewManager::createDynamicPlaylist( const Tomahawk::source_ptr& src, ViewPage* ViewManager::pageForCollection( const collection_ptr& col ) const { - return m_collectionViews.value( col, 0 ); + return m_collectionViews.value( col ).data(); } ViewPage* ViewManager::pageForDynPlaylist(const dynplaylist_ptr& pl) const { - return m_dynamicWidgets.value( pl, 0 ); + return m_dynamicWidgets.value( pl ).data(); } ViewPage* ViewManager::pageForPlaylist(const playlist_ptr& pl) const { - return m_playlistViews.value( pl, 0 ); + return m_playlistViews.value( pl ).data(); } @@ -878,20 +852,6 @@ ViewManager::pageForInterface( Tomahawk::PlaylistInterface* interface ) const return 0; } - -int -ViewManager::positionInHistory( ViewPage* page ) const -{ - for ( int i = 0; i < m_pageHistory.count(); i++ ) - { - if ( page == m_pageHistory.at( i ) ) - return i; - } - - return -1; -} - - PlaylistInterface* ViewManager::currentPlaylistInterface() const { @@ -905,29 +865,15 @@ ViewManager::currentPlaylistInterface() const Tomahawk::ViewPage* ViewManager::currentPage() const { - if ( m_historyPosition >= 0 ) - return m_pageHistory.at( m_historyPosition ); - else - return 0; + return m_pageHistory.isEmpty() ? 0 : m_pageHistory.front(); } - -void -ViewManager::setHistoryPosition( int position ) -{ - m_historyPosition = position; - - emit historyBackAvailable( m_historyPosition > 0 ); - emit historyForwardAvailable( m_historyPosition < m_pageHistory.count() - 1 ); -} - - Tomahawk::playlist_ptr ViewManager::playlistForInterface( Tomahawk::PlaylistInterface* interface ) const { - foreach ( PlaylistView* view, m_playlistViews.values() ) + foreach ( QWeakPointer view, m_playlistViews.values() ) { - if ( view->playlistInterface() == interface ) + if ( !view.isNull() && view.data()->playlistInterface() == interface ) { return m_playlistViews.key( view ); } @@ -940,9 +886,9 @@ ViewManager::playlistForInterface( Tomahawk::PlaylistInterface* interface ) cons Tomahawk::dynplaylist_ptr ViewManager::dynamicPlaylistForInterface( Tomahawk::PlaylistInterface* interface ) const { - foreach ( DynamicWidget* view, m_dynamicWidgets.values() ) + foreach ( QWeakPointer view, m_dynamicWidgets.values() ) { - if ( view->playlistInterface() == interface ) + if ( !view.isNull() && view.data()->playlistInterface() == interface ) { return m_dynamicWidgets.key( view ); } @@ -955,16 +901,16 @@ ViewManager::dynamicPlaylistForInterface( Tomahawk::PlaylistInterface* interface Tomahawk::collection_ptr ViewManager::collectionForInterface( Tomahawk::PlaylistInterface* interface ) const { - foreach ( CollectionView* view, m_collectionViews.values() ) + foreach ( QWeakPointer view, m_collectionViews.values() ) { - if ( view->playlistInterface() == interface ) + if ( view.data()->playlistInterface() == interface ) { return m_collectionViews.key( view ); } } - foreach ( AlbumView* view, m_collectionAlbumViews.values() ) + foreach ( QWeakPointer view, m_collectionAlbumViews.values() ) { - if ( view->playlistInterface() == interface ) + if ( view.data()->playlistInterface() == interface ) { return m_collectionAlbumViews.key( view ); } diff --git a/src/libtomahawk/viewmanager.h b/src/libtomahawk/viewmanager.h index d1ab325b4..b9bc1201f 100644 --- a/src/libtomahawk/viewmanager.h +++ b/src/libtomahawk/viewmanager.h @@ -80,7 +80,6 @@ public: Tomahawk::PlaylistInterface* currentPlaylistInterface() const; Tomahawk::ViewPage* currentPage() const; Tomahawk::ViewPage* pageForInterface( Tomahawk::PlaylistInterface* interface ) const; - int positionInHistory( Tomahawk::ViewPage* page ) const; Tomahawk::ViewPage* show( Tomahawk::ViewPage* page ); @@ -114,9 +113,6 @@ signals: void playClicked(); void pauseClicked(); - void historyBackAvailable( bool avail ); - void historyForwardAvailable( bool avail ); - void tempPageActivated( Tomahawk::ViewPage* ); void viewPageActivated( Tomahawk::ViewPage* ); @@ -135,8 +131,6 @@ public slots: Tomahawk::ViewPage* show( const Tomahawk::source_ptr& source ); void historyBack(); - void historyForward(); - void showHistory( int historyPosition ); void removeFromHistory( Tomahawk::ViewPage* p ); void setTreeMode(); @@ -162,7 +156,6 @@ private slots: void onWidgetDestroyed( QWidget* widget ); private: - void setHistoryPosition( int position ); void setPage( Tomahawk::ViewPage* page, bool trackHistory = true ); void updateView(); void unlinkPlaylist(); @@ -192,17 +185,16 @@ private: QList< Tomahawk::collection_ptr > m_superCollections; - QHash< Tomahawk::dynplaylist_ptr, Tomahawk::DynamicWidget* > m_dynamicWidgets; - QHash< Tomahawk::collection_ptr, CollectionView* > m_collectionViews; - QHash< Tomahawk::collection_ptr, ArtistView* > m_treeViews; - QHash< Tomahawk::collection_ptr, AlbumView* > m_collectionAlbumViews; - QHash< Tomahawk::artist_ptr, ArtistInfoWidget* > m_artistViews; - QHash< Tomahawk::album_ptr, AlbumInfoWidget* > m_albumViews; - QHash< Tomahawk::playlist_ptr, PlaylistView* > m_playlistViews; - QHash< Tomahawk::source_ptr, SourceInfoWidget* > m_sourceViews; + QHash< Tomahawk::dynplaylist_ptr, QWeakPointer > m_dynamicWidgets; + QHash< Tomahawk::collection_ptr, QWeakPointer > m_collectionViews; + QHash< Tomahawk::collection_ptr, QWeakPointer > m_treeViews; + QHash< Tomahawk::collection_ptr, QWeakPointer > m_collectionAlbumViews; + QHash< Tomahawk::artist_ptr, QWeakPointer > m_artistViews; + QHash< Tomahawk::album_ptr, QWeakPointer > m_albumViews; + QHash< Tomahawk::playlist_ptr, QWeakPointer > m_playlistViews; + QHash< Tomahawk::source_ptr, QWeakPointer > m_sourceViews; QList m_pageHistory; - int m_historyPosition; Tomahawk::collection_ptr m_currentCollection; int m_currentMode; diff --git a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp index e44992741..dbd2a53f6 100644 --- a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp +++ b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp @@ -31,15 +31,13 @@ #include "widgets/overlaywidget.h" -static QString s_aiInfoIdentifier = QString( "ArtistInfoWidget" ); - using namespace Tomahawk; - ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget* parent ) : QWidget( parent ) , ui( new Ui::ArtistInfoWidget ) , m_artist( artist ) + , m_infoId( uuid() ) { ui->setupUi( this ); @@ -95,7 +93,7 @@ ArtistInfoWidget::load( const artist_ptr& artist ) artistInfo["artist"] = artist->name(); Tomahawk::InfoSystem::InfoRequestData requestData; - requestData.caller = s_aiInfoIdentifier; + requestData.caller = m_infoId; requestData.customData = QVariantMap(); requestData.input = artist->name(); @@ -121,7 +119,7 @@ ArtistInfoWidget::load( const artist_ptr& artist ) void ArtistInfoWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ) { - if ( requestData.caller != s_aiInfoIdentifier ) + if ( requestData.caller != m_infoId ) { // qDebug() << "Info of wrong type or not with our identifier"; return; @@ -139,6 +137,7 @@ ArtistInfoWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestD } } +qDebug() << "ARTISTINFOWIDGET got infosystem info for:" << m_title << output.value< Tomahawk::InfoSystem::InfoGenericMap >(); QVariantMap returnedData = output.value< QVariantMap >(); switch ( requestData.type ) { diff --git a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.h b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.h index 155a3f2f7..b9e97259d 100644 --- a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.h +++ b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.h @@ -102,6 +102,7 @@ private: QString m_title; QString m_description; QString m_longDescription; + QString m_infoId; QPixmap m_pixmap; }; diff --git a/src/libtomahawk/widgets/maclineedit.h b/src/libtomahawk/widgets/maclineedit.h deleted file mode 100644 index 1e3320993..000000000 --- a/src/libtomahawk/widgets/maclineedit.h +++ /dev/null @@ -1,84 +0,0 @@ -/* This file is part of Clementine. - Copyright 2010, David Sansome - - Clementine 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. - - Clementine 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 Clementine. If not, see . -*/ - -#ifndef MACLINEEDIT_H -#define MACLINEEDIT_H - -#include - -#include "dllmacro.h" - -class SearchTargetWrapper; - -class DLLEXPORT LineEditInterface { -public: - LineEditInterface(QWidget* widget) : widget_(widget) {} - - QWidget* widget() const { return widget_; } - - virtual ~LineEditInterface() {} - - virtual void clear() { set_text(QString()); } - virtual void set_focus() = 0; - virtual QString text() const = 0; - virtual void set_text(const QString& text) = 0; - - virtual QString hint() const = 0; - virtual void set_hint(const QString& hint) = 0; - virtual void clear_hint() = 0; - - virtual void set_enabled(bool enabled) = 0; - -protected: - QWidget* widget_; -}; - -class DLLEXPORT MacLineEdit : public QMacCocoaViewContainer, public LineEditInterface { - Q_OBJECT - Q_PROPERTY(QString hint READ hint WRITE set_hint); - - public: - MacLineEdit(QWidget* parent = 0); - ~MacLineEdit(); - - QString hint() const { return hint_; } - void set_hint(const QString& hint); - void clear_hint() { set_hint(QString()); } - - void paintEvent(QPaintEvent* e); - - void set_text(const QString&); - QString text() const; - void set_focus() {} - - void set_enabled(bool enabled); - - signals: - void textChanged(const QString& text); - void textEdited(const QString& text); - - private: - // Called by NSSearchFieldCell when the text changes. - void TextChanged(const QString& text); - - QString hint_; - - friend class SearchTargetWrapper; - SearchTargetWrapper* wrapper_; -}; - -#endif // MACLINEEDIT_H diff --git a/src/libtomahawk/widgets/maclineedit.mm b/src/libtomahawk/widgets/maclineedit.mm deleted file mode 100644 index e391613be..000000000 --- a/src/libtomahawk/widgets/maclineedit.mm +++ /dev/null @@ -1,140 +0,0 @@ -/* This file is part of Clementine. - Copyright 2010, David Sansome - - Clementine 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. - - Clementine 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 Clementine. If not, see . -*/ - -#include "maclineedit.h" - -#import - -#include - -@interface SearchTarget : NSObject { - SearchTargetWrapper* wrapper_; -} - -- (id) initWithWrapper: (SearchTargetWrapper*)wrapper; -- (void) action; -@end - -class SearchTargetWrapper { - public: - explicit SearchTargetWrapper(NSSearchField* search, MacLineEdit* lineedit); - void TextChanged(); - - QString text() const; - void setText(const QString& text); - - void SetHint(const QString& hint); - - void SetEnabled(bool enabled); - - private: - NSSearchField* search_; - SearchTarget* target_; - MacLineEdit* lineedit_; -}; - - -@implementation SearchTarget -- (id) initWithWrapper: (SearchTargetWrapper*)wrapper { - wrapper_ = wrapper; - return self; -} - -- (void) action { - wrapper_->TextChanged(); -} -@end - -SearchTargetWrapper::SearchTargetWrapper(NSSearchField* search, MacLineEdit* lineedit) - : search_(search), - lineedit_(lineedit) { - target_ = [[SearchTarget alloc] initWithWrapper:this]; - - [[search cell] setSendsWholeSearchString:true]; - - [[search cell] setTarget:target_]; - [[search cell] setAction:@selector(action)]; -} - -void SearchTargetWrapper::TextChanged() { - NSString* text = [[search_ cell] stringValue]; - lineedit_->TextChanged(QString::fromUtf8([text UTF8String])); -} - -QString SearchTargetWrapper::text() const { - NSString* text = [[search_ cell] stringValue]; - return QString::fromUtf8([text UTF8String]); -} - -void SearchTargetWrapper::setText(const QString& text) { - NSString* t = [[NSString alloc] initWithUTF8String:text.toUtf8().constData()]; - [[search_ cell] setStringValue:t]; - [t release]; -} - -void SearchTargetWrapper::SetHint(const QString& hint) { - NSString* t = [[NSString alloc] initWithUTF8String:hint.toUtf8().constData()]; - [[search_ cell] setPlaceholderString:t]; - [t release]; -} - -void SearchTargetWrapper::SetEnabled(bool enabled) { - [search_ setEnabled:enabled]; -} - -MacLineEdit::MacLineEdit(QWidget* parent) - : QMacCocoaViewContainer(0, parent), - LineEditInterface(this) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - NSSearchField* search = [[NSSearchField alloc] init]; - setCocoaView(search); - - wrapper_ = new SearchTargetWrapper(search, this); - - [search release]; - [pool release]; // Pool's closed. -} - -MacLineEdit::~MacLineEdit() { - delete wrapper_; -} - -void MacLineEdit::paintEvent(QPaintEvent* e) { - QMacCocoaViewContainer::paintEvent(e); -} - -void MacLineEdit::TextChanged(const QString& text) { - emit textChanged(text); - emit textEdited(text); -} - -QString MacLineEdit::text() const { - return wrapper_->text(); -} - -void MacLineEdit::set_text(const QString& text) { - wrapper_->setText(text); -} - -void MacLineEdit::set_enabled(bool enabled) { - wrapper_->SetEnabled(enabled); -} - -void MacLineEdit::set_hint(const QString& hint) { - wrapper_->SetHint(hint); -} diff --git a/src/libtomahawk/widgets/newplaylistwidget.cpp b/src/libtomahawk/widgets/newplaylistwidget.cpp index 201a7b015..01b7fdffa 100644 --- a/src/libtomahawk/widgets/newplaylistwidget.cpp +++ b/src/libtomahawk/widgets/newplaylistwidget.cpp @@ -149,6 +149,6 @@ NewPlaylistWidget::savePlaylist() void NewPlaylistWidget::cancel() { + // will be deleted by viewmanager emit destroyed( this ); - deleteLater(); } diff --git a/src/libtomahawk/widgets/playlisttypeselectordlg.cpp b/src/libtomahawk/widgets/playlisttypeselectordlg.cpp index 8207edf34..9e80addcd 100644 --- a/src/libtomahawk/widgets/playlisttypeselectordlg.cpp +++ b/src/libtomahawk/widgets/playlisttypeselectordlg.cpp @@ -35,22 +35,24 @@ PlaylistTypeSelectorDlg::PlaylistTypeSelectorDlg( QWidget* parent, Qt::WindowFla #ifdef Q_WS_MAC // ui-> - ui->horizontalLayout_2->setContentsMargins( 4, 4, 4, 4 ); + ui->verticalLayout->setContentsMargins( 4, 0, 4, 4 ); setSizeGripEnabled( false ); + resize( width(), 150 ); setMinimumSize( size() ); setMaximumSize( size() ); // to remove the resize grip on osx this is the only way +#else + ui->verticalLayout->setContentsMargins( 9, 0, 9, 9 ); #endif + ui->line->setMaximumHeight( ui->label->height() ); + ui->line->setContentsMargins( 0, 0, 0, 0 ); 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& ))); } @@ -72,7 +74,6 @@ 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 } @@ -80,7 +81,7 @@ PlaylistTypeSelectorDlg::createAutomaticPlaylist() QString PlaylistTypeSelectorDlg::playlistName() const { - return m_playlistName; + return ui->playlistNameLine->text(); } @@ -89,11 +90,3 @@ 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 index de00c1504..ac90ef40f 100644 --- a/src/libtomahawk/widgets/playlisttypeselectordlg.h +++ b/src/libtomahawk/widgets/playlisttypeselectordlg.h @@ -40,15 +40,13 @@ public: QString playlistName() const; private slots: - void createNormalPlaylist(); - void createAutomaticPlaylist(); - void enableAutoPlaylistButton( const QString& ); + void createNormalPlaylist(); + void createAutomaticPlaylist(); private: bool m_isAutoPlaylist; // if not an auto playlist then its a normal playlist Ui::PlaylistTypeSelectorDlg *ui; - QString m_playlistName; }; diff --git a/src/libtomahawk/widgets/playlisttypeselectordlg.ui b/src/libtomahawk/widgets/playlisttypeselectordlg.ui index 3ae6c25df..bb17630a5 100644 --- a/src/libtomahawk/widgets/playlisttypeselectordlg.ui +++ b/src/libtomahawk/widgets/playlisttypeselectordlg.ui @@ -6,8 +6,8 @@ 0 0 - 482 - 169 + 420 + 100 @@ -18,8 +18,8 @@ - 482 - 145 + 420 + 100 @@ -34,21 +34,15 @@ false - + - - - 0 - - - 2 - + - 221 - 40 + 190 + 0 @@ -63,42 +57,12 @@ - + Qt::Vertical - - - 20 - 28 - - - - - - - - Create Manual Playlist - - - - - - - Qt::Vertical - - - - - - - 4 - - - 1 - @@ -118,57 +82,42 @@ + + + + - - - Qt::Vertical + + + Name: - - - 20 - 40 - + + 1 - + - - - - - Name: - - - 1 - - - - - - - New Playlist... - - - - + + + New Playlist... + + + + + + - - - Qt::Vertical + + + Create Manual Playlist - - - 20 - 40 - - - + - false + true Create Automatic Playlist diff --git a/src/libtomahawk/widgets/searchwidget.cpp b/src/libtomahawk/widgets/searchwidget.cpp index 5b253c83a..208c223bf 100644 --- a/src/libtomahawk/widgets/searchwidget.cpp +++ b/src/libtomahawk/widgets/searchwidget.cpp @@ -39,6 +39,7 @@ SearchWidget::SearchWidget( const QString& search, QWidget* parent ) { ui->setupUi( this ); + ui->resultsView->setGuid( "searchwidget" ); m_resultsModel = new PlaylistModel( ui->resultsView ); ui->resultsView->setPlaylistModel( m_resultsModel ); ui->resultsView->overlay()->setEnabled( false ); @@ -96,7 +97,6 @@ SearchWidget::onResultsFound( const QList& results ) Tomahawk::query_ptr q = result->toQuery(); q->setResolveFinished( true ); q->addResults( rl ); - qDebug() << result->toString(); m_resultsModel->append( q ); } diff --git a/src/libtomahawk/widgets/welcomewidget.cpp b/src/libtomahawk/widgets/welcomewidget.cpp index 34df559fd..5e090f090 100644 --- a/src/libtomahawk/widgets/welcomewidget.cpp +++ b/src/libtomahawk/widgets/welcomewidget.cpp @@ -86,7 +86,7 @@ WelcomeWidget::WelcomeWidget( QWidget* parent ) m_recentAlbumsModel = new AlbumModel( ui->additionsView ); ui->additionsView->setAlbumModel( m_recentAlbumsModel ); - m_recentAlbumsModel->addFilteredCollection( collection_ptr(), 20, DatabaseCommand_AllAlbums::ModificationTime ); + m_recentAlbumsModel->addFilteredCollection( collection_ptr(), 20, DatabaseCommand_AllAlbums::ModificationTime, true ); m_timer = new QTimer( this ); connect( m_timer, SIGNAL( timeout() ), SLOT( checkQueries() ) ); @@ -108,6 +108,14 @@ void WelcomeWidget::updateRecentTracks() { m_tracksModel->loadHistory( Tomahawk::source_ptr(), HISTORY_TRACK_ITEMS ); + + connect( SourceList::instance()->getLocal().data(), SIGNAL( stats( QVariantMap ) ), this, SLOT( updateRecentAdditions() ) ); +} + +void +WelcomeWidget::updateRecentAdditions() +{ + m_recentAlbumsModel->addFilteredCollection( collection_ptr(), 20, DatabaseCommand_AllAlbums::ModificationTime, true ); } diff --git a/src/libtomahawk/widgets/welcomewidget.h b/src/libtomahawk/widgets/welcomewidget.h index 6df35c045..9d7089582 100644 --- a/src/libtomahawk/widgets/welcomewidget.h +++ b/src/libtomahawk/widgets/welcomewidget.h @@ -103,6 +103,7 @@ signals: public slots: void updateRecentTracks(); void updatePlaylists(); + void updateRecentAdditions(); private slots: void onSourceAdded( const Tomahawk::source_ptr& source ); diff --git a/src/musicscanner.cpp b/src/musicscanner.cpp index 4777d95d3..123654aa8 100644 --- a/src/musicscanner.cpp +++ b/src/musicscanner.cpp @@ -283,14 +283,6 @@ MusicScanner::listerFinished( const QMap& newmtimes ) Database::instance()->enqueue( QSharedPointer(cmd) ); } - // re-calculate source stats - { - DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() ); - connect( cmd, SIGNAL( done( QVariantMap ) ), - SourceList::instance()->getLocal().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection ); - Database::instance()->enqueue( QSharedPointer( cmd ) ); - } - if ( !m_dirLister.isNull() ) { m_dirListerThreadController->quit();; diff --git a/src/resolversmodel.cpp b/src/resolversmodel.cpp index b1f1cb031..837f83cd3 100644 --- a/src/resolversmodel.cpp +++ b/src/resolversmodel.cpp @@ -109,6 +109,11 @@ ResolversModel::setData( const QModelIndex& index, const QVariant& value, int ro m_enabledResolvers.append( resolver ); TomahawkApp::instance()->enableScriptResolver( resolver ); + emit dataChanged( index, index ); + + if( Tomahawk::ExternalResolver* res = TomahawkApp::instance()->resolverForPath( resolver ) ) { + connect( res, SIGNAL( changed() ), this, SLOT( resolverChanged() ) ); + } } else if( state == Qt::Unchecked ) { m_enabledResolvers.removeAll( resolver ); diff --git a/src/searchbox.ui b/src/searchbox.ui index f996396fa..10b0f8783 100644 --- a/src/searchbox.ui +++ b/src/searchbox.ui @@ -7,26 +7,13 @@ 0 0 345 - 31 + 51 Form - - - - Qt::Horizontal - - - - 141 - 20 - - - - diff --git a/src/sip/jabber/jabber.cpp b/src/sip/jabber/jabber.cpp index 9434dc1b4..886edb647 100644 --- a/src/sip/jabber/jabber.cpp +++ b/src/sip/jabber/jabber.cpp @@ -119,10 +119,9 @@ JabberPlugin::JabberPlugin( const QString& pluginId ) m_client->disco()->addIdentity( Jreen::Disco::Identity( "client", "type", "tomahawk", "en" ) ); m_client->disco()->addFeature( TOMAHAWK_FEATURE ); - // setup caps node, legacy peer detection - used before 0.1 + // setup caps node Jreen::Capabilities::Ptr caps = m_client->presence().payload(); caps->setNode( TOMAHAWK_CAP_NODE_NAME ); - //FIXME: caps->setVersion( TOMAHAWK_VERSION ); // print connection parameters qDebug() << "Our JID set to:" << m_client->jid().full(); @@ -235,7 +234,6 @@ JabberPlugin::disconnectPlugin() //m_room = 0; m_peers.clear(); - m_legacy_peers.clear(); m_client->disconnectFromServer( true ); m_state = Disconnecting; @@ -389,16 +387,6 @@ JabberPlugin::sendMsg(const QString& to, const QString& msg) return; } - if( m_legacy_peers.contains( to ) ) - { - qDebug() << Q_FUNC_INFO << to << "Send legacy message" << msg; - Jreen::Message m( Jreen::Message::Chat, Jreen::JID(to), msg); - m_client->send( m ); - - return; - } - - /******************************************************* * Obsolete this by a SipMessage class */ @@ -643,14 +631,6 @@ void JabberPlugin::onPresenceReceived( const Jreen::RosterItem::Ptr &item, const // ignore anyone not Running tomahawk: Jreen::Capabilities::Ptr caps = presence.payload(); - /* Disabled this, because it's somewhat ugly and we should rely on nothing but the features - if ( caps && ( caps->node() == TOMAHAWK_CAP_NODE_NAME ) ) - { - // must be a jreen resource, implementation in gloox was broken - qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk: yes" << "caps " << caps->node(); - handlePeerStatus( jid, presence.subtype() ); - } else - */ if( caps ) { qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk: maybe" << "caps " << caps->node() << "requesting disco..."; @@ -784,21 +764,6 @@ void JabberPlugin::onNewIq(const Jreen::IQ& iq) // the actual presence doesn't matter, it just needs to be "online" handlePeerStatus( jid, Jreen::Presence::Available ); } - else - { -// qDebug() << Q_FUNC_INFO << jid.full() << "Running tomahawk/feature enabled: no"; - - //LEGACY: accept resources starting with tomahawk too - if( jid.resource().startsWith("tomahawk") ) - { - qDebug() << Q_FUNC_INFO << jid.full() << "Detected legacy tomahawk.."; - - // add to legacy peers, so we can send text messages instead of iqs - m_legacy_peers.append( jid ); - - handlePeerStatus( jid, Jreen::Presence::Available ); - } - } } else if(context == RequestVersion) { @@ -881,12 +846,6 @@ void JabberPlugin::handlePeerStatus(const Jreen::JID& jid, Jreen::Presence::Type m_peers[ jid ] = presenceType; qDebug() << Q_FUNC_INFO << "* Peer goes offline:" << fulljid; - // remove peer from legacy peers - if( m_legacy_peers.contains( jid ) ) - { - m_legacy_peers.removeAll( jid ); - } - emit peerOffline( fulljid ); return; } diff --git a/src/sip/jabber/jabber.h b/src/sip/jabber/jabber.h index 101ac5c15..cc10e5322 100644 --- a/src/sip/jabber/jabber.h +++ b/src/sip/jabber/jabber.h @@ -152,7 +152,6 @@ private: QHash m_peers; QHash m_subscriptionConfirmBoxes; enum IqContext { NoContext, RequestDisco, RequestedDisco, SipMessageSent, RequestedVCard, RequestVersion, RequestedVersion }; - QStringList m_legacy_peers; AvatarManager *m_avatarManager; }; diff --git a/src/sip/twitter/tomahawkoauthtwitter.cpp b/src/sip/twitter/tomahawkoauthtwitter.cpp index a2932b995..35cd98a9e 100644 --- a/src/sip/twitter/tomahawkoauthtwitter.cpp +++ b/src/sip/twitter/tomahawkoauthtwitter.cpp @@ -6,7 +6,7 @@ TomahawkOAuthTwitter::TomahawkOAuthTwitter( QNetworkAccessManager *nam, QObject* parent ) - : OAuthTwitter( QByteArray( "C4v4Wfa21rfIDck4HMR3A" ), QByteArray( "zXSjU6bjrvg6UVMJX4JufqHyjj3iextY14SR9uBEAo" ), parent ) + : OAuthTwitter( QByteArray::fromBase64( "QzR2NFdmYTIxcmZJRGNrNEhNUjNB" ), QByteArray::fromBase64( "elhTalU2Ympydmc2VVZNSlg0SnVmcUh5amozaWV4dFkxNFNSOXVCRUFv" ), parent ) { setNetworkAccessManager( nam ); } diff --git a/src/sourcetree/items/categoryitems.cpp b/src/sourcetree/items/categoryitems.cpp index d57551a14..86bc03134 100644 --- a/src/sourcetree/items/categoryitems.cpp +++ b/src/sourcetree/items/categoryitems.cpp @@ -68,34 +68,44 @@ CategoryAddItem::activate() { 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() ); - } + PlaylistTypeSelectorDlg* playlistSelectorDlg = new PlaylistTypeSelectorDlg( TomahawkApp::instance()->mainWindow(), Qt::Sheet ); +#ifndef Q_OS_MAC + playlistSelectorDlg->setModal( true ); +#endif + connect( playlistSelectorDlg, SIGNAL( finished( int ) ), this, SLOT( dialogClosed( int ) ) ); + playlistSelectorDlg->show(); break; - } + } case SourcesModel::StationsCategory: APP->mainWindow()->createStation(); break; } } +void +CategoryAddItem::dialogClosed( int ret ) +{ + PlaylistTypeSelectorDlg* playlistSelectorDlg = qobject_cast< PlaylistTypeSelectorDlg* >( sender() ); + Q_ASSERT( playlistSelectorDlg ); + + QString playlistName = playlistSelectorDlg->playlistName(); + if ( playlistName.isEmpty() ) + playlistName = tr( "New Playlist" ); + + if ( !playlistSelectorDlg->playlistTypeIsAuto() && ret ) { + + playlist_ptr playlist = Tomahawk::Playlist::create( SourceList::instance()->getLocal(), uuid(), playlistName, "", "", false, QList< query_ptr>() ); + ViewManager::instance()->show( playlist ); + + } else if ( playlistSelectorDlg->playlistTypeIsAuto() && ret ) { + // create Auto Playlist + APP->mainWindow()->createAutomaticPlaylist( playlistName ); + } else if ( !ret ) { + model()->viewPageActivated( ViewManager::instance()->currentPage() ); + } + playlistSelectorDlg->deleteLater(); +} Qt::ItemFlags CategoryAddItem::flags() const diff --git a/src/sourcetree/items/categoryitems.h b/src/sourcetree/items/categoryitems.h index 52468ff06..a7de58b0f 100644 --- a/src/sourcetree/items/categoryitems.h +++ b/src/sourcetree/items/categoryitems.h @@ -37,6 +37,7 @@ public: private slots: void parsedDroppedTracks( const QList< Tomahawk::query_ptr >& tracks ); + void dialogClosed( int ret ); private: SourcesModel::CategoryType m_categoryType; diff --git a/src/sourcetree/items/collectionitem.cpp b/src/sourcetree/items/collectionitem.cpp index 9bca2be3d..3dcb9900d 100644 --- a/src/sourcetree/items/collectionitem.cpp +++ b/src/sourcetree/items/collectionitem.cpp @@ -244,6 +244,8 @@ CollectionItem::playlistDeletedInternal( SourceTreeItem* parent, const T& p ) parent->beginRowsRemoved( i, i ); parent->removeChild( pl ); parent->endRowsRemoved(); + + delete pl; break; } } diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp index caab4d44d..d3f0af496 100644 --- a/src/sourcetree/sourcesmodel.cpp +++ b/src/sourcetree/sourcesmodel.cpp @@ -283,7 +283,7 @@ SourcesModel::viewPageActivated( Tomahawk::ViewPage* page ) if ( !idx.isValid() ) m_sourceTreeLinks.remove( page ); else - emit selectRequest( idx ); + emit selectRequest( QPersistentModelIndex( idx ) ); } else { @@ -420,7 +420,7 @@ SourcesModel::linkSourceItemToPage( SourceTreeItem* item, ViewPage* p ) m_sourceTreeLinks[ p ] = item; if( m_viewPageDelayedCacheItem == p ) - emit selectRequest( indexFromItem( item ) ); + emit selectRequest( QPersistentModelIndex( indexFromItem( item ) ) ); if ( QObject* obj = dynamic_cast< QObject* >( p ) ) { @@ -517,12 +517,12 @@ SourcesModel::rowForItem( SourceTreeItem* item ) const void SourcesModel::itemSelectRequest( SourceTreeItem* item ) { - emit selectRequest( indexFromItem( item ) ); + emit selectRequest( QPersistentModelIndex( indexFromItem( item ) ) ); } void SourcesModel::itemExpandRequest( SourceTreeItem *item ) { qDebug() << "expanding source" << indexFromItem( item ) << item; - emit expandRequest( indexFromItem( item ) ); + emit expandRequest( QPersistentModelIndex( indexFromItem( item ) ) ); } diff --git a/src/sourcetree/sourcesmodel.h b/src/sourcetree/sourcesmodel.h index bf90a9a25..7bf1c2ef0 100644 --- a/src/sourcetree/sourcesmodel.h +++ b/src/sourcetree/sourcesmodel.h @@ -108,8 +108,8 @@ public slots: void itemExpandRequest( SourceTreeItem* item ); signals: - void selectRequest( const QModelIndex& idx ); - void expandRequest( const QModelIndex& idx ); + void selectRequest( const QPersistentModelIndex& idx ); + void expandRequest( const QPersistentModelIndex& idx ); private slots: void onSourcesAdded( const QList& sources ); diff --git a/src/sourcetree/sourcesproxymodel.cpp b/src/sourcetree/sourcesproxymodel.cpp index 66a3e85be..3188cda77 100644 --- a/src/sourcetree/sourcesproxymodel.cpp +++ b/src/sourcetree/sourcesproxymodel.cpp @@ -37,10 +37,10 @@ SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent ) setSourceModel( model ); - if ( model && model->metaObject()->indexOfSignal( "expandRequest(QModelIndex)" ) > -1 ) - connect( model, SIGNAL( expandRequest( QModelIndex ) ), this, SLOT( expandRequested( QModelIndex ) ) ); - if ( model && model->metaObject()->indexOfSignal( "selectRequest(QModelIndex)" ) > -1 ) - connect( model, SIGNAL( selectRequest( QModelIndex ) ), this, SLOT( selectRequested( QModelIndex ) ) ); + if ( model && model->metaObject()->indexOfSignal( "expandRequest(QPersistentModelIndex)" ) > -1 ) + connect( model, SIGNAL( expandRequest( QPersistentModelIndex ) ), this, SLOT( expandRequested( QPersistentModelIndex ) ), Qt::QueuedConnection ); + if ( model && model->metaObject()->indexOfSignal( "selectRequest(QPersistentModelIndex)" ) > -1 ) + connect( model, SIGNAL( selectRequest( QPersistentModelIndex ) ), this, SLOT( selectRequested( QPersistentModelIndex ) ), Qt::QueuedConnection ); } @@ -72,18 +72,18 @@ SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePar void -SourcesProxyModel::selectRequested( const QModelIndex& idx ) +SourcesProxyModel::selectRequested( const QPersistentModelIndex& idx ) { - qDebug() << "selectRequested for idx" << idx << idx.data(Qt::DisplayRole).toString() << mapFromSource( idx ); - emit selectRequest( mapFromSource( idx ) ); + qDebug() << "selectRequested for idx" << idx << idx.data(Qt::DisplayRole).toString() << mapFromSource( idx ) << mapFromSource( idx ).data(Qt::DisplayRole).toString(); + emit selectRequest( QPersistentModelIndex( mapFromSource( idx ) ) ); } void -SourcesProxyModel::expandRequested( const QModelIndex& idx ) +SourcesProxyModel::expandRequested( const QPersistentModelIndex& idx ) { - qDebug() << "emitting expand for idx" << idx << idx.data(Qt::DisplayRole).toString() << mapFromSource( idx ); - emit expandRequest( mapFromSource( idx ) ); + qDebug() << "emitting expand for idx" << idx << idx.data(Qt::DisplayRole).toString() << mapFromSource( idx ) << mapFromSource( idx ).data(Qt::DisplayRole).toString(); + emit expandRequest( QPersistentModelIndex( mapFromSource( idx ) ) ); } diff --git a/src/sourcetree/sourcesproxymodel.h b/src/sourcetree/sourcesproxymodel.h index 01c0a9f87..a1908b73c 100644 --- a/src/sourcetree/sourcesproxymodel.h +++ b/src/sourcetree/sourcesproxymodel.h @@ -33,12 +33,12 @@ public: public slots: void showOfflineSources( bool offlineSourcesShown ); - void selectRequested( const QModelIndex& ); - void expandRequested( const QModelIndex& ); + void selectRequested( const QPersistentModelIndex& ); + void expandRequested( const QPersistentModelIndex& ); signals: - void selectRequest( const QModelIndex& idx ); - void expandRequest( const QModelIndex& idx ); + void selectRequest( const QPersistentModelIndex& idx ); + void expandRequest( const QPersistentModelIndex& idx ); protected: bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const; diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index 7156b68f2..4297caffe 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -112,8 +112,8 @@ SourceTreeView::SourceTreeView( QWidget* parent ) m_model = new SourcesModel( this ); m_proxyModel = new SourcesProxyModel( m_model, this ); - connect( m_proxyModel, SIGNAL( selectRequest( QModelIndex ) ), this, SLOT( selectRequest( QModelIndex ) ), Qt::QueuedConnection ); - connect( m_proxyModel, SIGNAL( expandRequest( QModelIndex ) ), this, SLOT( expandRequest( QModelIndex ) ), Qt::QueuedConnection ); + connect( m_proxyModel, SIGNAL( selectRequest( QPersistentModelIndex ) ), this, SLOT( selectRequest( QPersistentModelIndex ) ) ); + connect( m_proxyModel, SIGNAL( expandRequest( QPersistentModelIndex ) ), this, SLOT( expandRequest( QPersistentModelIndex ) ) ); setModel( m_proxyModel ); @@ -167,7 +167,7 @@ SourceTreeView::setupMenus() if ( pi && dynamic_cast< SourcePlaylistInterface* >( pi ) ) { SourcePlaylistInterface* sourcepi = dynamic_cast< SourcePlaylistInterface* >( pi ); - if ( !sourcepi->source().isNull() && sourcepi->source()->id() == source->id() ) + if ( !sourcepi->source().isNull() && sourcepi->source()->id() == source->id() && !AudioEngine::instance()->state() == AudioEngine::Stopped ) { m_latchOnAction->setText( tr( "&Catch Up" ) ); m_latchMenu.addSeparator(); @@ -243,8 +243,9 @@ SourceTreeView::onItemExpanded( const QModelIndex& idx ) void -SourceTreeView::selectRequest( const QModelIndex& idx ) +SourceTreeView::selectRequest( const QPersistentModelIndex& idx ) { + qDebug() << "Select request for:" << idx << idx.data().toString() << selectionModel()->selectedIndexes().contains( idx ); if ( !selectionModel()->selectedIndexes().contains( idx ) ) { scrollTo( idx, QTreeView::EnsureVisible ); @@ -253,9 +254,9 @@ SourceTreeView::selectRequest( const QModelIndex& idx ) } void -SourceTreeView::expandRequest( const QModelIndex &idx ) +SourceTreeView::expandRequest( const QPersistentModelIndex &idx ) { - qDebug() << "Expanding idx" << idx; + qDebug() << "Expanding idx" << idx << idx.data( Qt::DisplayRole ).toString(); expand( idx ); } @@ -369,11 +370,9 @@ SourceTreeView::latchOn() SourcePlaylistInterface* sourcepi = dynamic_cast< SourcePlaylistInterface* >( pi ); if ( !sourcepi->source().isNull() && sourcepi->source()->id() == source->id() ) { - //it's a catch-up -- if they're trying to catch-up in the same track, don't do anything - //so that you don't repeat the track and/or cause the retry timer to fire - if ( !AudioEngine::instance()->currentTrack().isNull() && !sourcepi->hasNextItem() && - AudioEngine::instance()->currentTrack()->id() == sourcepi->currentItem()->id() ) - return; + //it's a catch-up -- logic in audioengine should take care of it + AudioEngine::instance()->next(); + return; } } diff --git a/src/sourcetree/sourcetreeview.h b/src/sourcetree/sourcetreeview.h index 15c8276f9..2eca36fa2 100644 --- a/src/sourcetree/sourcetreeview.h +++ b/src/sourcetree/sourcetreeview.h @@ -48,8 +48,8 @@ signals: private slots: void onItemExpanded( const QModelIndex& idx ); void onItemActivated( const QModelIndex& index ); - void selectRequest( const QModelIndex& idx ); - void expandRequest( const QModelIndex& idx ); + void selectRequest( const QPersistentModelIndex& idx ); + void expandRequest( const QPersistentModelIndex& idx ); void loadPlaylist(); void deletePlaylist( const QModelIndex& = QModelIndex() ); diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index 55819319c..b3bad5658 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -391,6 +391,7 @@ TomahawkApp::registerMetaTypes() qRegisterMetaType< DirLister::Mode >("DirLister::Mode"); qRegisterMetaType< Tomahawk::InfoSystem::ArtistTrackPair >("Tomahawk::InfoSystem::ArtistTrackPair"); qRegisterMetaType< QList >("QList"); + qRegisterMetaType< QPersistentModelIndex >( "QPersistentModelIndex" ); } diff --git a/src/tomahawkapp.h b/src/tomahawkapp.h index 9e36f802b..6aa3fca33 100644 --- a/src/tomahawkapp.h +++ b/src/tomahawkapp.h @@ -145,5 +145,7 @@ private: QxtHttpSessionManager m_session; }; +Q_DECLARE_METATYPE( QPersistentModelIndex ); + #endif // TOMAHAWKAPP_H diff --git a/src/tomahawktrayicon.cpp b/src/tomahawktrayicon.cpp index 11b039171..e7990921d 100644 --- a/src/tomahawktrayicon.cpp +++ b/src/tomahawktrayicon.cpp @@ -42,8 +42,8 @@ TomahawkTrayIcon::TomahawkTrayIcon( QObject* parent ) m_contextMenu = new QMenu(); setContextMenu( m_contextMenu ); - m_playAction = m_contextMenu->addAction( tr( "Play" ) ); - m_pauseAction = m_contextMenu->addAction( tr( "Pause" ) ); + m_playPauseAction = m_contextMenu->addAction( tr( "Play" ) ); + //m_pauseAction = m_contextMenu->addAction( tr( "Pause" ) ); m_stopAction = m_contextMenu->addAction( tr( "Stop" ) ); m_contextMenu->addSeparator(); m_prevAction = m_contextMenu->addAction( tr( "Previous Track" ) ); @@ -61,13 +61,16 @@ TomahawkTrayIcon::TomahawkTrayIcon( QObject* parent ) m_quitAction = m_contextMenu->addAction( tr( "Quit" ) ); connect( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ), SLOT( setResult( Tomahawk::result_ptr ) ) ); + connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( enablePause() ) ); + connect( AudioEngine::instance(), SIGNAL( resumed() ), this, SLOT( enablePause() ) ); + connect( AudioEngine::instance(), SIGNAL( stopped() ), this, SLOT( enablePlay() ) ); + connect( AudioEngine::instance(), SIGNAL( paused() ), this, SLOT( enablePlay() ) ); - connect( m_playAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( play() ) ); - connect( m_pauseAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( pause() ) ); - connect( m_stopAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( stop() ) ); - connect( m_prevAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( previous() ) ); - connect( m_nextAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( next() ) ); - connect( m_quitAction, SIGNAL( triggered() ), (QObject*)APP, SLOT( quit() ) ); + connect( m_playPauseAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( playPause() ) ); + connect( m_stopAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( stop() ) ); + connect( m_prevAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( previous() ) ); + connect( m_nextAction, SIGNAL( triggered() ), AudioEngine::instance(), SLOT( next() ) ); + connect( m_quitAction, SIGNAL( triggered() ), (QObject*)APP, SLOT( quit() ) ); connect( &m_animationTimer, SIGNAL( timeout() ), SLOT( onAnimationTimer() ) ); connect( this, SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ), SLOT( onActivated( QSystemTrayIcon::ActivationReason ) ) ); @@ -81,6 +84,7 @@ TomahawkTrayIcon::~TomahawkTrayIcon() delete m_contextMenu; } + void TomahawkTrayIcon::setShowHideWindow( bool show ) { @@ -88,12 +92,16 @@ TomahawkTrayIcon::setShowHideWindow( bool show ) { m_showWindowAction->setText( tr( "Hide Tomahawk Window" ) ); m_showWindowAction->setData( show ); - } else { + } + else + { m_showWindowAction->setText( tr( "Show Tomahawk Window" ) ); } + m_showWindowAction->setData( show ); } + void TomahawkTrayIcon::showWindow() { @@ -103,12 +111,16 @@ TomahawkTrayIcon::showWindow() APP->mainWindow()->raise(); setShowHideWindow( true ); - } else { + } + else + { APP->mainWindow()->hide(); + setShowHideWindow( false ); } } + void TomahawkTrayIcon::setResult( const Tomahawk::result_ptr& result ) { @@ -148,14 +160,7 @@ TomahawkTrayIcon::refreshToolTip() void TomahawkTrayIcon::onAnimationTimer() { - /*if( m_animationPixmaps.isEmpty() ) - { - stopIpodScrobblingAnimation(); - Q_ASSERT( !"Animation should not be started without frames being loaded" ); - return; - } - - m_currentAnimationFrame++; +/* m_currentAnimationFrame++; if( m_currentAnimationFrame >= m_animationPixmaps.count() ) m_currentAnimationFrame = 0; @@ -192,6 +197,20 @@ TomahawkTrayIcon::onActivated( QSystemTrayIcon::ActivationReason reason ) } +void +TomahawkTrayIcon::enablePlay() +{ + m_playPauseAction->setText( tr( "Play" ) ); +} + + +void +TomahawkTrayIcon::enablePause() +{ + m_playPauseAction->setText( tr( "Pause" ) ); +} + + bool TomahawkTrayIcon::event( QEvent* e ) { diff --git a/src/tomahawktrayicon.h b/src/tomahawktrayicon.h index c78a8b173..3e0280d16 100644 --- a/src/tomahawktrayicon.h +++ b/src/tomahawktrayicon.h @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -43,6 +43,9 @@ private slots: void onActivated( QSystemTrayIcon::ActivationReason reason ); void showWindow(); + void enablePlay(); + void enablePause(); + private: void refreshToolTip(); ~TomahawkTrayIcon(); @@ -52,10 +55,10 @@ private: QList m_animationPixmaps; int m_currentAnimationFrame; - + QMenu* m_contextMenu; - QAction* m_playAction; - QAction* m_pauseAction; + QAction* m_playPauseAction; + //QAction* m_pauseAction; QAction* m_stopAction; QAction* m_prevAction; QAction* m_nextAction; diff --git a/src/tomahawkwindow.cpp b/src/tomahawkwindow.cpp index aac45bdc1..3d99bdc48 100644 --- a/src/tomahawkwindow.cpp +++ b/src/tomahawkwindow.cpp @@ -18,7 +18,6 @@ #include "tomahawkwindow.h" #include "ui_tomahawkwindow.h" -#include "ui_searchbox.h" #include #include @@ -65,11 +64,9 @@ #ifdef Q_OS_WIN32 #include #endif -#ifdef Q_OS_MAC -#include "widgets/maclineedit.h" -#endif #include "utils/logger.h" +#include "Qocoa/qsearchfield.h" using namespace Tomahawk; @@ -77,7 +74,7 @@ using namespace Tomahawk; TomahawkWindow::TomahawkWindow( QWidget* parent ) : QMainWindow( parent ) , ui( new Ui::TomahawkWindow ) - , m_searchWidget( new Ui::GlobalSearchWidget ) + , m_searchWidget( 0 ) , m_audioControls( new AudioControls( this ) ) , m_trayIcon( new TomahawkTrayIcon( this ) ) { @@ -96,7 +93,6 @@ TomahawkWindow::TomahawkWindow( QWidget* parent ) ui->centralWidget->layout()->setSpacing( 0 ); setupSideBar(); - setupToolBar(); statusBar()->addPermanentWidget( m_audioControls, 1 ); setupUpdateCheck(); @@ -195,15 +191,21 @@ TomahawkWindow::setupSideBar() AnimatedSplitter* sidebar = new AnimatedSplitter(); sidebar->setOrientation( Qt::Vertical ); sidebar->setChildrenCollapsible( false ); - sidebar->setGreedyWidget( 0 ); + + m_searchWidget = new QSearchField( sidebar ); + m_searchWidget->setPlaceholderText( "Global Search..." ); + connect( m_searchWidget, SIGNAL( returnPressed() ), this, SLOT( onFilterEdited() ) ); m_sourcetree = new SourceTreeView(); TransferView* transferView = new TransferView( sidebar ); PipelineStatusView* pipelineView = new PipelineStatusView( sidebar ); + sidebar->addWidget( m_searchWidget ); sidebar->addWidget( m_sourcetree ); sidebar->addWidget( transferView ); sidebar->addWidget( pipelineView ); + + sidebar->setGreedyWidget( 1 ); sidebar->hide( 1, false ); sidebar->hide( 2, false ); @@ -227,52 +229,6 @@ TomahawkWindow::setupSideBar() ui->actionShowOfflineSources->setChecked( TomahawkSettings::instance()->showOfflineSources() ); } - -void -TomahawkWindow::setupToolBar() -{ - QToolBar* toolbar = addToolBar( "TomahawkToolbar" ); - toolbar->setObjectName( "TomahawkToolbar" ); - toolbar->setMovable( false ); - toolbar->setFloatable( false ); - toolbar->setIconSize( QSize( 28, 28 ) ); - toolbar->setToolButtonStyle( Qt::ToolButtonFollowStyle ); - toolbar->installEventFilter( new WidgetDragFilter( toolbar ) ); - toolbar->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); - - m_backAvailable = toolbar->addAction( QIcon( RESPATH "images/back.png" ), tr( "Back" ), ViewManager::instance(), SLOT( historyBack() ) ); - m_backAvailable->setToolTip( tr( "Go back one page" ) ); - m_forwardAvailable = toolbar->addAction( QIcon( RESPATH "images/forward.png" ), tr( "Forward" ), ViewManager::instance(), SLOT( historyForward() ) ); - m_forwardAvailable->setToolTip( tr( "Go forward one page" ) ); - - m_searchBox = new QWidget( toolbar ); - -#ifdef Q_OS_MAC - QWidget *spacerWidget = new QWidget( this ); - spacerWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - spacerWidget->setVisible( true ); - toolbar->addWidget( spacerWidget ); - - m_searchBox->setLayout( new QHBoxLayout() ); - - MacLineEdit* lineEdit = new MacLineEdit( m_searchBox ); - lineEdit->setFixedSize( 256, 28 ); - lineEdit->set_hint( tr( "Search" ) ); - lineEdit->setVisible( true ); - m_searchBox->layout()->addWidget( lineEdit ); - - connect( lineEdit, SIGNAL( textChanged( QString ) ), SLOT( onSearch( QString ) ) ); -#else - m_searchWidget->setupUi( m_searchBox ); - m_searchWidget->searchEdit->setStyleSheet( "QLineEdit { border: 1px solid gray; border-radius: 6px; margin-right: 2px; }" ); - - connect( m_searchWidget->searchEdit, SIGNAL( returnPressed() ), SLOT( onFilterEdited() ) ); -#endif - - toolbar->addWidget( m_searchBox ); -} - - void TomahawkWindow::setupUpdateCheck() { @@ -360,10 +316,6 @@ TomahawkWindow::setupSignals() connect( plugin, SIGNAL( addMenu( QMenu* ) ), this, SLOT( pluginMenuAdded( QMenu* ) ) ); connect( plugin, SIGNAL( removeMenu( QMenu* ) ), this, SLOT( pluginMenuRemoved( QMenu* ) ) ); } - - // - connect( ViewManager::instance(), SIGNAL( historyBackAvailable( bool ) ), SLOT( onHistoryBackAvailable( bool ) ) ); - connect( ViewManager::instance(), SIGNAL( historyForwardAvailable( bool ) ), SLOT( onHistoryForwardAvailable( bool ) ) ); } @@ -572,26 +524,34 @@ TomahawkWindow::createStation() void TomahawkWindow::createPlaylist() { - PlaylistTypeSelectorDlg playlistSelectorDlg; - int successfulReturn = playlistSelectorDlg.exec(); + PlaylistTypeSelectorDlg* playlistSelectorDlg = new PlaylistTypeSelectorDlg( TomahawkApp::instance()->mainWindow(), Qt::Sheet ); +#ifndef Q_OS_MAC + playlistSelectorDlg->setModal( true ); +#endif + connect( playlistSelectorDlg, SIGNAL( finished( int ) ), this, SLOT( playlistCreateDialogFinished( int ) ) ); - 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 ); - } + playlistSelectorDlg->show(); } +void TomahawkWindow::playlistCreateDialogFinished( int ret ) +{ + PlaylistTypeSelectorDlg* playlistSelectorDlg = qobject_cast< PlaylistTypeSelectorDlg* >( sender() ); + Q_ASSERT( playlistSelectorDlg ); + + QString playlistName = playlistSelectorDlg->playlistName(); + if ( playlistName.isEmpty() ) + playlistName = tr( "New Playlist" ); + + if ( !playlistSelectorDlg->playlistTypeIsAuto() && ret ) { + + playlist_ptr playlist = Tomahawk::Playlist::create( SourceList::instance()->getLocal(), uuid(), playlistName, "", "", false, QList< query_ptr>() ); + ViewManager::instance()->show( playlist ); + } else if ( playlistSelectorDlg->playlistTypeIsAuto() && ret ) { + // create Auto Playlist + createAutomaticPlaylist( playlistName ); + } + playlistSelectorDlg->deleteLater(); +} void TomahawkWindow::audioStarted() @@ -615,21 +575,6 @@ TomahawkWindow::onPlaybackLoading( const Tomahawk::result_ptr& result ) setWindowTitle( m_windowTitle ); } - -void -TomahawkWindow::onHistoryBackAvailable( bool avail ) -{ - m_backAvailable->setEnabled( avail ); -} - - -void -TomahawkWindow::onHistoryForwardAvailable( bool avail ) -{ - m_forwardAvailable->setEnabled( avail ); -} - - void TomahawkWindow::onSipConnected() { @@ -717,8 +662,8 @@ TomahawkWindow::onSearch( const QString& search ) void TomahawkWindow::onFilterEdited() { - onSearch( m_searchWidget->searchEdit->text() ); - m_searchWidget->searchEdit->clear(); + onSearch( m_searchWidget->text() ); + m_searchWidget->clear(); } diff --git a/src/tomahawkwindow.h b/src/tomahawkwindow.h index 988d66899..f6980f78a 100644 --- a/src/tomahawkwindow.h +++ b/src/tomahawkwindow.h @@ -27,6 +27,7 @@ #include "result.h" +class QSearchField; class SipPlugin; class SourceTreeView; class QAction; @@ -81,8 +82,6 @@ private slots: void addPeerManually(); void onPlaybackLoading( const Tomahawk::result_ptr& result ); - void onHistoryBackAvailable( bool avail ); - void onHistoryForwardAvailable( bool avail ); void audioStarted(); void audioStopped(); @@ -99,27 +98,23 @@ private slots: void minimize(); void maximize(); + void playlistCreateDialogFinished( int ret ); private: void loadSettings(); void saveSettings(); void applyPlatformTweaks(); void setupSignals(); - void setupToolBar(); void setupSideBar(); void setupUpdateCheck(); Ui::TomahawkWindow* ui; - Ui::GlobalSearchWidget* m_searchWidget; - QWidget* m_searchBox; + QSearchField* m_searchWidget; AudioControls* m_audioControls; TomahawkTrayIcon* m_trayIcon; SourceTreeView* m_sourcetree; QPushButton* m_statusButton; - QAction* m_backAvailable; - QAction* m_forwardAvailable; - Tomahawk::result_ptr m_currentTrack; QString m_windowTitle; };