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());
	}
}
/** 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;
}