void MusicSearchEngine::watchForChanges() { // Gather all folders registered on music locations QFileInfoList dirs; for (QString musicPath : SettingsPrivate::instance()->musicLocations()) { QFileInfo location(musicPath); QDirIterator it(location.absoluteFilePath(), QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); while (it.hasNext()) { QString entry = it.next(); QFileInfo qFileInfo(entry); dirs << qFileInfo; } } SqlDatabase *db = SqlDatabase::instance(); db->open(); db->exec("PRAGMA journal_mode = MEMORY"); db->exec("PRAGMA synchronous = OFF"); db->exec("PRAGMA temp_store = 2"); db->exec("PRAGMA foreign_keys = 1"); QStringList newFoldersToAddInLibrary; // Add folders that were not found first for (QFileInfo f : dirs) { QSqlQuery query = db->exec("SELECT * FROM filesystem WHERE path = \"" + f.absoluteFilePath() + "\""); if (!query.next()) { newFoldersToAddInLibrary << f.absoluteFilePath(); QSqlQuery prepared(*db); prepared.prepare("INSERT INTO filesystem (path, lastModified) VALUES (?, ?)"); prepared.addBindValue(f.absoluteFilePath()); prepared.addBindValue(f.lastModified().toTime_t()); prepared.exec(); } } if (!newFoldersToAddInLibrary.isEmpty()) { this->doSearch(newFoldersToAddInLibrary); } // Process in reverse mode to clean cache: from database file and check if entry exists in database QStringList oldLocations; QSqlQuery cache = db->exec("SELECT * FROM filesystem"); while (cache.next()) { QDir d(cache.record().value(0).toString()); d.exists(); QFileInfo fileInfo(cache.record().value(0).toString()); // Remove folder in database because it couldn't be find in the filesystem if (!fileInfo.exists()) { db->exec("DELETE FROM filesystem WHERE path = \"" + fileInfo.absoluteFilePath() + "\""); oldLocations << fileInfo.absoluteFilePath(); } } if (!oldLocations.isEmpty()) { db->rebuild(oldLocations, QStringList()); } }
// Check if the expected rows in the DB are non-empty. Note that in some cases they might be, then we cannot use this function // https://github.com/owncloud/client/issues/2038 static void assertCsyncJournalOk(SyncJournalDb &journal) { // The DB is openend in locked mode: close to allow us to access. journal.close(); SqlDatabase db; QVERIFY(db.openReadOnly(journal.databaseFilePath())); SqlQuery q("SELECT count(*) from metadata where length(fileId) == 0", db); QVERIFY(q.exec()); QVERIFY(q.next().hasData); QCOMPARE(q.intValue(0), 0); #if defined(Q_OS_WIN) // Make sure the file does not appear in the FileInfo FileSystem::setFileHidden(journal.databaseFilePath() + "-shm", true); #endif }
void RemoteControl::sendTrackInfos(const QString &track) { if (!_webSocket) { return; } QStringList args; args << QString::number(CMD_Track); SqlDatabase db; TrackDAO dao = db.selectTrackByURI(track); args << dao.uri(); args << dao.artistAlbum(); args << dao.album(); args << dao.title(); args << dao.trackNumber(); args << QString::number(dao.rating()); _webSocket->sendTextMessage(args.join(QChar::Null)); // Send cover if any if (Cover *cover = db.selectCoverFromURI(track)) { _webSocket->sendBinaryMessage(cover->byteArray()); } }
/** Rebuild the list of separators when one has changed grammatical articles in options. */ void LibraryItemModel::rebuildSeparators() { SqlDatabase db; auto s = SettingsPrivate::instance(); QStringList filters; if (s->isLibraryFilteredByArticles() && !s->libraryFilteredByArticles().isEmpty()) { filters = s->libraryFilteredByArticles(); } // Reset custom displayed text, like "Artist, the" QHashIterator<SeparatorItem*, QModelIndex> i(_topLevelItems); while (i.hasNext()) { i.next(); if (auto item = itemFromIndex(i.value())) { if (!i.value().data(Miam::DF_CustomDisplayText).toString().isEmpty()) { item->setData(QString(), Miam::DF_CustomDisplayText); // Recompute standard normalized name: "The Artist" -> "theartist" item->setData(db.normalizeField(item->text()), Miam::DF_NormalizedString); } else if (!filters.isEmpty()) { for (QString filter : filters) { QString text = item->text(); if (text.startsWith(filter + " ", Qt::CaseInsensitive)) { text = text.mid(filter.length() + 1); item->setData(text + ", " + filter, Miam::DF_CustomDisplayText); item->setData(db.normalizeField(text), Miam::DF_NormalizedString); break; } } } } } // Delete separators first QSet<int> setRows; QHashIterator<QString, SeparatorItem*> it(_letters); while (it.hasNext()) { it.next(); setRows << it.value()->index().row(); } // Always remove items (rows) in reverse order QList<int> rows = setRows.toList(); std::sort(rows.begin(), rows.end(), std::greater<int>()); for (int row : rows) { auto item = takeItem(row); removeRow(row); delete item; } _letters.clear(); _topLevelItems.clear(); // Insert once again new separators for (int row = 0; row < rowCount(); row++) { auto item = this->item(row); if (item->type() != Miam::IT_Separator) { if (auto separator = this->insertSeparator(item)) { _topLevelItems.insert(separator, item->index()); } } } }
/** Redefined from MiamSortFilterProxyModel. */ bool UniqueLibraryFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QStandardItem *item = _model->itemFromIndex(_model->index(sourceRow, 1, sourceParent)); if (!item) { return false; } bool result = false; switch (item->type()) { case Miam::IT_Artist: if (MiamSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent)) { result = true; } else { SqlDatabase db; db.open(); QSqlQuery getArtist(db); getArtist.setForwardOnly(true); getArtist.prepare("SELECT * FROM tracks WHERE title LIKE ? AND artistId = ?"); getArtist.addBindValue("%" + filterRegExp().pattern() + "%"); getArtist.addBindValue(item->data(Miam::DF_ID).toUInt()); result = getArtist.exec() && getArtist.next(); } break; case Miam::IT_Album: if (MiamSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent)) { result = true; } else if (filterRegExp().indexIn(item->data(Miam::DF_Artist).toString()) != -1) { result = true; } else { SqlDatabase db; db.open(); QSqlQuery getAlbum(db); getAlbum.setForwardOnly(true); getAlbum.prepare("SELECT * FROM tracks WHERE title LIKE ? AND albumId = ?"); getAlbum.addBindValue("%" + filterRegExp().pattern() + "%"); getAlbum.addBindValue(item->data(Miam::DF_ID).toUInt()); result = getAlbum.exec() && getAlbum.next(); } break; case Miam::IT_Disc: if (filterRegExp().indexIn(item->data(Miam::DF_Artist).toString()) != -1) { result = true; } else { SqlDatabase db; db.open(); QSqlQuery getDiscAlbum(db); getDiscAlbum.setForwardOnly(true); getDiscAlbum.prepare("SELECT * FROM tracks WHERE disc > 0 AND title LIKE ? AND albumId = ?"); getDiscAlbum.addBindValue("%" + filterRegExp().pattern() + "%"); getDiscAlbum.addBindValue(item->data(Miam::DF_ID).toUInt()); result = getDiscAlbum.exec() && getDiscAlbum.next(); } break; case Miam::IT_Track: if (MiamSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent)) { result = true; } else { result = filterRegExp().indexIn(item->data(Miam::DF_Artist).toString()) != -1 || filterRegExp().indexIn(item->data(Miam::DF_Album).toString()) != -1; } break; case Miam::IT_Separator: for (QModelIndex index : _topLevelItems.values(static_cast<SeparatorItem*>(item))) { if (filterAcceptsRow(index.row(), sourceParent)) { result = true; } } break; default: break; } return result; }
SqlQuery::SqlQuery(const QString& sql, SqlDatabase& db) :_db(db.sqliteDb()), _stmt(0), _errId(0) { prepare(sql); }
SqlQuery::SqlQuery( SqlDatabase& db ) :_db(db.sqliteDb()), _stmt(0), _errId(0) { }
SqlQuery::SqlQuery(const QByteArray &sql, SqlDatabase &db) : _sqldb(&db) , _db(db.sqliteDb()) { prepare(sql); }
SqlQuery::SqlQuery(SqlDatabase &db) : _sqldb(&db) , _db(db.sqliteDb()) { }