--- amarok/src/app.cpp 2007/07/15 09:16:57 688173 +++ amarok/src/app.cpp 2007/08/23 20:24:11 703986 @@ -1355,17 +1355,26 @@ result.replace( QChar(0x00fd), "y" ).replace( QChar(0x00dd), "Y" ); result.replace( QChar(0x00f1), "n" ).replace( QChar(0x00d1), "N" ); + // czech letters with carons + result.replace( QChar(0x0161), "s" ).replace( QChar(0x0160), "S" ); + result.replace( QChar(0x010d), "c" ).replace( QChar(0x010c), "C" ); + result.replace( QChar(0x0159), "r" ).replace( QChar(0x0158), "R" ); + result.replace( QChar(0x017e), "z" ).replace( QChar(0x017d), "Z" ); + result.replace( QChar(0x0165), "t" ).replace( QChar(0x0164), "T" ); + result.replace( QChar(0x0148), "n" ).replace( QChar(0x0147), "N" ); + result.replace( QChar(0x010f), "d" ).replace( QChar(0x010e), "D" ); + // accented vowels QChar a[] = { 'a', 0xe0,0xe1,0xe2,0xe3,0xe5, 0 }; QChar A[] = { 'A', 0xc0,0xc1,0xc2,0xc3,0xc5, 0 }; - QChar E[] = { 'e', 0xe8,0xe9,0xea,0xeb, 0 }; - QChar e[] = { 'E', 0xc8,0xc9,0xca,0xcb, 0 }; + QChar e[] = { 'e', 0xe8,0xe9,0xea,0xeb,0x11b, 0 }; + QChar E[] = { 'E', 0xc8,0xc9,0xca,0xcb,0x11a, 0 }; QChar i[] = { 'i', 0xec,0xed,0xee,0xef, 0 }; QChar I[] = { 'I', 0xcc,0xcd,0xce,0xcf, 0 }; QChar o[] = { 'o', 0xf2,0xf3,0xf4,0xf5,0xf8, 0 }; QChar O[] = { 'O', 0xd2,0xd3,0xd4,0xd5,0xd8, 0 }; - QChar u[] = { 'u', 0xf9,0xfa,0xfb, 0 }; - QChar U[] = { 'U', 0xd9,0xda,0xdb, 0 }; + QChar u[] = { 'u', 0xf9,0xfa,0xfb,0x16f, 0 }; + QChar U[] = { 'U', 0xd9,0xda,0xdb,0x16e, 0 }; QChar nul[] = { 0 }; QChar *replacements[] = { a, A, e, E, i, I, o, O, u, U, nul }; --- amarok/src/collectionbrowser.cpp 2007/03/01 20:29:23 638401 +++ amarok/src/collectionbrowser.cpp 2007/09/27 09:50:56 717679 @@ -63,7 +63,6 @@ #include #include #include -#include //KGlobal::dirs() #include //ctor #include //dragObject() #include --- amarok/src/collectiondb.cpp 2007/06/21 13:37:52 678474 +++ amarok/src/collectiondb.cpp 2007/11/15 00:17:39 736848 @@ -67,6 +67,7 @@ #include //DbConnection::sqlite_power() #include //query() +#include //exit() #include //usleep() #include @@ -217,6 +218,7 @@ : EngineObserver( EngineController::instance() ) , m_autoScoring( true ) , m_noCover( locate( "data", "amarok/images/nocover.png" ) ) + , m_shadowImage( locate( "data", "amarok/images/shadow_albumcover.png" ) ) , m_scanInProgress( false ) , m_rescanRequired( false ) , m_aftEnabledPersistentTables() @@ -738,10 +740,10 @@ query( "CREATE INDEX tags_artist_index ON tags( artist );" ); query( "CREATE INDEX tags_album_index ON tags( album );" ); query( "CREATE INDEX tags_deviceid_index ON tags( deviceid ); "); - query( "CREATE INDEX tags_url_index ON tags( url(20) ); "); + query( "CREATE INDEX tags_url_index ON tags( url ); "); query( "CREATE INDEX embed_deviceid_index ON embed( deviceid ); "); - query( "CREATE INDEX embed_url_index ON embed( url(20) ); "); + query( "CREATE INDEX embed_url_index ON embed( url ); "); query( "CREATE INDEX related_artists_artist ON related_artists( artist );" ); @@ -2055,11 +2057,12 @@ return s; } - QString CollectionDB::makeShadowedImage( const QString& albumImage, bool cache ) { - const QImage original( albumImage ); + qApp->lock(); + const QImage original( albumImage, "PNG" ); + qApp->unlock(); if( original.hasAlphaBuffer() ) return albumImage; @@ -2067,22 +2070,26 @@ const QFileInfo fileInfo( albumImage ); const uint shadowSize = static_cast( original.width() / 100.0 * 6.0 ); const QString cacheFile = fileInfo.fileName() + "@shadow"; - QImage shadow; if ( !cache && cacheCoverDir().exists( cacheFile ) ) return cacheCoverDir().filePath( cacheFile ); + QImage shadow; + const QString folder = Amarok::saveLocation( "covershadow-cache/" ); const QString file = QString( "shadow_albumcover%1x%2.png" ).arg( original.width() + shadowSize ).arg( original.height() + shadowSize ); - if ( QFile::exists( folder + file ) ) - shadow.load( folder + file ); + if ( QFile::exists( folder + file ) ) { + qApp->lock(); + shadow.load( folder + file, "PNG" ); + qApp->unlock(); + } else { - shadow.load( locate( "data", "amarok/images/shadow_albumcover.png" ) ); + shadow = QDeepCopy(instance()->m_shadowImage); shadow = shadow.smoothScale( original.width() + shadowSize, original.height() + shadowSize ); shadow.save( folder + file, "PNG" ); } - QImage target( shadow ); + QImage target(shadow); bitBlt( &target, 0, 0, &original ); if ( cache ) { @@ -2642,10 +2649,10 @@ pcb.setCopyright ( *++it ); pcb.setParentId ( (*++it).toInt() ); pcb.setSaveLocation( *++it ); - pcb.setAutoScan ( *++it == boolT() ? true : false ); + pcb.setAutoScan ( boolFromSql( *++it ) ); pcb.setFetchType ( (*++it).toInt() ); - pcb.setAutoTransfer( *++it == boolT() ? true : false ); - pcb.setPurge ( *++it == boolT() ? true : false ); + pcb.setAutoTransfer( boolFromSql( *++it ) ); + pcb.setPurge ( boolFromSql( *++it ) ); pcb.setPurgeCount ( (*++it).toInt() ); bundles.append( pcb ); @@ -2689,7 +2696,7 @@ peb.setSize ( 0 ); else peb.setSize ( (*it).toInt() ); - peb.setNew ( (*++it) == boolT() ? true : false ); + peb.setNew ( boolFromSql( *++it ) ); bundles.append( peb ); } @@ -2723,7 +2730,7 @@ peb.setSize ( 0 ); else peb.setSize ( (*it).toInt() ); - peb.setNew ( (*++it) == boolT() ? true : false ); + peb.setNew ( boolFromSql( *++it ) ); } return peb; @@ -2778,10 +2785,10 @@ pcb->setCopyright ( *++it ); pcb->setParentId ( (*++it).toInt() ); pcb->setSaveLocation( *++it ); - pcb->setAutoScan ( *++it == boolT() ? true : false ); + pcb->setAutoScan ( boolFromSql( *++it ) ); pcb->setFetchType ( (*++it).toInt() ); - pcb->setAutoTransfer( *++it == boolT() ? true : false ); - pcb->setPurge ( *++it == boolT() ? true : false ); + pcb->setAutoTransfer( boolFromSql( *++it ) ); + pcb->setPurge ( boolFromSql( *++it ) ); pcb->setPurgeCount ( (*++it).toInt() ); } @@ -2794,7 +2801,7 @@ { QString command = QString( "INSERT INTO podcastfolders ( name, parent, isOpen ) VALUES ('" ); command += escapeString( name ) + "',"; - command += QString::number( parent_id ) + ','; + command += QString::number( parent_id ) + ","; command += isOpen ? boolT() + ");" : boolF() + ");"; insert( command, NULL ); @@ -4718,7 +4725,7 @@ { recreateConnections = true; } - else if ( AmarokConfig::mySqlPassword() != config->password() ) + else if ( AmarokConfig::mySqlPassword2() != config->password() ) { recreateConnections = true; } @@ -7834,7 +7841,7 @@ QueryBuilder::tableName( int table ) { // optimize for 1 table which is by far the most frequent case - static const QString tabNames[] = { + static const char tabNames[][16] = { "album", "artist", "composer", --- amarok/src/collectiondb.h 2007/02/01 20:16:22 629191 +++ amarok/src/collectiondb.h 2007/11/08 07:40:55 734136 @@ -253,6 +253,7 @@ QString boolT() const { if (getDbConnectionType() == DbConnection::postgresql) return "true"; else return "1"; } QString boolF() const { if (getDbConnectionType() == DbConnection::postgresql) return "false"; else return "0"; } + inline bool boolFromSql( const QString &b ) { return ( b == boolT() || b == "t" ); } //textColumnType should be used for normal strings, which need to be compared //either case-sensitively or -insensitively QString textColumnType( int length=255 ) const { if ( getDbConnectionType() == DbConnection::postgresql ) return "TEXT"; else return QString("VARCHAR(%1)").arg(length); } @@ -619,7 +620,7 @@ static QMap *itemCoverMap; static QMutex *itemCoverMapMutex; - QImage m_noCover; + QImage m_noCover, m_shadowImage; static QMap *threadConnections; static QMutex *connectionMutex; --- amarok/src/contextbrowser.cpp 2007/08/03 08:45:34 695895 +++ amarok/src/contextbrowser.cpp 2007/09/27 09:50:56 717679 @@ -212,7 +212,8 @@ m_contextTab = new QVBox(this, "context_tab"); - m_currentTrackPage = new HTMLView( m_contextTab, "current_track_page", true /* DNDEnabled */ ); + m_currentTrackPage = new HTMLView( m_contextTab, "current_track_page", true /* DNDEnabled */, + true /*JScriptEnabled*/ ); m_lyricsTab = new QVBox(this, "lyrics_tab"); @@ -264,7 +265,7 @@ - m_lyricsPage = new HTMLView( m_lyricsTab, "lyrics_page", true /* DNDEnabled */ ); + m_lyricsPage = new HTMLView( m_lyricsTab, "lyrics_page", true /* DNDEnabled */, false /* JScriptEnabled*/ ); m_lyricsTextEdit = new KTextEdit ( m_lyricsTab, "lyrics_text_edit"); m_lyricsTextEdit->setTextFormat( Qt::PlainText ); m_lyricsTextEdit->hide(); @@ -285,7 +286,7 @@ m_wikiToolBar->setDelayedPopup( WIKI_BACK, m_wikiBackPopup ); m_wikiToolBar->setDelayedPopup( WIKI_FORWARD, m_wikiForwardPopup ); - m_wikiPage = new HTMLView( m_wikiTab, "wiki_page", true /* DNDEnabled */ ); + m_wikiPage = new HTMLView( m_wikiTab, "wiki_page", true /* DNDEnabled */, false /* JScriptEnabled */ ); m_cuefile = CueFile::instance(); connect( m_cuefile, SIGNAL(metaData( const MetaBundle& )), @@ -1104,6 +1105,13 @@ { m_metadataHistory += QDeepCopy( *it ); } + + + m_amarokIconPath = QDeepCopy(KGlobal::iconLoader()->iconPath( "amarok", + -KIcon::SizeEnormous ) ); + m_musicBrainIconPath = QDeepCopy(locate( "data", "amarok/images/musicbrainz.png" ) + ); + m_lastfmIcon = "file://" + locate( "data","amarok/images/lastfm.png" ); } private: @@ -1145,6 +1153,9 @@ b->saveHtmlData(); // Send html code to file } QString m_HTMLSource; + QString m_amarokIconPath; + QString m_musicBrainIconPath; + QString m_lastfmIcon; ContextBrowser *b; MetaBundle m_currentTrack; @@ -1329,7 +1340,7 @@ "\n" ) .args( QStringList() << escapeHTMLAttr( "externalurl://amarok.kde.org" ) - << escapeHTMLAttr( KGlobal::iconLoader()->iconPath( "amarok", -KIcon::SizeEnormous ) ) + << escapeHTMLAttr( m_amarokIconPath ) << i18n( "1 Track", "%n Tracks", songCount.toInt() ) << i18n( "1 Artist", "%n Artists", artistCount.toInt() ) << i18n( "1 Album", "%n Albums", albumCount.toInt() ) @@ -1743,7 +1754,6 @@ const QString albumUrl = lastFmInfo->albumUrl(); const QString artistUrl = lastFmInfo->artistUrl(); const QString titleUrl = lastFmInfo->titleUrl(); - const QString lastfmIcon = "file://" + locate( "data","amarok/images/lastfm.png" ); const QString coverImage = ContextBrowser::getEncodedImage( lastFmInfo->imageUrl() ); @@ -1818,7 +1828,7 @@ << escapeHTMLAttr( currentTrack.album() )//10 << escapeHTMLAttr( userpage ) //11 << escapeHTMLAttr( userpage ) //12 - << escapeHTMLAttr( lastfmIcon ) //13 + << escapeHTMLAttr( m_lastfmIcon ) //13 << escapeHTML( i18n( "Skip" ) ) //14 << escapeHTMLAttr( skipIcon ) //15 << escapeHTML( i18n( "Love" ) ) //16 @@ -2249,7 +2259,7 @@ << escapeHTMLAttr( currentTrack.artist() ) << escapeHTMLAttr( currentTrack.album() ) << escapeHTMLAttr( currentTrack.title() ) - << escapeHTML( locate( "data", "amarok/images/musicbrainz.png" ) ) ) + << escapeHTML( m_musicBrainIconPath ) ) : QString ( //no title "%1 " "\n" @@ -2612,7 +2622,7 @@ qb.groupBy( QueryBuilder::tabAlbum, QueryBuilder::valName ); qb.groupBy( QueryBuilder::tabAlbum, QueryBuilder::valID ); qb.sortByFunction( QueryBuilder::funcMax, QueryBuilder::tabYear, QueryBuilder::valName, true ); - qb.sortBy( QueryBuilder::tabAlbum, QueryBuilder::valName ); + qb.sortBy( QueryBuilder::tabAlbum, QueryBuilder::valName, true ); qb.setOptions( QueryBuilder::optNoCompilations ); values = qb.run(); @@ -2775,7 +2785,7 @@ qb.addReturnValue( QueryBuilder::tabAlbum, QueryBuilder::valID ); qb.addMatch( QueryBuilder::tabSong, QueryBuilder::valArtistID, QString::number( artist_id ) ); qb.sortBy( QueryBuilder::tabYear, QueryBuilder::valName, true ); - qb.sortBy( QueryBuilder::tabAlbum, QueryBuilder::valName ); + qb.sortBy( QueryBuilder::tabAlbum, QueryBuilder::valName, true ); qb.setOptions( QueryBuilder::optRemoveDuplicates ); qb.setOptions( QueryBuilder::optOnlyCompilations ); values = qb.run(); @@ -3192,11 +3202,15 @@ { // Embed cover image in html (encoded string), to get around khtml's caching //debug() << "Encoding imageUrl: " << imageUrl << endl; - const QImage img( imageUrl ); + qApp->lock(); + const QImage img( imageUrl, "PNG" ); + qApp->unlock(); QByteArray ba; QBuffer buffer( ba ); buffer.open( IO_WriteOnly ); + qApp->lock(); img.save( &buffer, "PNG" ); // writes image into ba in PNG format + qApp->unlock(); const QString coverImage = QString( "data:image/png;base64,%1" ).arg( KCodecs::base64Encode( ba ) ); //debug() << "Encoded imageUrl: " << coverImage << endl; return coverImage; @@ -3716,8 +3730,11 @@ QString ContextBrowser::wikiURL( const QString &item ) { + // add any special characters to be replaced here + QString wStr = QString(item).replace( "/", " " ); + return QString( "http://%1.wikipedia.org/wiki/" ).arg( wikiLocale() ) - + KURL::encode_string_no_slash( item, 106 /*utf-8*/ ); + + KURL::encode_string_no_slash( wStr, 106 /*utf-8*/ ); } void @@ -4326,6 +4343,9 @@ //which can be confusing, and looks less polished/professional //This can be changed if it slows things down too much... if( m_browseLabels || ( currentTrack.isFile() && ( currentTrack.url().path() == path || AmarokConfig::useRatings() ) ) ) + m_dirtyCurrentTrackPage = true; // will be reloaded when viewed (much faster) + + if( currentPage() == m_contextTab ) refreshCurrentTrackPage(); } --- amarok/src/dynamicmode.cpp 2007/02/01 20:16:22 629191 +++ amarok/src/dynamicmode.cpp 2007/09/23 00:57:57 715714 @@ -380,7 +380,8 @@ DEBUG_BLOCK KURL::List retrieval; - if( m_cachedItemSet.count() <= trackCount ) + // always rebuild with suggested mode since the artists will be changing + if( m_cachedItemSet.count() <= trackCount || appendType() == SUGGESTION ) rebuildCachedItemSet(); for( uint i=0; i < trackCount; i++ ) --- amarok/src/enginecontroller.cpp 2007/06/10 22:42:29 673737 +++ amarok/src/enginecontroller.cpp 2007/08/31 12:27:24 706845 @@ -244,13 +244,10 @@ if( engine() != EngineController::instance()->m_voidEngine ) { //we special case this as otherwise users hate us - if ( !valid && ext.lower() == "mp3" && !installDistroCodec(AmarokConfig::soundSystem()) ) - Amarok::StatusBar::instance()->longMessageThreadSafe( - i18n( "

The %1 claims it cannot play MP3 files." - "

You may want to choose a different engine from the Configure Dialog, or examine " - "the installation of the multimedia-framework that the current engine uses. " - "

You may find useful information in the FAQ section of the Amarok HandBook." ) - .arg( AmarokConfig::soundSystem() ), KDE::StatusBar::Error ); + if ( !valid && ext.lower() == "mp3"){ + QCustomEvent * e = new QCustomEvent( 2000 ); + QApplication::postEvent( Amarok::StatusBar::instance(), e ); + } // Cache this result for the next lookup if ( !ext.isEmpty() ) @@ -260,6 +257,17 @@ return valid; } +void EngineController::unplayableNotification() { + + if( !installDistroCodec(AmarokConfig::soundSystem())) + Amarok::StatusBar::instance()->longMessageThreadSafe( + i18n( "

The %1 claims it cannot play MP3 files." + "

You may want to choose a different engine from the Configure Dialog, or examine " + "the installation of the multimedia-framework that the current engine uses. " + "

You may find useful information in the FAQ section of the Amarok HandBook." ) + .arg( AmarokConfig::soundSystem() ), KDE::StatusBar::Error ); +} + bool EngineController::installDistroCodec( const QString& engine /*Filetype type*/) { KService::Ptr service = KTrader::self()->query( "Amarok/CodecInstall" --- amarok/src/enginecontroller.h 2007/04/30 18:40:11 659747 +++ amarok/src/enginecontroller.h 2007/08/31 12:27:24 706845 @@ -52,6 +52,7 @@ uint trackPosition() const; EngineBase* loadEngine(); + void unplayableNotification(); uint trackLength() const { return m_bundle.length() * 1000; } const MetaBundle &bundle() const; --- amarok/src/mountpointmanager.cpp 2007/07/27 15:12:16 693227 +++ amarok/src/mountpointmanager.cpp 2007/09/24 13:43:08 716304 @@ -233,6 +233,7 @@ MountPointManager::getAbsolutePath( const int deviceId, const QString& relativePath ) const { KURL rpath; + rpath.setProtocol("file"); rpath.setPath( relativePath ); KURL url; getAbsolutePath( deviceId, rpath, url ); --- amarok/src/statusbar/statusBarBase.cpp 2007/02/01 20:16:22 629191 +++ amarok/src/statusbar/statusBarBase.cpp 2007/08/31 12:27:24 706845 @@ -25,6 +25,7 @@ #include "squeezedtextlabel.h" #include "statusBarBase.h" #include "threadmanager.h" +#include "enginecontroller.h" #include #include @@ -343,9 +344,13 @@ void StatusBar::customEvent( QCustomEvent *e ) { - QString *s = static_cast( e->data() ); - longMessage( *s ); - delete s; + if(e->type() == 1000 ){ + QString *s = static_cast( e->data() ); + longMessage( *s ); + delete s; + }else if(e->type() == 2000 ){ + EngineController::instance()->unplayableNotification(); + } }