void EnzymesSelectorWidget::loadFile(const QString& url) {
    TaskStateInfo ti;
    QList<SEnzymeData> enzymes;

    if (!QFileInfo(url).exists()) {
        ti.setError(  tr("File not exists: %1").arg(url) );
    } else {
        GTIMER(c1,t1,"FindEnzymesDialog::loadFile [EnzymesIO::readEnzymes]");
        enzymes = EnzymesIO::readEnzymes(url, ti);
    }
    if (ti.hasError()) {
        if (isVisible()) {
            QMessageBox::critical(NULL, tr("Error"), ti.getError());
        } else  {
            ioLog.error(ti.getError());
        }
        return;
    }
    if (!enzymes.isEmpty()) {
        if (AppContext::getSettings()->getValue(EnzymeSettings::DATA_FILE_KEY).toString() != url) {
            lastSelection.clear();
        }
        AppContext::getSettings()->setValue(EnzymeSettings::DATA_FILE_KEY, url);
    }

    setEnzymesList(enzymes);
}
void EnzymesSelectorWidget::saveFile(const QString& url) {
    TaskStateInfo ti;
    QString source = AppContext::getSettings()->getValue(EnzymeSettings::DATA_FILE_KEY).toString();

    GTIMER(c1,t1,"FindEnzymesDialog::saveFile [EnzymesIO::writeEnzymes]");

    QSet<QString> enzymes;

    for(int i=0, n = tree->topLevelItemCount(); i<n; i++){
        EnzymeGroupTreeItem* gi = static_cast<EnzymeGroupTreeItem*>(tree->topLevelItem(i));
        for (int j=0, m = gi->childCount(); j < m; j++) {
            EnzymeTreeItem* item = static_cast<EnzymeTreeItem*>(gi->child(j));
            if (item->checkState(0) == Qt::Checked) {
                enzymes.insert(item->enzyme->id);
            }
        }
    }

    EnzymesIO::writeEnzymes(url, source, enzymes, ti);

    if (ti.hasError()) {
        if (isVisible()) {
            QMessageBox::critical(NULL, tr("Error"), ti.getError());
        } else  {
            uiLog.error(ti.getError());
        }
        return;
    }
    if (QMessageBox::question(this, tr("New enzymes database has been saved."),
        tr("Do you want to work with new database?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
            loadFile(url);
    }
}
void EnzymesSelectorWidget::setEnzymesList(const QList<SEnzymeData>& enzymes) {
    tree->setSortingEnabled(false);
    tree->disconnect(this);
    tree->clear();
    totalEnzymes = 0;

    GTIMER(c2,t2,"FindEnzymesDialog::loadFile [refill data tree]");

    enzymesFilterEdit->clear();

    foreach (const SEnzymeData& enz, enzymes) {
        EnzymeTreeItem* item = new EnzymeTreeItem(enz);
        if (lastSelection.contains(enz->id)) {
            item->setCheckState(0, Qt::Checked);
        }
        totalEnzymes++;
        EnzymeGroupTreeItem* gi = findGroupItem(enz->id.isEmpty() ? QString(" ") : enz->id.left(1), true);
        gi->addChild(item);

    }
void ReadShortReadsSubTask::run() {
    stateInfo.setProgress(0);
    GTIMER(cvar, tvar, "ReadSubTask");
    GenomeAlignerTask *parent = static_cast<GenomeAlignerTask*>(getParentTask());
    if (!alignContext.bestMode) {
        parent->pWriteTask->flush();
    }

    alignContext.cleanVectors();
    dataBunch = new DataBunch();

    if (isCanceled()) {
        readingFinishedWakeAll();
        return;
    }
    qint64 m = freeMemorySize;
    taskLog.details(QString("Memory size is %1").arg(m));
    bool alignReversed = settings.getCustomValue(GenomeAlignerTask::OPTION_ALIGN_REVERSED, true).toBool();
    int qualityThreshold = settings.getCustomValue(GenomeAlignerTask::OPTION_QUAL_THRESHOLD, 0).toInt();

    DNATranslation* transl = AppContext::getDNATranslationRegistry()->
        lookupTranslation(BaseDNATranslationIds::NUCL_DNA_DEFAULT_COMPLEMENT);

    alignContext.isReadingStarted = true;
    bunchSize = 0;
    int readNum = 0;
    while(!seqReader->isEnd()) {
        if (isCanceled()) {
            readingFinishedWakeAll();
            return;
        }
        SearchQuery *query = seqReader->read();
        if (NULL == query) {
            if (!seqReader->isEnd()) {
                setError("Short-reads object type must be a sequence, but not a multiple alignment");
                readingFinishedWakeAll();
                return;
            }
            break;
        }
        ++bunchSize;

        if (!checkDnaQuality(query, qualityThreshold)) {
            continue;
        }
        updateMinMaxReadLengths(alignContext, query->length());

        int W = 0, q = 0;
        int CMAX = alignContext.nMismatches;
        if (!add(CMAX, W, q, readNum, query, parent)) {
            delete query;
            continue;
        }
        m -= query->memoryHint();

        if (alignReversed) {
            SearchQuery *rQu = createRevComplQuery(query, transl);
            if (rQu) {
                add(CMAX, W, q, readNum, rQu, parent);
                m -= rQu->memoryHint();
            }
        }

        qint64 alignContextMemoryHint = dataBunch->memoryHint();
        if (m <= alignContextMemoryHint + prevMemoryHint) {
            break;
        }

        SAFE_POINT(NULL != dataBunch, "No dataBunch",);
        if (dataBunch->bitValuesV.size() > DROP_BUNCH_DATA_SIZE) {
            dropToAlignContext();
            readNum = 0;
            alignContext.readShortReadsWait.wakeOne();
        }
    }

    dropToAlignContext();
    readingFinishedWakeAll();
}