Ejemplo n.º 1
1
// watcher
void CoverArtCache::coverLoaded() {
    QFutureWatcher<FutureResult>* watcher;
    watcher = reinterpret_cast<QFutureWatcher<FutureResult>*>(sender());
    FutureResult res = watcher->result();

    if (sDebug) {
        kLogger.debug() << "coverLoaded" << res.cover;
    }

    // Don't cache full size covers (resizedToWidth = 0)
    // Large cover art wastes space in our cache and will likely
    // uncache a lot of the small covers we need in the library
    // table.
    // Full size covers are used in the Skin Widgets, which are
    // loaded with an artificial delay anyway and an additional
    // re-load delay can be accepted.

    // Create pixmap, GUI thread only
    QPixmap pixmap = QPixmap::fromImage(res.cover.image);
    if (!pixmap.isNull() && res.cover.resizedToWidth != 0) {
        // we have to be sure that res.cover.hash is unique
        // because insert replaces the images with the same key
        QString cacheKey = pixmapCacheKey(
                res.cover.hash, res.cover.resizedToWidth);
        QPixmapCache::insert(cacheKey, pixmap);
    }

    m_runningRequests.remove(qMakePair(res.pRequestor, res.cover.hash));

    if (res.signalWhenDone) {
        emit(coverFound(res.pRequestor, res.cover, pixmap, false));
    }
}
Ejemplo n.º 2
0
void KWin::Script::slotScriptLoadedFromFile()
{
    QFutureWatcher<QByteArray> *watcher = dynamic_cast< QFutureWatcher< QByteArray>* >(sender());
    if (!watcher) {
        // not invoked from a QFutureWatcher
        return;
    }
    if (watcher->result().isNull()) {
        // do not load empty script
        deleteLater();
        watcher->deleteLater();
        return;
    }
    QScriptValue optionsValue = m_engine->newQObject(options, QScriptEngine::QtOwnership,
                            QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater);
    m_engine->globalObject().setProperty(QStringLiteral("options"), optionsValue, QScriptValue::Undeletable);
    m_engine->globalObject().setProperty(QStringLiteral("QTimer"), constructTimerClass(m_engine));
    QObject::connect(m_engine, SIGNAL(signalHandlerException(QScriptValue)), this, SLOT(sigException(QScriptValue)));
    KWin::MetaScripting::supplyConfig(m_engine);
    installScriptFunctions(m_engine);

    QScriptValue ret = m_engine->evaluate(QString::fromUtf8(watcher->result()));

    if (ret.isError()) {
        sigException(ret);
        deleteLater();
    }

    watcher->deleteLater();
    setRunning(true);
    m_starting = false;
}
Ejemplo n.º 3
0
void PatternManager::thresholdImageFinished() {
    QFutureWatcher<cv::Mat*>* watcher = static_cast<QFutureWatcher<cv::Mat*>*>(QObject::sender());
    this->m_thresholdedPatterns.push_back(watcher->result());
    qDebug() << "Image thresholded " << watcher->result()->depth();
    delete watcher;
    emit imgThresholded(this->m_thresholdedPatterns.size());
    if(this->m_thresholdedPatterns.size() == patternSetSize) {
        emit originalPatternsThresholded();
        qDebug("All images thresholded");
    }
}
Ejemplo n.º 4
0
void EditTagDialog::SetSongsFinished() {
  QFutureWatcher<QList<Data> >* watcher =
      dynamic_cast<QFutureWatcher<QList<Data> >*>(sender());
  if (!watcher) return;
  watcher->deleteLater();

  if (!SetLoading(QString())) return;

  data_ = watcher->result();
  if (data_.count() == 0) {
    // If there were no valid songs, disable everything
    ui_->song_list->setEnabled(false);
    ui_->tab_widget->setEnabled(false);

    // Show a summary with empty information
    UpdateSummaryTab(Song());
    ui_->tab_widget->setCurrentWidget(ui_->summary_tab);

    SetSongListVisibility(false);
    return;
  }

  // Add the filenames to the list
  for (const Data& data : data_) {
    ui_->song_list->addItem(data.current_.basefilename());
  }

  // Select all
  ui_->song_list->setCurrentRow(0);
  ui_->song_list->selectAll();

  // Hide the list if there's only one song in it
  SetSongListVisibility(data_.count() != 1);
}
Ejemplo n.º 5
0
    void downloadFile()
    {
        QTemporaryFile file;
        file.setAutoRemove(false);

        if (file.open()) {
            const QString filename = file.fileName();
            QInstaller::blockingWrite(&file, QByteArray(scLargeSize, '1'));
            file.close();

            DownloadFileTask fileTask(QLatin1String("file:///") + filename);
            QFutureWatcher<FileTaskResult> watcher;

            QSignalSpy started(&watcher, SIGNAL(started()));
            QSignalSpy finished(&watcher, SIGNAL(finished()));
            QSignalSpy progress(&watcher, SIGNAL(progressValueChanged(int)));

            watcher.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, &fileTask));

            watcher.waitForFinished();
            QTest::qWait(10); // Spin the event loop to deliver queued signals.

            QCOMPARE(started.count(), 1);
            QCOMPARE(finished.count(), 1);

            FileTaskResult result = watcher.result();
            QCOMPARE(watcher.future().resultCount(), 1);

            QVERIFY(QFile(result.target()).exists());
            QCOMPARE(file.size(), QFile(result.target()).size());
            QCOMPARE(result.checkSum().toHex(), QByteArray("85304f87b8d90554a63c6f6d1e9cc974fbef8d32"));
        }
    }
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 );
}
Ejemplo n.º 7
0
void DocsetRegistry::loadDocset(const QString &path)
{
    QFutureWatcher<Docset *> *watcher = new QFutureWatcher<Docset *>();
    connect(watcher, &QFutureWatcher<Docset *>::finished, this, [this, watcher] {
        QScopedPointer<QFutureWatcher<Docset *>, QScopedPointerDeleteLater> guard(watcher);

        Docset *docset = watcher->result();
        // TODO: Emit error
        if (!docset->isValid()) {
            qWarning("Could not load docset from '%s'. Reinstall the docset.",
                     qPrintable(docset->path()));
            delete docset;
            return;
        }

        docset->setFuzzySearchEnabled(m_fuzzySearchEnabled);

        const QString name = docset->name();
        if (m_docsets.contains(name)) {
            unloadDocset(name);
        }

        m_docsets[name] = docset;
        emit docsetLoaded(name);
    });

    watcher->setFuture(QtConcurrent::run([path] {
        return new Docset(path);
    }));
}
Ejemplo n.º 8
0
QVariant ThumbnailModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::DecorationRole && index.isValid()) {
        QString id = itemId(index).toString();

        QFutureWatcher<QImage> *future = cache.object(id);

        if (!future) {
            future = new QFutureWatcher<QImage>;

            QString path = imagePath(index);

            if (!path.isEmpty()) {
                future->setFuture(QtConcurrent::run(ThumbnailModel::load, path));

                connect(future, SIGNAL(finished()), this, SLOT(thumbnailLoaded()));
            }

            cache.insert(id, future);
        }

        return !future->isCanceled()
                ? future->result()
                : QVariant();
    } else {
        return QGalleryQueryModel::data(index, role);
    }
}
Ejemplo n.º 9
0
void Fix8Log::finishedReadingDataFileSlot()
{
    qDebug() << "Finishded future reading..";
    QFutureWatcher<FutureReadData *> *watcher =
            (QFutureWatcher<FutureReadData *> *)sender();
    FutureReadData *frd = watcher->result();
}
Ejemplo n.º 10
0
sqlqueryresultlist searchhandler::perform_grep(QString searchtxt, sqlqueryresultlist searchlist, bool exactmatch)
{
	QVector<QString> strvec;
	sqlqueryresultlist resultlist;
	QFutureWatcher<sqlqueryresultlist> futureWatcher;
	QProgressDialog dialog;
	unsigned int n = searchlist.resultlist.size();
	if (n == 0) return resultlist;
	strvec.resize(n);
	for (unsigned int i=0; i < n; i++)
	{
		strvec.replace(i, str2qt(searchlist.resultlist[i].filepath));
	}
	dialog.setAutoReset(false);
	dialog.setLabelText(QString("Grep ").append(QString(tr("in progress"))).append(QString(" ...")));
	dialog.setCancelButtonText(tr("Cancel"));
	QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset()));
	QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
	QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int)));
	QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
	m_grepExactMatch = exactmatch;
	(*m_grepRegExp) = QRegExp(searchtxt.toAscii().data(), Qt::CaseInsensitive);
	m_grepRegExp->setPatternSyntax(QRegExp::RegExp2);
	futureWatcher.setFuture(QtConcurrent::mappedReduced(strvec, doGrep,
				collateGrep, QtConcurrent::SequentialReduce));
	dialog.exec();
	futureWatcher.waitForFinished();
	if (futureWatcher.isCanceled() == false)
		resultlist = futureWatcher.result();
	return resultlist;
}
Ejemplo n.º 11
0
void tst_QFutureWatcher::resultAt()
{
    QFutureWatcher<int> futureWatcher;
    futureWatcher.setFuture((new IntTask())->start());
    futureWatcher.waitForFinished();
    QCOMPARE(futureWatcher.result(), 10);
    QCOMPARE(futureWatcher.resultAt(0), 10);
}
Ejemplo n.º 12
0
void TagCompleter::ModelReady() {
  QFutureWatcher<TagCompletionModel*>* watcher =
      dynamic_cast<QFutureWatcher<TagCompletionModel*>*>(sender());
  if (!watcher) return;

  TagCompletionModel* model = watcher->result();
  setModel(model);
  setCaseSensitivity(Qt::CaseInsensitive);
  editor_->setCompleter(this);
}
Ejemplo n.º 13
0
void AttachDialog::updateProcessesFinished()
{
  QFutureWatcher<ProcDataList>* watcher = dynamic_cast<QFutureWatcher<ProcDataList>*>(sender());
  Q_ASSERT(watcher);
  ui.stackedWidget->setCurrentWidget(ui.listViewPage);
  const int oldPid = pid();
  m_model->mergeProcesses(watcher->result());
  if (oldPid != pid()) {
    ui.view->setCurrentIndex(QModelIndex());
  }
  watcher->deleteLater();
}
Ejemplo n.º 14
0
void PrettyImage::ImageScaled() {
  QFutureWatcher<QImage>* watcher =
      reinterpret_cast<QFutureWatcher<QImage>*>(sender());
  if (!watcher) return;
  watcher->deleteLater();

  thumbnail_ = QPixmap::fromImage(watcher->result());
  state_ = State_Finished;

  updateGeometry();
  update();
  emit Loaded();
}
Ejemplo n.º 15
0
void PatternManager::fileLoadFinished()
{
    qDebug("file loaded signal");
    //QProgressBar* watcher2 = qobject_cast<QProgressBar*>(QObject::sender());
    QFutureWatcher<cv::Mat*>* watcher = static_cast<QFutureWatcher<cv::Mat*>*>(QObject::sender());
    this->m_originalPatterns.push_back(watcher->result());
    //Do I need to delete the watcher now???
    delete watcher;
    emit fileLoaded(this->m_originalPatterns.size());
    if(this->m_originalPatterns.size() == patternSetSize) {
        emit originalPatternsLoaded();
    }
}
void AccountsWorker::createAccount(const User *user)
{
    qDebug() << "create account " << user;
    Q_EMIT requestFrameAutoHide(false);

    QFutureWatcher<CreationResult*> *watcher = new QFutureWatcher<CreationResult*>(this);
    connect(watcher, &QFutureWatcher<CreationResult*>::finished, [this, watcher] {
        CreationResult *result = watcher->result();
        Q_EMIT accountCreationFinished(result);
        Q_EMIT requestFrameAutoHide(true);
        watcher->deleteLater();
    });

    QFuture<CreationResult*> future = QtConcurrent::run(this, &AccountsWorker::createAccountInternal, user);
    watcher->setFuture(future);
}
Ejemplo n.º 17
0
void DownloadSizeFinder::watcherFinished()
{
    QFutureWatcher<DownloadFile>* w = static_cast<
            QFutureWatcher<DownloadFile>*>(sender());
    DownloadFile r = w->result();

    this->mutex.lock();
    if (r.error.isEmpty())
        this->files.insert(r.url, QString::number(r.size));
    else
        this->files.insert(r.url, "*" + r.error);
    this->mutex.unlock();

    emit this->downloadCompleted(r.url, r.size, r.error);

    w->deleteLater();
}
Ejemplo n.º 18
0
int main(int argc, char **argv)
{
    QCoreApplication application(argc, argv);

    if(application.arguments().count() < 4+1) {
        qDebug() << "Usage:" << argv[0] << "order" << "width" << "height" << "output";
        return 0;
    }

// /////////////////////////////////////////////////////////////////
// Single concurrent run preprocessing
// /////////////////////////////////////////////////////////////////

    qtrRenderer::newtonOrder = application.arguments().value(1).toInt();

    qtrTile tile;
    tile.setWholeRect(QRect(0, 0,
        application.arguments().value(2).toInt(),
        application.arguments().value(3).toInt()));
    tile.setTileRect(QRect(0, 0,
        application.arguments().value(2).toInt(),
        application.arguments().value(3).toInt()));

// /////////////////////////////////////////////////////////////////
// Single concurrent run
// /////////////////////////////////////////////////////////////////

    QFuture<QImage> future = QtConcurrent::run(qtrRenderer::newtonImage, tile);

    QFutureWatcher<QImage> watcher;
    watcher.setFuture(future);
    watcher.waitForFinished();

// /////////////////////////////////////////////////////////////////
// Single concurrent run postprocessing
// /////////////////////////////////////////////////////////////////

    watcher.result().save(application.arguments().value(4));

    return 0;
}
Ejemplo n.º 19
0
void PluginEffectLoader::queryAndLoadAll()
{
    if (m_queryConnection) {
        return;
    }
    // perform querying for the services in a thread
    QFutureWatcher<QVector<KPluginMetaData>> *watcher = new QFutureWatcher<QVector<KPluginMetaData>>(this);
    m_queryConnection = connect(watcher, &QFutureWatcher<QVector<KPluginMetaData>>::finished, this,
        [this, watcher]() {
            const auto effects = watcher->result();
            for (const auto &effect : effects) {
                const LoadEffectFlags flags = readConfig(effect.pluginId(), effect.isEnabledByDefault());
                if (flags.testFlag(LoadEffectFlag::Load)) {
                    m_queue->enqueue(qMakePair(effect, flags));
                }
            }
            watcher->deleteLater();
            m_queryConnection = QMetaObject::Connection();
        },
        Qt::QueuedConnection);
    watcher->setFuture(QtConcurrent::run(this, &PluginEffectLoader::findAllEffects));
}
Ejemplo n.º 20
0
// watcher
void CoverArtCache::coverLoaded() {
    QFutureWatcher<FutureResult>* watcher;
    watcher = reinterpret_cast<QFutureWatcher<FutureResult>*>(sender());
    FutureResult res = watcher->result();

    if (sDebug) {
        qDebug() << "CoverArtCache::coverLoaded" << res.cover;
    }

    QString cacheKey = CoverArtUtils::pixmapCacheKey(res.cover.info.hash,
                                                     res.desiredWidth);
    QPixmap pixmap;
    if (!QPixmapCache::find(cacheKey, &pixmap) && !res.cover.image.isNull()) {
        pixmap.convertFromImage(res.cover.image);
        QPixmapCache::insert(cacheKey, pixmap);
    }
    m_runningRequests.remove(qMakePair(res.pRequestor, res.requestReference));

    if (res.signalWhenDone) {
        emit(coverFound(res.pRequestor, res.requestReference,
                        res.cover.info, pixmap, false));
    }
}
Ejemplo n.º 21
0
bool FileManager::removeRecursively(const QString &path)
{
    qCDebug(log, "Removing '%s'...", qPrintable(path));

    if (!QFileInfo(path).isDir()) {
        qCWarning(log, "'%s' is not a directory.", qPrintable(path));
        return false;
    }

    const QString deletePath = QStringLiteral("%1.%2.deleteme")
            .arg(path, QString::number(QDateTime::currentMSecsSinceEpoch()));

    if (!QDir().rename(path, deletePath)) {
        qCWarning(log, "Failed to rename '%s' to '%s'.", qPrintable(path), qPrintable(deletePath));
        return false;
    } else {
        qCDebug(log, "Renamed '%s' to '%s'.", qPrintable(path), qPrintable(deletePath));
    }


    QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>();
    connect(watcher, &QFutureWatcher<bool>::finished, [=] {
        if (!watcher->result()) {
            qCWarning(log, "Failed to remove '%s'.", qPrintable(deletePath));
        } else {
            qCDebug(log, "Removed '%s'.", qPrintable(deletePath));
        }

        watcher->deleteLater();
    });

    watcher->setFuture(QtConcurrent::run([deletePath] {
        return QDir(deletePath).removeRecursively();
    }));

    return true;
}
void IcecastService::ParseDirectoryFinished() {
  QFutureWatcher<IcecastBackend::StationList >* watcher =
      static_cast<QFutureWatcher<IcecastBackend::StationList>*>(sender());
  IcecastBackend::StationList all_stations = watcher->result();
  sort(all_stations.begin(), all_stations.end(), StationSorter<IcecastBackend::Station>());
  // Remove duplicates by name. These tend to be multiple URLs for the same station.
  IcecastBackend::StationList::iterator it =
      unique(all_stations.begin(), all_stations.end(), StationEquality<IcecastBackend::Station>());
  all_stations.erase(it, all_stations.end());

  // Cluster stations by genre.
  QMultiHash<QString, IcecastBackend::Station*> genres;

  // Add stations.
  for (int i=0 ; i<all_stations.count() ; ++i) {
    IcecastBackend::Station& s = all_stations[i];
    genres.insert(s.genre, &s);
  }

  QSet<QString> genre_set = genres.keys().toSet();

  // Merge genres with only 1 or 2 stations into "Other".
  foreach (const QString& genre, genre_set) {
    if (genres.count(genre) < 3) {
      const QList<IcecastBackend::Station*>& small_genre = genres.values(genre);
      foreach (IcecastBackend::Station* s, small_genre) {
        s->genre = "Other";
      }
    }
  }

  backend_->ClearAndAddStations(all_stations);
  delete watcher;

  model()->task_manager()->SetTaskFinished(load_directory_task_id_);
  load_directory_task_id_ = 0;
}
Ejemplo n.º 23
0
void SettingsDialog::removeDocsets(const QStringList &names)
{
    for (const QString &name : names) {
        const QString title = m_docsetRegistry->docset(name)->title();
        m_docsetRegistry->remove(name);

        const QDir dataDir(m_application->settings()->docsetPath);
        if (dataDir.exists()) {
            ui->docsetsProgress->show();
            ui->removeDocsetsButton->setEnabled(false);
            displayProgress();

            QFuture<bool> future = QtConcurrent::run([=] {
                QDir docsetDir(dataDir);
                return docsetDir.cd(name + QLatin1String(".docset"))
                        && docsetDir.removeRecursively();
            });
            QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>();
            watcher->setFuture(future);
            connect(watcher, &QFutureWatcher<void>::finished, [=] {
                if (!watcher->result()) {
                    QMessageBox::warning(this, tr("Error"),
                                         QString(tr("Cannot delete docset <b>%1</b>!")).arg(title));
                }

                resetProgress();

                QListWidgetItem *listItem = findDocsetListItem(title);
                if (listItem)
                    listItem->setHidden(false);

                watcher->deleteLater();
            });
        }
    }
}
Ejemplo n.º 24
0
void ClipboardJob::start()
{
    const QString operation = operationName();
    // first check for operations not needing an item
    if (operation == QLatin1String("clearHistory")) {
        m_klipper->slotAskClearHistory();
        setResult(true);
        emitResult();
        return;
    } else if (operation == QLatin1String("configureKlipper")) {
        m_klipper->slotConfigure();
        setResult(true);
        emitResult();
        return;
    }

    // other operations need the item
    HistoryItemConstPtr item = m_klipper->history()->find(QByteArray::fromBase64(destination().toUtf8()));
    if (item.isNull()) {
        setResult(false);
        emitResult();
        return;
    }
    if (operation == QLatin1String("select")) {
        m_klipper->history()->slotMoveToTop(item->uuid());
        setResult(true);
    } else if (operation == QLatin1String("remove")) {
        m_klipper->history()->remove(item);
        setResult(true);
    } else if (operation == QLatin1String("edit")) {
        connect(m_klipper, &Klipper::editFinished, this,
            [this, item](HistoryItemConstPtr editedItem, int result) {
                if (item != editedItem) {
                    // not our item
                    return;
                }
                setResult(result);
                emitResult();
            }
        );
        m_klipper->editData(item);
        return;
    } else if (operation == QLatin1String("barcode")) {
#ifdef HAVE_PRISON
        int pixelWidth = parameters().value(QStringLiteral("width")).toInt();
        int pixelHeight = parameters().value(QStringLiteral("height")).toInt();
        Prison::AbstractBarcode *code = nullptr;
        switch (parameters().value(QStringLiteral("barcodeType")).toInt()) {
        case 1: {
            code = Prison::createBarcode(Prison::DataMatrix);
            const int size = qMin(pixelWidth, pixelHeight);
            pixelWidth = size;
            pixelHeight = size;
            break;
        }
        case 2: {
            code = Prison::createBarcode(Prison::Code39);
            break;
        }
        case 3: {
            code = Prison::createBarcode(Prison::Code93);
            break;
        }
        case 0:
        default: {
            code = Prison::createBarcode(Prison::QRCode);
            const int size = qMin(pixelWidth, pixelHeight);
            pixelWidth = size;
            pixelHeight = size;
            break;
        }
        }
        if (code) {
            code->setData(item->text());
            QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this);
            connect(watcher, &QFutureWatcher<QImage>::finished, this,
                [this, watcher, code] {
                    setResult(watcher->result());
                    watcher->deleteLater();
                    delete code;
                    emitResult();
                }
            );
            auto future = QtConcurrent::run(code, &Prison::AbstractBarcode::toImage, QSizeF(pixelWidth, pixelHeight));
            watcher->setFuture(future);
            return;
        } else {
            setResult(false);
        }
#else
        setResult(false);
#endif
    } else if (operation == QLatin1String("action")) {
        m_klipper->urlGrabber()->invokeAction(item);
        setResult(true);

    } else if (operation == s_previewKey) {
        const int pixelWidth = parameters().value(s_previewWidthKey).toInt();
        const int pixelHeight = parameters().value(s_previewHeightKey).toInt();
        QUrl url = parameters().value(s_urlKey).toUrl();
        qCDebug(KLIPPER_LOG) << "URL: " << url;
        KFileItem item(url);

        if (pixelWidth <= 0 || pixelHeight <= 0) {
            qCWarning(KLIPPER_LOG) << "Preview size invalid: " << pixelWidth << "x" << pixelHeight;
            iconResult(item);
            return;
        }

        if (!url.isValid() || !url.isLocalFile()) { // no remote files
            qCWarning(KLIPPER_LOG) << "Invalid or non-local url for preview: " << url;
            iconResult(item);
            return;
        }

        KFileItemList urls;
        urls << item;

        KIO::PreviewJob* job = KIO::filePreview(urls, QSize(pixelWidth, pixelHeight));
        job->setIgnoreMaximumSize(true);
        connect(job, &KIO::PreviewJob::gotPreview, this,
            [this](const KFileItem &item, const QPixmap &preview) {
                QVariantMap res;
                res.insert(s_urlKey, item.url());
                res.insert(s_previewKey, preview);
                res.insert(s_iconKey, false);
                res.insert(s_previewWidthKey, preview.size().width());
                res.insert(s_previewHeightKey, preview.size().height());
                setResult(res);
                emitResult();
            }
        );
        connect(job, &KIO::PreviewJob::failed, this,
            [this](const KFileItem &item) {
                iconResult(item);
            }
        );

        job->start();

        return;
    } else {
        setResult(false);
    }
    emitResult();
}