collectiondb.cpp
来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 1,976 行 · 第 1/5 页
CPP
1,976 行
// (c) 2004 Mark Kretschmann <markey@web.de>// (c) 2004 Christian Muehlhaeuser <chris@chris.de>// (c) 2004 Sami Nieminen <sami.nieminen@iki.fi>// (c) 2005 Ian Monroe <ian@monroe.nu>// See COPYING file for licensing information.#define DEBUG_PREFIX "CollectionDB"#include "app.h"#include "amarok.h"#include "amarokconfig.h"#include "config.h"#include "debug.h"#include "collectionbrowser.h" //updateTags()#include "collectiondb.h"#include "collectionreader.h"#include "coverfetcher.h"#include "enginecontroller.h"#include "metabundle.h" //updateTags()#include "playlist.h"#include "playlistbrowser.h"#include "pluginmanager.h"#include "scrobbler.h"#include "statusbar.h"#include "threadweaver.h"#include <qfile.h>#include <qimage.h>#include <qtimer.h>#include <kapplication.h>#include <kconfig.h>#include <kglobal.h>#include <kinputdialog.h> //setupCoverFetcher()#include <kio/job.h>#include <klineedit.h> //setupCoverFetcher()#include <klocale.h>#include <kmdcodec.h>#include <kstandarddirs.h>#include <kurl.h>#include <kio/netaccess.h>#include <cmath> //DbConnection::sqlite_power()#include <ctime> //query()#include <unistd.h> //usleep()#include <taglib/mpegfile.h>#include <taglib/mpegfile.h>#include <taglib/id3v2tag.h>#include <taglib/attachedpictureframe.h>#include <taglib/tbytevector.h>//////////////////////////////////////////////////////////////////////////////////////////// CLASS CollectionDB//////////////////////////////////////////////////////////////////////////////////////////CollectionDB* CollectionDB::instance(){ static CollectionDB db; return &db;}CollectionDB::CollectionDB() : EngineObserver( EngineController::instance() ) , m_cacheDir( amaroK::saveLocation() ) , m_coverDir( amaroK::saveLocation() ){ DEBUG_BLOCK // create cover dir, if it doesn't exist. if( !m_coverDir.exists( "albumcovers", false ) ) m_coverDir.mkdir( "albumcovers", false ); m_coverDir.cd( "albumcovers" ); // create image cache dir, if it doesn't exist. if( !m_cacheDir.exists( "albumcovers/cache", false ) ) m_cacheDir.mkdir( "albumcovers/cache", false ); m_cacheDir.cd( "albumcovers/cache" ); // Load DBEngine plugin QString query = "[X-KDE-Amarok-plugintype] == 'dbengine' and [X-KDE-Amarok-name] != '%1'"; KTrader::OfferList offers = PluginManager::query( query.arg( "sqlite-dbengine" ) ); m_dbEngine = (DBEngine*) PluginManager::createFromService( offers.first() ); //<OPEN DATABASE> initialize(); //</OPEN DATABASE> // TODO: Should write to config in dtor, but it crashes... KConfig* config = amaroK::config( "Collection Browser" ); config->writeEntry( "Database Version", DATABASE_VERSION ); config->writeEntry( "Database Stats Version", DATABASE_STATS_VERSION ); startTimer( MONITOR_INTERVAL * 1000 ); connect( Scrobbler::instance(), SIGNAL( similarArtistsFetched( const QString&, const QStringList& ) ), this, SLOT( similarArtistsFetched( const QString&, const QStringList& ) ) );}CollectionDB::~CollectionDB(){ DEBUG_FUNC_INFO destroy();// This crashes so it's done at the end of ctor.// KConfig* const config = amaroK::config( "Collection Browser" );// config->writeEntry( "Database Version", DATABASE_VERSION );// config->writeEntry( "Database Stats Version", DATABASE_STATS_VERSION );}//////////////////////////////////////////////////////////////////////////////////////////// PUBLIC//////////////////////////////////////////////////////////////////////////////////////////DbConnection*CollectionDB::getStaticDbConnection(){ return m_dbConnPool->getDbConnection();}voidCollectionDB::returnStaticDbConnection( DbConnection *conn ){ m_dbConnPool->putDbConnection( conn );}/** * Executes a SQL query on the already opened database * @param statement SQL program to execute. Only one SQL statement is allowed. * @return The queried data, or QStringList() on error. */QStringListCollectionDB::query( const QString& statement, DbConnection *conn ){ if ( DEBUG ) debug() << "Query-start: " << statement << endl; clock_t start = clock(); DbConnection *dbConn; if ( conn != NULL ) { dbConn = conn; } else { dbConn = m_dbConnPool->getDbConnection(); } QStringList values = dbConn->query( statement ); if ( conn == NULL ) { m_dbConnPool->putDbConnection( dbConn ); } if ( DEBUG ) { clock_t finish = clock(); const double duration = (double) (finish - start) / CLOCKS_PER_SEC; debug() << "SQL-query (" << duration << "s): " << statement << endl; } return values;}/** * Executes a SQL insert on the already opened database * @param statement SQL statement to execute. Only one SQL statement is allowed. * @return The rowid of the inserted item. */intCollectionDB::insert( const QString& statement, const QString& table, DbConnection *conn ){ if ( DEBUG ) debug() << "insert-start: " << statement << endl; clock_t start = clock(); DbConnection *dbConn; if ( conn != NULL ) { dbConn = conn; } else { dbConn = m_dbConnPool->getDbConnection(); } int id = dbConn->insert( statement, table ); if ( conn == NULL ) { m_dbConnPool->putDbConnection( dbConn ); } if ( DEBUG ) { clock_t finish = clock(); const double duration = (double) (finish - start) / CLOCKS_PER_SEC; debug() << "SQL-insert (" << duration << "s): " << statement << endl; } return id;}boolCollectionDB::isEmpty(){ QStringList values; if (m_dbConnPool->getDbConnectionType() == DbConnection::postgresql) { values = query( "SELECT COUNT( url ) FROM tags OFFSET 0 LIMIT 1;" ); } else { values = query( "SELECT COUNT( url ) FROM tags LIMIT 0, 1;" ); } return values.isEmpty() ? true : values.first() == "0";}boolCollectionDB::isValid(){ QStringList values1; QStringList values2; if (m_dbConnPool->getDbConnectionType() == DbConnection::postgresql) { values1 = query( "SELECT COUNT( url ) FROM tags OFFSET 0 LIMIT 1;" ); values2 = query( "SELECT COUNT( url ) FROM statistics OFFSET 0 LIMIT 1;" ); } else { values1 = query( "SELECT COUNT( url ) FROM tags LIMIT 0, 1;" ); values2 = query( "SELECT COUNT( url ) FROM statistics LIMIT 0, 1;" ); } //TODO? this returns true if value1 or value2 is not empty. Shouldn't this be and (&&)??? return !values1.isEmpty() || !values2.isEmpty();}voidCollectionDB::createTables( DbConnection *conn ){ DEBUG_FUNC_INFO //create tag table query( QString( "CREATE %1 TABLE tags%2 (" "url " + textColumnType() + "," "dir " + textColumnType() + "," "createdate INTEGER," "album INTEGER," "artist INTEGER," "genre INTEGER," "title " + textColumnType() + "," "year INTEGER," "comment " + textColumnType() + "," "track NUMERIC(4)," "bitrate INTEGER," "length INTEGER," "samplerate INTEGER," "sampler BOOL );" ) .arg( conn ? "TEMPORARY" : "" ) .arg( conn ? "_temp" : "" ), conn ); QString albumAutoIncrement = ""; QString artistAutoIncrement = ""; QString genreAutoIncrement = ""; QString yearAutoIncrement = ""; if ( m_dbConnPool->getDbConnectionType() == DbConnection::postgresql ) { query( QString( "CREATE SEQUENCE album_seq;" ), conn ); query( QString( "CREATE SEQUENCE artist_seq;" ), conn ); query( QString( "CREATE SEQUENCE genre_seq;" ), conn ); query( QString( "CREATE SEQUENCE year_seq;" ), conn ); albumAutoIncrement = QString("DEFAULT nextval('album_seq')"); artistAutoIncrement = QString("DEFAULT nextval('artist_seq')"); genreAutoIncrement = QString("DEFAULT nextval('genre_seq')"); yearAutoIncrement = QString("DEFAULT nextval('year_seq')"); } else if ( m_dbConnPool->getDbConnectionType() == DbConnection::mysql ) { albumAutoIncrement = "AUTO_INCREMENT"; artistAutoIncrement = "AUTO_INCREMENT"; genreAutoIncrement = "AUTO_INCREMENT"; yearAutoIncrement = "AUTO_INCREMENT"; } //create album table query( QString( "CREATE %1 TABLE album%2 (" "id INTEGER PRIMARY KEY %3," "name " + textColumnType() + ");" ) .arg( conn ? "TEMPORARY" : "" ) .arg( conn ? "_temp" : "" ) .arg( albumAutoIncrement ), conn ); //create artist table query( QString( "CREATE %1 TABLE artist%2 (" "id INTEGER PRIMARY KEY %3," "name " + textColumnType() + ");" ) .arg( conn ? "TEMPORARY" : "" ) .arg( conn ? "_temp" : "" ) .arg( artistAutoIncrement ), conn ); //create genre table query( QString( "CREATE %1 TABLE genre%2 (" "id INTEGER PRIMARY KEY %3," "name " + textColumnType() +");" ) .arg( conn ? "TEMPORARY" : "" ) .arg( conn ? "_temp" : "" ) .arg( genreAutoIncrement ), conn ); //create year table query( QString( "CREATE %1 TABLE year%2 (" "id INTEGER PRIMARY KEY %3," "name " + textColumnType() + ");" ) .arg( conn ? "TEMPORARY" : "" ) .arg( conn ? "_temp" : "" ) .arg( yearAutoIncrement ), conn ); //create images table query( QString( "CREATE %1 TABLE images%2 (" "path " + textColumnType() + "," "artist " + textColumnType() + "," "album " + textColumnType() + ");" ) .arg( conn ? "TEMPORARY" : "" ) .arg( conn ? "_temp" : "" ), conn ); // create directory statistics table query( QString( "CREATE %1 TABLE directories%2 (" "dir " + textColumnType() + " UNIQUE," "changedate INTEGER );" ) .arg( conn ? "TEMPORARY" : "" ) .arg( conn ? "_temp" : "" ), conn ); //create indexes query( QString( "CREATE INDEX album_idx%1 ON album%2( name );" ) .arg( conn ? "_temp" : "" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "CREATE INDEX artist_idx%1 ON artist%2( name );" ) .arg( conn ? "_temp" : "" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "CREATE INDEX genre_idx%1 ON genre%2( name );" ) .arg( conn ? "_temp" : "" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "CREATE INDEX year_idx%1 ON year%2( name );" ) .arg( conn ? "_temp" : "" ).arg( conn ? "_temp" : "" ), conn ); if ( !conn ) { // create related artists cache query( QString( "CREATE TABLE related_artists (" "artist " + textColumnType() + "," "suggestion " + textColumnType() + "," "changedate INTEGER );" ) ); query( "CREATE INDEX url_tag ON tags( url );" ); query( "CREATE INDEX album_tag ON tags( album );" ); query( "CREATE INDEX artist_tag ON tags( artist );" ); query( "CREATE INDEX genre_tag ON tags( genre );" ); query( "CREATE INDEX year_tag ON tags( year );" ); query( "CREATE INDEX sampler_tag ON tags( sampler );" ); query( "CREATE INDEX images_album ON images( album );" ); query( "CREATE INDEX images_artist ON images( artist );" ); query( "CREATE INDEX directories_dir ON directories( dir );" ); query( "CREATE INDEX related_artists_artist ON related_artists( artist );" ); }}voidCollectionDB::dropTables( DbConnection *conn ){ DEBUG_FUNC_INFO query( QString( "DROP TABLE tags%1;" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "DROP TABLE album%1;" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "DROP TABLE artist%1;" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "DROP TABLE genre%1;" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "DROP TABLE year%1;" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "DROP TABLE images%1;" ).arg( conn ? "_temp" : "" ), conn ); query( QString( "DROP TABLE directories%1;" ).arg( conn ? "_temp" : "" ), conn ); if ( !conn ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?