void SpellCheckerCore::futureFinished()
{
  /* Get the watcher from the sender() of the signal that invoked this slot.
   * reinterpret_cast is used since qobject_cast is not valid of template
   * classes since the template class does not have the Q_OBJECT macro. */
  QFutureWatcher<WordList>* watcher = reinterpret_cast<QFutureWatcher<WordList>*>( sender() );
  if( watcher == nullptr ) {
    return;
  }

  if( d->shuttingDown == true ) {
    /* Application shutting down, should not try something */
    return;
  }
  if( watcher->isCanceled() == true ) {
    /* Application is shutting down */
    return;
  }
  /* Get the list of words with spelling mistakes from the future. */
  WordList checkedWords = watcher->result();
  QMutexLocker locker( &d->futureMutex );
  /* Recheck again after getting the lock. */
  if( d->shuttingDown == true ) {
    return;
  }
  /* Get the file name associated with this future and the misspelled
   * words. */
  FutureWatcherMapIter iter = d->futureWatchers.find( watcher );
  if( iter == d->futureWatchers.end() ) {
    return;
  }
  QString fileName = iter.value();
  /* Remove the watcher from the list of running watchers and the file that
   * kept track of the file getting spell checked. */
  d->futureWatchers.erase( iter );
  d->filesInProcess.removeAll( fileName );
  /* Check if the file was scheduled for a re-check. As discussed previously,
   * if a spell check was requested for a file that had a future already in
   * progress, it was scheduled for a re-check as soon as the in progress one
   * completes. If it was scheduled, restart it using the normal slot. */
  QHash<QString, WordList>::iterator waitingIter = d->filesWaitingForProcess.find( fileName );
  if( waitingIter != d->filesWaitingForProcess.end() ) {
    WordList wordsToSpellCheck = waitingIter.value();
    /* remove the file and words from the scheduled list. */
    d->filesWaitingForProcess.erase( waitingIter );
    locker.unlock();
    /* Invoke the method to make sure that it gets called from the main thread.
     * This will most probably be already in the main thread, but to make sure
     * it is done like this. */
    this->metaObject()->invokeMethod( this
                                      , "spellcheckWordsFromParser"
                                      , Qt::QueuedConnection
                                      , Q_ARG( QString, fileName )
                                      , Q_ARG( SpellChecker::WordList, wordsToSpellCheck ) );
  }
  locker.unlock();
  watcher->deleteLater();
  /* Add the list of misspelled words to the mistakes model */
  addMisspelledWords( fileName, checkedWords );
}
void SpellCheckerCore::cancelFutures()
{
    QMutexLocker lock(&d->futureMutex);
    /* Iterate the futures and cancel them. */
    FutureWatcherMapIter iter = d->futureWatchers.begin();
    for(iter = d->futureWatchers.begin(); iter != d->futureWatchers.end(); ++iter) {
        iter.key()->future().cancel();
    }
}
void SpellCheckerCore::cancelFutures()
{
  QMutexLocker lock( &d->futureMutex );
  /* Iterate the futures and cancel them. */
  FutureWatcherMapIter iter = d->futureWatchers.begin();
  for( iter = d->futureWatchers.begin(); iter != d->futureWatchers.end(); ++iter ) {
    iter.key()->future().cancel();
  }

  /* Wait on the futures and delete the futures */
  for( iter = d->futureWatchers.begin(); iter != d->futureWatchers.end(); ++iter ) {
    iter.key()->future().waitForFinished();
    delete iter.key();
  }
  d->futureWatchers.clear();
}