oopapidocs
2.0
|
00001 00002 #include "abstractmetadataloader.h" 00003 #include "dbutils.h" 00004 #include "dbconnectionsettings.h" 00005 #include "metadatatable.h" 00006 #include "audiometadata.h" 00007 #include <QFileInfo> 00008 #include <QDirIterator> 00009 #include <QModelIndex> 00010 #include <QTime> 00011 #include <QSqlDatabase> 00012 #include <QSqlResult> 00013 #include <QSqlRecord> 00014 #include <QSqlField> 00015 #include <QSqlIndex> 00016 #include <QSqlError> 00017 #include <QDebug> 00018 #include <QApplication> 00019 #include <QSqlQuery> 00020 00021 00022 MetaDataTable* MetaDataTable::instance() { 00023 static MetaDataTable* retval = 0; 00024 QSqlDatabase db = DbConnectionSettings::lastSaved(); 00025 if (!db.isValid()) { 00026 qDebug() << "Unable to create db connection."; 00027 abort(); 00028 } 00029 if (retval == 0) { 00030 retval = new MetaDataTable(qApp); 00031 } 00032 return retval; 00033 } 00034 //start id=prepare 00035 MetaDataTable::MetaDataTable(QObject* parent) 00036 : QObject(parent), m_tableName("MetaData") { 00037 setObjectName(m_tableName); 00038 m_mdl = Abstract::MetaDataLoader::instance(); 00039 m_driver = DbConnectionSettings::lastSaved().driverName(); 00040 Q_ASSERT(createMetadataTable()); 00041 QString preparedQuery = "INSERT into MetaData" /* Tested with MySQL5. */ 00042 "(Artist, TrackTitle, AlbumTitle, TrackNumber, TrackTime, Genre," 00043 "Preference, FileName, Comment) VALUES (:artist, :title, :album," 00044 ":track, :time, :genre, :preference, :filename, :comment) " 00045 "ON DUPLICATE KEY UPDATE Preference=VALUES(Preference)," 00046 "Genre=VALUES(Genre), AlbumTitle=VALUES(AlbumTitle)," 00047 "TrackTitle=VALUES(TrackTitle), TrackNumber=VALUES(TrackNumber)," 00048 "Artist=VALUES(Artist), COMMENT=VALUES(Comment)"; 00049 if (m_driver == "QSQLITE") { 00050 preparedQuery = "INSERT or REPLACE into MetaData" 00051 "(Artist, TrackTitle, AlbumTitle, TrackNumber, TrackTime, " 00052 "Genre, Preference, FileName, Comment)" 00053 "VALUES (:artist, :title, :album, :track, :time, :genre, " 00054 ":preference, :filename, :comment)"; 00055 } 00056 bool prepSuccess = m_insertQuery.prepare(preparedQuery); 00057 if (!prepSuccess) { 00058 qDebug() << "Prepare fail: " << m_insertQuery.lastError().text() 00059 << m_insertQuery.lastQuery(); 00060 abort(); 00061 } 00062 //end 00063 m_deleteQuery = 00064 QString("delete from MetaData where FileName = \"%1\""); 00065 connect (m_mdl, SIGNAL(fetched(MetaDataValue)), 00066 this, SLOT(insert(MetaDataValue)), Qt::QueuedConnection); 00067 } 00068 00069 00070 MetaDataTable::~MetaDataTable() 00071 { 00072 DbConnectionSettings::lastSaved().close(); 00073 } 00074 00075 //start id=create 00076 bool MetaDataTable::createMetadataTable() { 00077 QSqlDatabase db = DbConnectionSettings::lastSaved(); 00078 if (m_driver == "QMYSQL") 00079 m_createTableQStr = QString("CREATE TABLE if not exists %1 (" 00080 "TrackTitle text, Artist text, " 00081 "AlbumTitle text, TrackTime integer, TrackNumber integer, " 00082 "Genre varchar(30), Preference integer, Comment text, " 00083 "FileName varchar(255) PRIMARY KEY, INDEX(Genre) ) " 00084 "DEFAULT CHARSET utf8").arg(m_tableName); 00085 else m_createTableQStr = QString("CREATE TABLE IF NOT EXISTS %1 (" /* 00086 Tested with SQLite3. */ 00087 "TrackTitle text, Artist text, AlbumTitle text, " 00088 "TrackTime integer, TrackNumber integer, Genre varchar(30), " 00089 "Preference integer, Comment text, FileName varchar(255) " 00090 "PRIMARY KEY)").arg(m_tableName); 00091 QSqlQuery q(m_createTableQStr); 00092 if (!q.isActive()) { 00093 qDebug() << "Create Table Fail: " << q.lastError().text() 00094 << q.lastQuery(); 00095 return false; 00096 } 00097 db.commit(); 00098 return true; 00099 } 00100 //end 00101 00102 bool MetaDataTable::clearTable() { 00103 QSqlDatabase db = DbConnectionSettings::lastSaved(); 00104 QSqlQuery q("delete from MetaData"); 00105 return q.isActive(); 00106 } 00107 //start id=select 00108 QStringList MetaDataTable::genres() const { 00109 QStringList sl; 00110 QSqlDatabase db = DbConnectionSettings::lastSaved(); 00111 QSqlQuery q("SELECT DISTINCT Genre from MetaData"); 00112 if (!q.isActive()) { 00113 qDebug() << "Query Failed: " << q.lastQuery() 00114 << q.lastError().text(); 00115 } else while (q.next()) { 00116 sl << q.value(0).toString(); 00117 } 00118 return sl; 00119 } 00120 //end 00121 00122 //start id="insert" 00123 bool MetaDataTable::insert(const MetaDataValue &ft) { 00124 using namespace DbUtils; 00125 00126 QSqlDatabase db = DbConnectionSettings::lastSaved(); 00127 QSqlRecord record = db.record(m_tableName); 00128 if (record.isEmpty() && !createMetadataTable()) { 00129 qDebug() << "unable to create metadata: " 00130 << db.lastError().text(); 00131 return false; 00132 } 00133 00134 m_insertQuery.bindValue(":artist", ft.artist()); 00135 m_insertQuery.bindValue(":title", ft.trackTitle()); 00136 m_insertQuery.bindValue(":album", ft.albumTitle()); 00137 m_insertQuery.bindValue(":track", ft.trackNumber()); 00138 QTime t = ft.trackTime(); 00139 int secs = QTime().secsTo(t); 00140 m_insertQuery.bindValue(":time", secs); 00141 m_insertQuery.bindValue(":genre", ft.genre()); 00142 m_insertQuery.bindValue(":filename", ft.fileName()); 00143 int pref = ft.preference().intValue(); 00144 m_insertQuery.bindValue(":preference", pref); 00145 m_insertQuery.bindValue(":comment", ft.comment()); 00146 00147 bool retval = m_insertQuery.exec(); 00148 00149 if (!retval) { 00150 qDebug() << m_insertQuery.lastError().text() 00151 << m_insertQuery.lastQuery(); 00152 abort(); 00153 } 00154 emit inserted(ft); 00155 return retval; 00156 } 00157 //end 00158 00159 bool MetaDataTable:: 00160 hasMetaData(QString fileName, bool fetch, bool refresh) { 00161 MetaDataValue mdv = findRecord(fileName); 00162 if (refresh || (fetch && mdv.isNull())) { 00163 m_mdl->get(fileName); 00164 } 00165 return !mdv.isNull(); 00166 } 00167 //start id="findrecord" 00168 MetaDataValue MetaDataTable::findRecord(QString fileName) { 00169 using namespace DbUtils; 00170 QFileInfo fi(fileName); 00171 MetaDataObject f; 00172 if (!fi.exists()) return f; /* Return a QObject by value? Don't forget, MetaDataValue is the base class of this particular QObject. */ 00173 QString abs = fi.absoluteFilePath(); 00174 00175 QSqlDatabase db = DbConnectionSettings::lastSaved(); 00176 QString qs = QString("select * from %1 where FileName = \"%2\"") 00177 .arg(m_tableName).arg(escape(abs)); 00178 QSqlQuery findQuery(qs); 00179 if (!findQuery.isActive()) { 00180 qDebug() << "Query Failed: " << findQuery.lastQuery() 00181 << findQuery.lastError().text(); 00182 return f; 00183 } 00184 if (!findQuery.first()) return f; 00185 QSqlRecord rec = findQuery.record(); 00186 for (int i=rec.count() -1; i >= 0; --i) { /* Properties in QObject map to column names / field values in the table! */ 00187 QSqlField field = rec.field(i); 00188 QString key = field.name(); 00189 QVariant value = field.value(); 00190 if (key == "Preference") { 00191 int v = value.toInt(); 00192 Preference p(v); 00193 f.setPreference(p); 00194 } 00195 else if (key == "TrackTime") { /* SQLite has no time type, so we must store as int. */ 00196 QTime trackTime; 00197 trackTime = trackTime.addSecs(value.toInt()); 00198 f.setTrackTime(trackTime); 00199 } 00200 else { 00201 f.setProperty(key, value); /* Using QObject setProperty for other columns. */ 00202 } 00203 00204 } 00205 return f; /* Create a value type from this local stack QObject about to be destroyed. */ 00206 } 00207 //end 00208 QSet<QString> MetaDataTable::allSongs() { 00209 QSet<QString> retval; 00210 QSqlDatabase db = DbConnectionSettings::lastSaved(); 00211 QSqlQuery q = db.exec("select FileName from MetaData"); 00212 while (q.next()) { 00213 retval << q.value(0).toString(); 00214 } 00215 return retval; 00216 } 00217 00218 int MetaDataTable::visit(QString directory) { 00219 // QSet<QString> loaded = allSongs(); 00220 int i=0; 00221 QDirIterator itr(directory, m_mdl->supportedExtensions(), 00222 QDir::Files, QDirIterator::Subdirectories); 00223 while (itr.hasNext()) { 00224 QString fn = itr.next(); 00225 if (!hasMetaData(fn, true)) { 00226 ++i; 00227 qApp->processEvents(); 00228 } 00229 } 00230 return i; 00231 } 00232 00233 00234 bool MetaDataTable::dropMetaData(QString fileName) { 00235 QString q = m_deleteQuery.arg(DbUtils::escape(fileName)); 00236 QSqlQuery query(q); 00237 00238 // qDebug() << "drop: " << fileName; 00239 bool retval = query.isActive(); 00240 qDebug() << query.lastQuery(); 00241 return retval; 00242 } 00243