void SyncUnmountableManager::AddFiles (const AddFilesParams& params)
	{
		auto coll = Core::Instance ().GetLocalCollection ();

		const auto& format = params.TCParams_.FormatID_;

		auto syncer = params.Syncer_;
		for (const auto& file : params.Files_)
		{
			const auto trackId = coll->FindTrack (file);
			if (trackId < 0)
				continue;

			const auto trackNumber = coll->GetCollectionModel ()->
					GetTrackData (trackId, LocalCollectionModel::Role::TrackNumber).toInt ();
			const auto& trackTitle = coll->GetCollectionModel ()->
					GetTrackData (trackId, LocalCollectionModel::Role::TrackTitle).toString ();

			const auto album = coll->GetTrackAlbum (trackId);
			if (!album)
				continue;

			const auto& artists = coll->GetAlbumArtists (album->ID_);
			if (artists.isEmpty ())
				continue;

			const auto& artist = coll->GetArtist (artists.at (0));

			syncer->SetFileInfo (file,
					{
						format.isEmpty () ?
							QFileInfo (file).suffix ().toLower () :
							format,
						trackNumber,
						trackTitle,
						artist.Name_,
						album->Name_,
						album->Year_,
						album->CoverPath_,
						QStringList ()
					});

			Source2Params_ [file] = params;
		}

		SyncManagerBase::AddFiles (params.Files_, params.TCParams_);
	}
	void LocalCollection::HandleExistingInfos (const QList<MediaInfo>& infos)
	{
		Q_FOREACH (const auto& info, infos)
		{
			const auto& path = info.LocalPath_;
			const auto trackIdx = FindTrack (path);
			const auto trackAlbum = GetTrackAlbum (trackIdx);
			if (!trackAlbum)
			{
				qWarning () << Q_FUNC_INFO
						<< "no album for track"
						<< path;
				continue;
			}

			const auto pos = std::find_if (trackAlbum->Tracks_.begin (), trackAlbum->Tracks_.end (),
					[trackIdx] (decltype (trackAlbum->Tracks_.front ()) track)
						{ return track.ID_ == trackIdx; });
			const auto& track = pos != trackAlbum->Tracks_.end () ?
					*pos :
					Collection::Track ();
			const auto& artist = GetArtist (AlbumID2ArtistID_ [trackAlbum->ID_]);
			if (artist.Name_ == info.Artist_ &&
					trackAlbum->Name_ == info.Album_ &&
					trackAlbum->Year_ == info.Year_ &&
					track.Number_ == info.TrackNumber_ &&
					track.Name_ == info.Title_ &&
					track.Genres_ == info.Genres_)
				continue;

			auto stats = GetTrackStats (path);
			RemoveTrack (path);

			const auto& newArts = Storage_->AddToCollection ({ info });
			HandleNewArtists (newArts);

			const auto newTrackIdx = FindTrack (path);
			stats.TrackID_ = newTrackIdx;
			Storage_->SetTrackStats (stats);
		}
	}
	void LocalCollection::RemoveTrack (const QString& path)
	{
		const int id = FindTrack (path);
		if (id == -1)
			return;

		auto album = GetTrackAlbum (id);
		try
		{
			Storage_->RemoveTrack (id);
		}
		catch (const std::exception& e)
		{
			qWarning () << Q_FUNC_INFO
					<< "error removing track:"
					<< e.what ();
			throw;
		}

		CollectionModel_->RemoveTrack (id);

		Path2Track_.remove (path);
		Track2Path_.remove (id);
		Track2Album_.remove (id);
		PresentPaths_.remove (path);

		if (!album)
			return;

		auto pos = std::remove_if (album->Tracks_.begin (), album->Tracks_.end (),
				[id] (decltype (album->Tracks_.front ()) item) { return item.ID_ == id; });
		album->Tracks_.erase (pos, album->Tracks_.end ());

		if (album->Tracks_.isEmpty ())
			RemoveAlbum (album->ID_);
	}