void MusicSearchEngine::doSearch()
{
	qDebug() << Q_FUNC_INFO;
	emit aboutToSearch();

	_db.init();

	QSqlQuery cleanDb(_db);
	cleanDb.setForwardOnly(true);
	//cleanDb.exec("DELETE FROM tracks WHERE uri LIKE 'file:%'");
	//cleanDb.exec("DELETE FROM albums WHERE id NOT IN (SELECT DISTINCT albumId FROM tracks)");
	//cleanDb.exec("DELETE FROM artists WHERE id NOT IN (SELECT DISTINCT artistId FROM tracks)");
	cleanDb.exec("DELETE FROM tracks");
	cleanDb.exec("DELETE FROM albums");
	cleanDb.exec("DELETE FROM artists");
	cleanDb.exec("DROP INDEX indexArtist");
	cleanDb.exec("DROP INDEX indexAlbum");
	cleanDb.exec("DROP INDEX indexPath");
	cleanDb.exec("DROP INDEX indexArtistId");
	cleanDb.exec("DROP INDEX indexAlbumId");
	_db.transaction();

	MusicSearchEngine::isScanning = true;
	QList<QDir> locations;
	QStringList pathsToSearch = _delta.isEmpty() ? SettingsPrivate::instance()->musicLocations() : _delta;
	for (QString musicPath : pathsToSearch) {
		QDir location(musicPath);
		location.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot);
		locations.append(location);
	}

	int entryCount = 0;
	// QDirIterator class is very fast to scan large directories
	for (QDir location : locations) {
		QDirIterator it(location.absolutePath(), QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
		while (it.hasNext()) {
			it.next();
			entryCount++;
		}
	}

	int currentEntry = 0;
	int percent = 1;
	bool atLeastOneAudioFileWasFound = false;
	bool isNewDirectory = false;

	QString coverPath;
	QString lastFileScannedNextToCover;

	QStringList suffixes = FileHelper::suffixes(FileHelper::All);

	for (QDir location : locations) {
		QDirIterator it(location.absolutePath(), QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
		while (it.hasNext()) {
			QString entry = it.next();
			QFileInfo qFileInfo(entry);
			currentEntry++;

			// Directory has changed: we can discard cover
			if (qFileInfo.isDir()) {
				if (!coverPath.isEmpty() && !lastFileScannedNextToCover.isEmpty()) {
					_db.saveCoverRef(coverPath, lastFileScannedNextToCover);
					coverPath.clear();
				}
				isNewDirectory = true;
				atLeastOneAudioFileWasFound = false;
				lastFileScannedNextToCover.clear();
				continue;
			} else if (qFileInfo.suffix().toLower() == "jpg" || qFileInfo.suffix().toLower() == "png") {
				if (atLeastOneAudioFileWasFound) {
					coverPath = qFileInfo.absoluteFilePath();
					_db.saveCoverRef(coverPath, lastFileScannedNextToCover);
					coverPath.clear();
				} else if (isNewDirectory) {
					coverPath = qFileInfo.absoluteFilePath();
				}
			} else if (suffixes.contains(qFileInfo.suffix())) {
				_db.saveFileRef(qFileInfo.absoluteFilePath());
				atLeastOneAudioFileWasFound = true;
				lastFileScannedNextToCover = qFileInfo.absoluteFilePath();
				isNewDirectory = false;
			}

			if (currentEntry * 100 / entryCount > percent) {
				percent = currentEntry * 100 / entryCount;
				emit progressChanged(percent);
				qApp->processEvents();
			}
		}
		atLeastOneAudioFileWasFound = false;
	}

	_db.commit();

	QSqlQuery index(_db);
	index.exec("CREATE INDEX IF NOT EXISTS indexArtist ON tracks (artistId)");
	index.exec("CREATE INDEX IF NOT EXISTS indexAlbum ON tracks (albumId)");
	index.exec("CREATE INDEX IF NOT EXISTS indexPath ON tracks (uri)");
	index.exec("CREATE INDEX IF NOT EXISTS indexArtistId ON artists (id)");
	index.exec("CREATE INDEX IF NOT EXISTS indexAlbumId ON albums (id)");

	// Resync remote players and remote databases
	//emit aboutToResyncRemoteSources();

	MusicSearchEngine::isScanning = false;
	emit searchHasEnded();

	this->deleteLater();
}
void MusicSearchEngine::doSearch(const QStringList &delta)
{
	//qDebug() << Q_FUNC_INFO << delta;
	MusicSearchEngine::isScanning = true;
	QList<QDir> locations;
	QStringList pathsToSearch = delta.isEmpty() ? SettingsPrivate::instance()->musicLocations() : delta;
	for (QString musicPath : pathsToSearch) {
		QDir location(musicPath);
		location.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot);
		locations.append(location);
	}

	int entryCount = 0;
	// QDirIterator class is very fast to scan large directories
	for (QDir location : locations) {
		QDirIterator it(location.absolutePath(), QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
		while (it.hasNext()) {
			it.next();
			entryCount++;
		}
	}

	int currentEntry = 0;
	int percent = 1;
	bool atLeastOneAudioFileWasFound = false;
	bool isNewDirectory = false;

	QString coverPath;
	QString lastFileScannedNextToCover;

	QStringList suffixes = FileHelper::suffixes(FileHelper::All);

	for (QDir location : locations) {
		QDirIterator it(location.absolutePath(), QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
		while (it.hasNext()) {
			QString entry = it.next();
			QFileInfo qFileInfo(entry);
			currentEntry++;

			// Directory has changed: we can discard cover
			if (qFileInfo.isDir()) {
				if (!coverPath.isEmpty() && !lastFileScannedNextToCover.isEmpty()) {
					emit scannedCover(coverPath, lastFileScannedNextToCover);
					coverPath.clear();
				}
				isNewDirectory = true;
				atLeastOneAudioFileWasFound = false;
				lastFileScannedNextToCover.clear();
				continue;
			} else if (qFileInfo.suffix().toLower() == "jpg" || qFileInfo.suffix().toLower() == "png") {
				if (atLeastOneAudioFileWasFound) {
					coverPath = qFileInfo.absoluteFilePath();
					emit scannedCover(coverPath, lastFileScannedNextToCover);
					coverPath.clear();
				} else if (isNewDirectory) {
					coverPath = qFileInfo.absoluteFilePath();
				}
			} else if (suffixes.contains(qFileInfo.suffix())) {
				emit scannedFile(qFileInfo.absoluteFilePath());
				atLeastOneAudioFileWasFound = true;
				lastFileScannedNextToCover = qFileInfo.absoluteFilePath();
				isNewDirectory = false;
			}

			if (currentEntry * 100 / entryCount > percent) {
				percent = currentEntry * 100 / entryCount;
				emit progressChanged(percent);
			}
		}
		atLeastOneAudioFileWasFound = false;
	}
	emit searchHasEnded();
	MusicSearchEngine::isScanning = false;
}