<commit_before>// Copyright (c) 2012-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "coins.h"

#include "random.h"

#include <assert.h>

/**
 * calculate number of bytes for the bitmask, and its number of non-zero bytes
 * each bit in the bitmask represents the availability of one output, but the
 * availabilities of the first two outputs are encoded separately
 */
void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
    unsigned int nLastUsedByte = 0;
    for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
        bool fZero = true;
        for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
            if (!vout[2+b*8+i].IsNull()) {
                fZero = false;
                continue;
            }
        }
        if (!fZero) {
            nLastUsedByte = b + 1;
            nNonzeroBytes++;
        }
    }
    nBytes += nLastUsedByte;
}

bool CCoins::Spend(const COutPoint &out, CTxInUndo &undo) {
    if (out.n >= vout.size())
        return false;
    if (vout[out.n].IsNull())
        return false;
    undo = CTxInUndo(vout[out.n]);
    vout[out.n].SetNull();
    Cleanup();
    if (vout.size() == 0) {
        undo.nHeight = nHeight;
        undo.fCoinBase = fCoinBase;
        undo.nVersion = this->nVersion;
    }
    return true;
}

bool CCoins::Spend(int nPos) {
    CTxInUndo undo;
    COutPoint out(0, nPos);
    return Spend(out, undo);
}

bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(0); }
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }

CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }

CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}

CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), hashBlock(0) { }

CCoinsViewCache::~CCoinsViewCache()
{
    assert(!hasModifier);
}

CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
    CCoinsMap::iterator it = cacheCoins.find(txid);
    if (it != cacheCoins.end())
        return it;
    CCoins tmp;
    if (!base->GetCoins(txid, tmp))
        return cacheCoins.end();
    CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
    tmp.swap(ret->second.coins);
    if (ret->second.coins.IsPruned()) {
        // The parent only has an empty entry for this txid; we can consider our
        // version as fresh.
        ret->second.flags = CCoinsCacheEntry::FRESH;
    }
    return ret;
}

bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
    CCoinsMap::const_iterator it = FetchCoins(txid);
    if (it != cacheCoins.end()) {
        coins = it->second.coins;
        return true;
    }
    return false;
}

CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
    assert(!hasModifier);
    std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
    if (ret.second) {
        if (!base->GetCoins(txid, ret.first->second.coins)) {
            // The parent view does not have this entry; mark it as fresh.
            ret.first->second.coins.Clear();
            ret.first->second.flags = CCoinsCacheEntry::FRESH;
        } else if (ret.first->second.coins.IsPruned()) {
            // The parent view only has a pruned entry for this; mark it as fresh.
            ret.first->second.flags = CCoinsCacheEntry::FRESH;
        }
    }
    // Assume that whenever ModifyCoins is called, the entry will be modified.
    ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
    return CCoinsModifier(*this, ret.first);
}

const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
    CCoinsMap::const_iterator it = FetchCoins(txid);
    if (it == cacheCoins.end()) {
        return NULL;
    } else {
        return &it->second.coins;
    }
}

bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
    CCoinsMap::const_iterator it = FetchCoins(txid);
    // We're using vtx.empty() instead of IsPruned here for performance reasons,
    // as we only care about the case where a transaction was replaced entirely
    // in a reorganization (which wipes vout entirely, as opposed to spending
    // which just cleans individual outputs).
    return (it != cacheCoins.end() && !it->second.coins.vout.empty());
}

uint256 CCoinsViewCache::GetBestBlock() const {
    if (hashBlock == uint256(0))
        hashBlock = base->GetBestBlock();
    return hashBlock;
}

void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
    hashBlock = hashBlockIn;
}

bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
    assert(!hasModifier);
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
        if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
            CCoinsMap::iterator itUs = cacheCoins.find(it->first);
            if (itUs == cacheCoins.end()) {
                if (!it->second.coins.IsPruned()) {
                    // The parent cache does not have an entry, while the child
                    // cache does have (a non-pruned) one. Move the data up, and
                    // mark it as fresh (if the grandparent did have it, we
                    // would have pulled it in at first GetCoins).
                    assert(it->second.flags & CCoinsCacheEntry::FRESH);
                    CCoinsCacheEntry& entry = cacheCoins[it->first];
                    entry.coins.swap(it->second.coins);
                    entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
                }
            } else {
                if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
                    // The grandparent does not have an entry, and the child is
                    // modified and being pruned. This means we can just delete
                    // it from the parent.
                    cacheCoins.erase(itUs);
                } else {
                    // A normal modification.
                    itUs->second.coins.swap(it->second.coins);
                    itUs->second.flags |= CCoinsCacheEntry::DIRTY;
                }
            }
        }
        CCoinsMap::iterator itOld = it++;
        mapCoins.erase(itOld);
    }
    hashBlock = hashBlockIn;
    return true;
}

bool CCoinsViewCache::Flush() {
    bool fOk = base->BatchWrite(cacheCoins, hashBlock);
    cacheCoins.clear();
    return fOk;
}

unsigned int CCoinsViewCache::GetCacheSize() const {
    return cacheCoins.size();
}

const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
{
    const CCoins* coins = AccessCoins(input.prevout.hash);
    assert(coins && coins->IsAvailable(input.prevout.n));
    return coins->vout[input.prevout.n];
}

CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
{
    if (tx.IsCoinBase())
        return 0;

    CAmount nResult = 0;
    for (unsigned int i = 0; i < tx.vin.size(); i++)
        nResult += GetOutputFor(tx.vin[i]).nValue;

    return nResult;
}

bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
{
    if (!tx.IsCoinBase()) {
        for (unsigned int i = 0; i < tx.vin.size(); i++) {
            const COutPoint &prevout = tx.vin[i].prevout;
            const CCoins* coins = AccessCoins(prevout.hash);
            if (!coins || !coins->IsAvailable(prevout.n)) {
                return false;
            }
        }
    }
    return true;
}

double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
{
    if (tx.IsCoinBase())
        return 0.0;
    double dResult = 0.0;
    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        const CCoins* coins = AccessCoins(txin.prevout.hash);
        assert(coins);
        if (!coins->IsAvailable(txin.prevout.n)) continue;
        if (coins->nHeight < nHeight) {
            dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
        }
    }
    return tx.ComputePriority(dResult);
}

CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_) : cache(cache_), it(it_) {
    assert(!cache.hasModifier);
    cache.hasModifier = true;
}

CCoinsModifier::~CCoinsModifier()
{
    assert(cache.hasModifier);
    cache.hasModifier = false;
    it->second.coins.Cleanup();
    if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
        cache.cacheCoins.erase(it);
    }
}
<commit_msg>Fix relaypriority calculation error Author: maiiz <maiiz@users.noreply.github.com> Github-Issue: https://github.com/litecoin-project/litecoin/issues/247 Rebased-From: 94a34a5d951cee59ef9c9274c5ad49ac2a91ab8a<commit_after>// Copyright (c) 2012-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "coins.h"

#include "random.h"

#include <assert.h>

/**
 * calculate number of bytes for the bitmask, and its number of non-zero bytes
 * each bit in the bitmask represents the availability of one output, but the
 * availabilities of the first two outputs are encoded separately
 */
void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
    unsigned int nLastUsedByte = 0;
    for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
        bool fZero = true;
        for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
            if (!vout[2+b*8+i].IsNull()) {
                fZero = false;
                continue;
            }
        }
        if (!fZero) {
            nLastUsedByte = b + 1;
            nNonzeroBytes++;
        }
    }
    nBytes += nLastUsedByte;
}

bool CCoins::Spend(const COutPoint &out, CTxInUndo &undo) {
    if (out.n >= vout.size())
        return false;
    if (vout[out.n].IsNull())
        return false;
    undo = CTxInUndo(vout[out.n]);
    vout[out.n].SetNull();
    Cleanup();
    if (vout.size() == 0) {
        undo.nHeight = nHeight;
        undo.fCoinBase = fCoinBase;
        undo.nVersion = this->nVersion;
    }
    return true;
}

bool CCoins::Spend(int nPos) {
    CTxInUndo undo;
    COutPoint out(0, nPos);
    return Spend(out, undo);
}

bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(0); }
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }

CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }

CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}

CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), hashBlock(0) { }

CCoinsViewCache::~CCoinsViewCache()
{
    assert(!hasModifier);
}

CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
    CCoinsMap::iterator it = cacheCoins.find(txid);
    if (it != cacheCoins.end())
        return it;
    CCoins tmp;
    if (!base->GetCoins(txid, tmp))
        return cacheCoins.end();
    CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
    tmp.swap(ret->second.coins);
    if (ret->second.coins.IsPruned()) {
        // The parent only has an empty entry for this txid; we can consider our
        // version as fresh.
        ret->second.flags = CCoinsCacheEntry::FRESH;
    }
    return ret;
}

bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
    CCoinsMap::const_iterator it = FetchCoins(txid);
    if (it != cacheCoins.end()) {
        coins = it->second.coins;
        return true;
    }
    return false;
}

CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
    assert(!hasModifier);
    std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
    if (ret.second) {
        if (!base->GetCoins(txid, ret.first->second.coins)) {
            // The parent view does not have this entry; mark it as fresh.
            ret.first->second.coins.Clear();
            ret.first->second.flags = CCoinsCacheEntry::FRESH;
        } else if (ret.first->second.coins.IsPruned()) {
            // The parent view only has a pruned entry for this; mark it as fresh.
            ret.first->second.flags = CCoinsCacheEntry::FRESH;
        }
    }
    // Assume that whenever ModifyCoins is called, the entry will be modified.
    ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
    return CCoinsModifier(*this, ret.first);
}

const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
    CCoinsMap::const_iterator it = FetchCoins(txid);
    if (it == cacheCoins.end()) {
        return NULL;
    } else {
        return &it->second.coins;
    }
}

bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
    CCoinsMap::const_iterator it = FetchCoins(txid);
    // We're using vtx.empty() instead of IsPruned here for performance reasons,
    // as we only care about the case where a transaction was replaced entirely
    // in a reorganization (which wipes vout entirely, as opposed to spending
    // which just cleans individual outputs).
    return (it != cacheCoins.end() && !it->second.coins.vout.empty());
}

uint256 CCoinsViewCache::GetBestBlock() const {
    if (hashBlock == uint256(0))
        hashBlock = base->GetBestBlock();
    return hashBlock;
}

void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
    hashBlock = hashBlockIn;
}

bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
    assert(!hasModifier);
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
        if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
            CCoinsMap::iterator itUs = cacheCoins.find(it->first);
            if (itUs == cacheCoins.end()) {
                if (!it->second.coins.IsPruned()) {
                    // The parent cache does not have an entry, while the child
                    // cache does have (a non-pruned) one. Move the data up, and
                    // mark it as fresh (if the grandparent did have it, we
                    // would have pulled it in at first GetCoins).
                    assert(it->second.flags & CCoinsCacheEntry::FRESH);
                    CCoinsCacheEntry& entry = cacheCoins[it->first];
                    entry.coins.swap(it->second.coins);
                    entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
                }
            } else {
                if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
                    // The grandparent does not have an entry, and the child is
                    // modified and being pruned. This means we can just delete
                    // it from the parent.
                    cacheCoins.erase(itUs);
                } else {
                    // A normal modification.
                    itUs->second.coins.swap(it->second.coins);
                    itUs->second.flags |= CCoinsCacheEntry::DIRTY;
                }
            }
        }
        CCoinsMap::iterator itOld = it++;
        mapCoins.erase(itOld);
    }
    hashBlock = hashBlockIn;
    return true;
}

bool CCoinsViewCache::Flush() {
    bool fOk = base->BatchWrite(cacheCoins, hashBlock);
    cacheCoins.clear();
    return fOk;
}

unsigned int CCoinsViewCache::GetCacheSize() const {
    return cacheCoins.size();
}

const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
{
    const CCoins* coins = AccessCoins(input.prevout.hash);
    assert(coins && coins->IsAvailable(input.prevout.n));
    return coins->vout[input.prevout.n];
}

CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
{
    if (tx.IsCoinBase())
        return 0;

    CAmount nResult = 0;
    for (unsigned int i = 0; i < tx.vin.size(); i++)
        nResult += GetOutputFor(tx.vin[i]).nValue;

    return nResult;
}

bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
{
    if (!tx.IsCoinBase()) {
        for (unsigned int i = 0; i < tx.vin.size(); i++) {
            const COutPoint &prevout = tx.vin[i].prevout;
            const CCoins* coins = AccessCoins(prevout.hash);
            if (!coins || !coins->IsAvailable(prevout.n)) {
                return false;
            }
        }
    }
    return true;
}

double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
{
    if (tx.IsCoinBase())
        return 0.0;
    double dResult = 0.0;
    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        const CCoins* coins = AccessCoins(txin.prevout.hash);
        assert(coins);
        if (!coins->IsAvailable(txin.prevout.n)) continue;
        if (coins->nHeight <= nHeight) {
            dResult += (double)(coins->vout[txin.prevout.n].nValue) * (nHeight-coins->nHeight);
        }
    }
    return tx.ComputePriority(dResult);
}

CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_) : cache(cache_), it(it_) {
    assert(!cache.hasModifier);
    cache.hasModifier = true;
}

CCoinsModifier::~CCoinsModifier()
{
    assert(cache.hasModifier);
    cache.hasModifier = false;
    it->second.coins.Cleanup();
    if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
        cache.cacheCoins.erase(it);
    }
}
<|endoftext|>


<commit_before>#include <QtWidgets>
#include "mainwindow.h"
#include <QKeyEvent>

Window::Window(QWidget *parent) : QWidget(parent)
{
    findButton = new QPushButton(tr("&Find"), this);
    connect(findButton, &QAbstractButton::clicked, this, &Window::find);
    textLabel = new QLabel(tr("Search:"));
    searchBox = new SearchBox();

    createFilesTable();

    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(textLabel, 0, 0);
    mainLayout->addWidget(searchBox, 0, 1, 1, 1);
    mainLayout ->addWidget(findButton, 0, 3);
    mainLayout->addWidget(filesTable, 1, 0, 1, 4);
    setLayout(mainLayout);

    setWindowTitle(tr("Find Recipes"));
    resize(500, 300);
}

void Window::find()
{
    filesTable->setRowCount(0);

    QString text = searchBox->text();

    currentDir = QDir(".");
    QStringList files;
    QString fileName = "*";
    files = currentDir.entryList(QStringList(fileName),
                                 QDir::Files | QDir::NoSymLinks);

    if (!text.isEmpty())
        files = findFiles(files, text);
    showFiles(files);
}

QStringList Window::findFiles(const QStringList &files, const QString &text)
{
    QProgressDialog progressDialog(this);
    progressDialog.setCancelButtonText(tr("&Cancel"));
    progressDialog.setRange(0, files.size());
    progressDialog.setWindowTitle(tr("Find Files"));

    QStringList foundFiles;

    for (int i = 0; i < files.size(); ++i) {
        progressDialog.setValue(i);
        progressDialog.setLabelText(tr("Searching file number %1 of %2...")
                                    .arg(i).arg(files.size()));
        qApp->processEvents();

        if (progressDialog.wasCanceled())
            break;

        QFile file(currentDir.absoluteFilePath(files[i]));

        if (file.open(QIODevice::ReadOnly)) {
            QString line;
            QTextStream in(&file);
            while (!in.atEnd()) {
                if (progressDialog.wasCanceled())
                    break;
                line = in.readLine();
                if (line.contains(text)) {
                    foundFiles << files[i];
                    break;
                }
            }
        }
    }
    return foundFiles;
}

void Window::showFiles(const QStringList &files)
{
    for (int i = 0; i < files.size(); ++i) {
        QFile file(currentDir.absoluteFilePath(files[i]));
        qint64 size = QFileInfo(file).size();

        QTableWidgetItem *fileNameItem = new QTableWidgetItem(files[i]);
        fileNameItem->setFlags(fileNameItem->flags() ^ Qt::ItemIsEditable);
        QTableWidgetItem *sizeItem = new QTableWidgetItem(tr("%1 KB")
                                             .arg(int((size + 1023) / 1024)));
        sizeItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
        sizeItem->setFlags(sizeItem->flags() ^ Qt::ItemIsEditable);

        int row = filesTable->rowCount();
        filesTable->insertRow(row);
        filesTable->setItem(row, 0, fileNameItem);
        filesTable->setItem(row, 1, sizeItem);
    }
}

void Window::createFilesTable()
{
    filesTable = new QTableWidget(0, 2);
    filesTable->setSelectionBehavior(QAbstractItemView::SelectRows);

    QStringList labels;
    labels << tr("Filename") << tr("Size");
    filesTable->setHorizontalHeaderLabels(labels);
    filesTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
    filesTable->verticalHeader()->hide();
    filesTable->setShowGrid(false);

    connect(filesTable, &QTableWidget::cellActivated,
            this, &Window::openFileOfItem);
}

void Window::openFileOfItem(int row, int /* column */)
{
    QTableWidgetItem *item = filesTable->item(row, 0);

    QDesktopServices::openUrl(QUrl::fromLocalFile(currentDir.absoluteFilePath(item->text())));
}
<commit_msg>Add function to get all files in subdirectories and modify 'find' usage to use new function<commit_after>#include <QtWidgets>
#include "mainwindow.h"
#include <QKeyEvent>
#include <QDebug>

#include <fts_fuzzy_match.h>
#include <glob.h>
#include <string>

Window::Window(QWidget *parent) : QWidget(parent)
{
    findButton = new QPushButton(tr("&Find"), this);
    connect(findButton, &QAbstractButton::clicked, this, &Window::find);
    textLabel = new QLabel(tr("Search:"));
    searchBox = new SearchBox();

    createFilesTable();

    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(textLabel, 0, 0);
    mainLayout->addWidget(searchBox, 0, 1, 1, 1);
    mainLayout ->addWidget(findButton, 0, 3);
    mainLayout->addWidget(filesTable, 1, 0, 1, 4);
    setLayout(mainLayout);

    setWindowTitle(tr("Find Recipes"));
    resize(500, 300);
}

// Get list of files according to glob patternn
QStringList globVector(const std::string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    QStringList files;
    for(unsigned int i=0; i<glob_result.gl_pathc; ++i){
        files << QString(glob_result.gl_pathv[i]);
    }
    globfree(&glob_result);
    return files;
}

void Window::find()
{
    filesTable->setRowCount(0);

    QStringList files = globVector("*/*.md");
    QString text = searchBox->text();
    if(!text.isEmpty()){
        files = findFiles(files, text);
    }
    showFiles(files);
}

/*
void Window::find()
{
    filesTable->setRowCount(0);

    QString text = searchBox->text();

    currentDir = QDir(".");
    QStringList files;
    QString fileName = "*";
    files = currentDir.entryList(QStringList(fileName),
                                 QDir::Files | QDir::NoSymLinks);

    if (!text.isEmpty())
        files = findFiles(files, text);
    showFiles(files);
}
*/

QStringList Window::findFiles(const QStringList &files, const QString &text)
{
    QProgressDialog progressDialog(this);
    progressDialog.setCancelButtonText(tr("&Cancel"));
    progressDialog.setRange(0, files.size());
    progressDialog.setWindowTitle(tr("Find Files"));

    QStringList foundFiles;

    for (int i = 0; i < files.size(); ++i) {
        progressDialog.setValue(i);
        progressDialog.setLabelText(tr("Searching file number %1 of %2...")
                                    .arg(i).arg(files.size()));
        qApp->processEvents();

        if (progressDialog.wasCanceled())
            break;

        QFile file(currentDir.absoluteFilePath(files[i]));

        if (file.open(QIODevice::ReadOnly)) {
            QString line;
            QTextStream in(&file);
            while (!in.atEnd()) {
                if (progressDialog.wasCanceled())
                    break;
                line = in.readLine();
                if (line.contains(text)) {
                    foundFiles << files[i];
                    break;
                }
            }
        }
    }
    return foundFiles;
}

void Window::showFiles(const QStringList &files)
{
    for (int i = 0; i < files.size(); ++i) {
        QFile file(currentDir.absoluteFilePath(files[i]));
        qint64 size = QFileInfo(file).size();

        QTableWidgetItem *fileNameItem = new QTableWidgetItem(files[i]);
        fileNameItem->setFlags(fileNameItem->flags() ^ Qt::ItemIsEditable);
        QTableWidgetItem *sizeItem = new QTableWidgetItem(tr("%1 KB")
                                             .arg(int((size + 1023) / 1024)));
        sizeItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
        sizeItem->setFlags(sizeItem->flags() ^ Qt::ItemIsEditable);

        int row = filesTable->rowCount();
        filesTable->insertRow(row);
        filesTable->setItem(row, 0, fileNameItem);
        filesTable->setItem(row, 1, sizeItem);
    }
}

void Window::createFilesTable()
{
    filesTable = new QTableWidget(0, 2);
    filesTable->setSelectionBehavior(QAbstractItemView::SelectRows);

    QStringList labels;
    labels << tr("Filename") << tr("Size");
    filesTable->setHorizontalHeaderLabels(labels);
    filesTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
    filesTable->verticalHeader()->hide();
    filesTable->setShowGrid(false);

    connect(filesTable, &QTableWidget::cellActivated,
            this, &Window::openFileOfItem);
}

void Window::openFileOfItem(int row, int /* column */)
{
    QTableWidgetItem *item = filesTable->item(row, 0);

    QDesktopServices::openUrl(QUrl::fromLocalFile(currentDir.absoluteFilePath(item->text())));
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "model.h"
#include "model_io.h"
#include "figurepainter.h"
#include "build_info.h"
#include <sstream>
#include <fstream>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QShortcut>
#include <QScreen>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    modelWidget(nullptr),
    redoExtraShortcut(QKeySequence("Ctrl+Shift+Z"), this),
    zoomInExtraShortcut(QKeySequence("Ctrl+="), this)
{
    ui->setupUi(this);
    connect(&redoExtraShortcut  , &QShortcut::activated, ui->actionRedo  , &QAction::trigger);
    connect(&zoomInExtraShortcut, &QShortcut::activated, ui->actionZoomIn, &QAction::trigger);
    setModelWidget(new Ui::ModelWidget());
    setWindowIcon(QIcon(":/icon.ico"));
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::on_actionNew_triggered() {
    setModelWidget(new Ui::ModelWidget());
    currentFileName = QString();
}

void MainWindow::setModelWidget(Ui::ModelWidget *newWidget) {
    if (this->modelWidget) {
        ui->wrapperFrame->layout()->removeWidget(this->modelWidget);
        delete this->modelWidget;
    }

    this->modelWidget = newWidget;
    ui->wrapperFrame->layout()->addWidget(this->modelWidget);
    ui->actionSaveAs->setEnabled(true);
    ui->actionUndo->setEnabled(modelWidget->canUndo());
    connect(modelWidget, &Ui::ModelWidget::canUndoChanged, [this]() {
        ui->actionUndo->setEnabled(modelWidget->canUndo());
    });
    ui->actionRedo->setEnabled(modelWidget->canRedo());
    connect(modelWidget, &Ui::ModelWidget::canRedoChanged, [this]() {
        ui->actionRedo->setEnabled(modelWidget->canRedo());
    });
    connect(modelWidget, &Ui::ModelWidget::scaleFactorChanged, [this]() {
        ui->actionZoomOut->setEnabled(modelWidget->scaleFactor() > SCALE_FACTOR_STEP + 1e-8);
    });
    modelWidget->setGridStep(ui->actionShowGrid->isChecked() ? defaultGridStep : 0);

    QScreen *screen = QApplication::screens().at(0);
    modelWidget->setScaleFactor(screen->logicalDotsPerInch() / 96.0);
}

void MainWindow::on_actionOpen_triggered() {
    QString filename = QFileDialog::getOpenFileName(
                           this,
                           "Select file with a model",
                           QDir::currentPath(),
                           "Models (*.model)"
                       );
    if (filename == "") {
        return;
    }

    std::unique_ptr<Ui::ModelWidget> modelWidget(new Ui::ModelWidget());
    QFile file(filename);
    if (!file.open(QFile::ReadOnly)) {
        QMessageBox::critical(this, "Error while opening model", "Unable to open file for reading");
        return;
    }
    std::stringstream data;
    data << file.readAll().toStdString();
    file.close();
    try {
        Model model;
        data >> model;
        modelWidget->setModel(std::move(model));
    } catch (model_format_error &e) {
        QMessageBox::critical(this, "Error while opening model", e.what());
        return;
    }

    setModelWidget(modelWidget.release());
    currentFileName = filename;
}

void MainWindow::on_actionSave_triggered() {
    if (currentFileName == QString()) {
        ui->actionSaveAs->trigger();
        return;
    }
    Model &model = this->modelWidget->getModel();
    std::ofstream file(currentFileName.toStdString());
    file << model;
}

QString forceFileExtension(QString filename, QString selectedFilter) {
    QString extension = selectedFilter.mid(selectedFilter.indexOf("(*.") + 3);
    extension.chop(1); // chop trailing )
    extension = ("." + extension).toLower();
    if (!filename.endsWith(extension)) {
        filename += extension;
    }
    return filename;
}

void MainWindow::on_actionSaveAs_triggered() {
    QString selectedFilter;
    QString filename = QFileDialog::getSaveFileName(
                           this,
                           "Select file to save in",
                           QDir::currentPath(),
                           "Models (*.model);;SVG (*.svg);;PNG (*.png)",
                           &selectedFilter
                       );
    if (filename == "") {
        return;
    }
    filename = forceFileExtension(filename, selectedFilter);
    Model &model = this->modelWidget->getModel();
    std::ofstream file(filename.toStdString());
    if (filename.toLower().endsWith(".svg")) {
        exportModelToSvg(model, file);
    } else if (filename.toLower().endsWith(".png")) {
        file.close();
        exportModelToImageFile(model, filename);
    } else {
        file << model;
        currentFileName = filename;
    }
}

void MainWindow::on_actionUndo_triggered() {
    // Extra check is added for symmetry with actionRedo
    if (!modelWidget->canUndo()) { return; }
    modelWidget->undo();
}

void MainWindow::on_actionRedo_triggered() {
    // Extra check is added because there is extra shortcut
    if (!modelWidget->canRedo()) { return; }
    modelWidget->redo();
}

void MainWindow::on_actionShowGrid_triggered() {
    if (ui->actionShowGrid->isChecked()) {
        defaultGridStep = QInputDialog::getInt(this, "Grid step", "Specify grid step in pixels", defaultGridStep, 1, int(1e9));
    }
    modelWidget->setGridStep(ui->actionShowGrid->isChecked() ? defaultGridStep : 0);
}

void MainWindow::on_actionZoomIn_triggered() {
    modelWidget->setScaleFactor(modelWidget->scaleFactor() + SCALE_FACTOR_STEP);
}

void MainWindow::on_actionZoomOut_triggered() {
    modelWidget->setScaleFactor(modelWidget->scaleFactor() - SCALE_FACTOR_STEP);
}

void MainWindow::on_actionExit_triggered() {
    QApplication::exit();
}

void MainWindow::on_actionAbout_triggered() {
    QMessageBox::about(this, "About Manugram",
                       QString()
                       + "Git commit hash: " + GIT_LAST_SHA1 + "\n"
                       + "Git commit date: " + GIT_LAST_TIME + "\n"
                       + "Build time: " + BUILD_TIME
                       );
}
<commit_msg>mainwindow: saving is now performed via stringstream and QFile (#45)<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "model.h"
#include "model_io.h"
#include "figurepainter.h"
#include "build_info.h"
#include <sstream>
#include <QByteArray>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QShortcut>
#include <QScreen>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    modelWidget(nullptr),
    redoExtraShortcut(QKeySequence("Ctrl+Shift+Z"), this),
    zoomInExtraShortcut(QKeySequence("Ctrl+="), this)
{
    ui->setupUi(this);
    connect(&redoExtraShortcut  , &QShortcut::activated, ui->actionRedo  , &QAction::trigger);
    connect(&zoomInExtraShortcut, &QShortcut::activated, ui->actionZoomIn, &QAction::trigger);
    setModelWidget(new Ui::ModelWidget());
    setWindowIcon(QIcon(":/icon.ico"));
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::on_actionNew_triggered() {
    setModelWidget(new Ui::ModelWidget());
    currentFileName = QString();
}

void MainWindow::setModelWidget(Ui::ModelWidget *newWidget) {
    if (this->modelWidget) {
        ui->wrapperFrame->layout()->removeWidget(this->modelWidget);
        delete this->modelWidget;
    }

    this->modelWidget = newWidget;
    ui->wrapperFrame->layout()->addWidget(this->modelWidget);
    ui->actionSaveAs->setEnabled(true);
    ui->actionUndo->setEnabled(modelWidget->canUndo());
    connect(modelWidget, &Ui::ModelWidget::canUndoChanged, [this]() {
        ui->actionUndo->setEnabled(modelWidget->canUndo());
    });
    ui->actionRedo->setEnabled(modelWidget->canRedo());
    connect(modelWidget, &Ui::ModelWidget::canRedoChanged, [this]() {
        ui->actionRedo->setEnabled(modelWidget->canRedo());
    });
    connect(modelWidget, &Ui::ModelWidget::scaleFactorChanged, [this]() {
        ui->actionZoomOut->setEnabled(modelWidget->scaleFactor() > SCALE_FACTOR_STEP + 1e-8);
    });
    modelWidget->setGridStep(ui->actionShowGrid->isChecked() ? defaultGridStep : 0);

    QScreen *screen = QApplication::screens().at(0);
    modelWidget->setScaleFactor(screen->logicalDotsPerInch() / 96.0);
}

void MainWindow::on_actionOpen_triggered() {
    QString filename = QFileDialog::getOpenFileName(
                           this,
                           "Select file with a model",
                           QDir::currentPath(),
                           "Models (*.model)"
                       );
    if (filename == "") {
        return;
    }

    std::unique_ptr<Ui::ModelWidget> modelWidget(new Ui::ModelWidget());
    QFile file(filename);
    if (!file.open(QFile::ReadOnly)) {
        QMessageBox::critical(this, "Error while opening model", "Unable to open file for reading");
        return;
    }
    std::stringstream data;
    data << file.readAll().toStdString();
    file.close();
    try {
        Model model;
        data >> model;
        modelWidget->setModel(std::move(model));
    } catch (model_format_error &e) {
        QMessageBox::critical(this, "Error while opening model", e.what());
        return;
    }

    setModelWidget(modelWidget.release());
    currentFileName = filename;
}

bool saveDataToFile(const std::string &data, QString &fileName) {
    QFile file(fileName);
    if (!file.open(QFile::WriteOnly)) {
        return false;
    }
    QByteArray buffer(data.data(), data.length());
    return file.write(buffer) == buffer.size();
}

void MainWindow::on_actionSave_triggered() {
    if (currentFileName == QString()) {
        ui->actionSaveAs->trigger();
        return;
    }
    std::stringstream data;
    data << this->modelWidget->getModel();
    if (!saveDataToFile(data.str(), currentFileName)) {
        QMessageBox::critical(this, "Error", "Unable to save model");
    }
}

QString forceFileExtension(QString filename, QString selectedFilter) {
    QString extension = selectedFilter.mid(selectedFilter.indexOf("(*.") + 3);
    extension.chop(1); // chop trailing )
    extension = ("." + extension).toLower();
    if (!filename.endsWith(extension)) {
        filename += extension;
    }
    return filename;
}

void MainWindow::on_actionSaveAs_triggered() {
    QString selectedFilter;
    QString filename = QFileDialog::getSaveFileName(
                           this,
                           "Select file to save in",
                           QDir::currentPath(),
                           "Models (*.model);;SVG (*.svg);;PNG (*.png)",
                           &selectedFilter
                       );
    if (filename == "") {
        return;
    }
    filename = forceFileExtension(filename, selectedFilter);
    Model &model = this->modelWidget->getModel();
    if (filename.toLower().endsWith(".svg")) {
        std::stringstream data;
        exportModelToSvg(model, data);
        if (!saveDataToFile(data.str(), filename)) {
            QMessageBox::critical(this, "Error", "Unable to save model to SVG");
        }
    } else if (filename.toLower().endsWith(".png")) {
        exportModelToImageFile(model, filename);
    } else {
        std::stringstream data;
        data << model;
        if (!saveDataToFile(data.str(), currentFileName)) {
            QMessageBox::critical(this, "Error", "Unable to save model");
        }
        currentFileName = filename;
    }
}

void MainWindow::on_actionUndo_triggered() {
    // Extra check is added for symmetry with actionRedo
    if (!modelWidget->canUndo()) { return; }
    modelWidget->undo();
}

void MainWindow::on_actionRedo_triggered() {
    // Extra check is added because there is extra shortcut
    if (!modelWidget->canRedo()) { return; }
    modelWidget->redo();
}

void MainWindow::on_actionShowGrid_triggered() {
    if (ui->actionShowGrid->isChecked()) {
        defaultGridStep = QInputDialog::getInt(this, "Grid step", "Specify grid step in pixels", defaultGridStep, 1, int(1e9));
    }
    modelWidget->setGridStep(ui->actionShowGrid->isChecked() ? defaultGridStep : 0);
}

void MainWindow::on_actionZoomIn_triggered() {
    modelWidget->setScaleFactor(modelWidget->scaleFactor() + SCALE_FACTOR_STEP);
}

void MainWindow::on_actionZoomOut_triggered() {
    modelWidget->setScaleFactor(modelWidget->scaleFactor() - SCALE_FACTOR_STEP);
}

void MainWindow::on_actionExit_triggered() {
    QApplication::exit();
}

void MainWindow::on_actionAbout_triggered() {
    QMessageBox::about(this, "About Manugram",
                       QString()
                       + "Git commit hash: " + GIT_LAST_SHA1 + "\n"
                       + "Git commit date: " + GIT_LAST_TIME + "\n"
                       + "Build time: " + BUILD_TIME
                       );
}
<|endoftext|>


<commit_before>#include <QFileDialog>
#include <QImageReader>
#include <QLabel>
#include <QMessageBox>
#include <QTimer>

#include "canvaswidget.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget* parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  setAttribute(Qt::WA_QuitOnClose);
  setWindowState(windowState() | Qt::WindowMaximized);
  setWindowTitle(appName());

  QActionGroup* modeActionGroup = new QActionGroup(this);
  toggleEtalonModeAction            = new QAction(QIcon(":/pictures/etalon.png"),                 QString::fromUtf8("Включить/выключить режим задания эталона"),  this);
  measureSegmentLengthAction        = new QAction(QIcon(":/pictures/segment_length.png"),         QString::fromUtf8("Измерение длин отрезков"),                   modeActionGroup);
  measurePolylineLengthAction       = new QAction(QIcon(":/pictures/polyline_length.png"),        QString::fromUtf8("Измерение длин кривых"),                     modeActionGroup);
  measureClosedPolylineLengthAction = new QAction(QIcon(":/pictures/closed_polyline_length.png"), QString::fromUtf8("Измерение длин замкнутых кривых"),           modeActionGroup);
  measureRectangleAreaAction        = new QAction(QIcon(":/pictures/rectangle_area.png"),         QString::fromUtf8("Измерение площадей прямоугольников"),        modeActionGroup);
  measurePolygonAreaAction          = new QAction(QIcon(":/pictures/polygon_area.png"),           QString::fromUtf8("Измерение площадей многоугольников"),        modeActionGroup);
  toggleRulerAction                 = new QAction(QIcon(":/pictures/toggle_ruler.png"),           QString::fromUtf8("Показать/скрыть масштабную линейку"),        this);
  aboutAction                       = new QAction(QIcon(":/pictures/about.png"),                  QString::fromUtf8("О программе"),                               this);
  toggleEtalonModeAction->setCheckable(true);
  toggleEtalonModeAction->setChecked(true);
  foreach (QAction* action, modeActionGroup->actions())
    action->setCheckable(true);
  measureSegmentLengthAction->setChecked(true);
  toggleRulerAction->setCheckable(true);
  toggleRulerAction->setChecked(true);
  ui->mainToolBar->addAction(toggleEtalonModeAction);
  ui->mainToolBar->addSeparator();
  ui->mainToolBar->addActions(modeActionGroup->actions());
  ui->mainToolBar->addSeparator();
  ui->mainToolBar->addAction(toggleRulerAction);
  ui->mainToolBar->addSeparator();
  ui->mainToolBar->addAction(aboutAction);
  ui->mainToolBar->setIconSize(QSize(32, 32));
  ui->mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu);

  QList<QByteArray> supportedFormatsList__ = QImageReader::supportedImageFormats();
  QSet<QString> supportedFormatsSet;
  foreach (const QByteArray& format, supportedFormatsList__)
    supportedFormatsSet.insert(QString(format).toLower());
  QStringList supportedFormatsList(supportedFormatsSet.toList());
  qSort(supportedFormatsList);
  QString allFormatsString;
  QStringList singleFormatsList;
  foreach (const QString& lowerFormat, supportedFormatsList) {
    QString upperFormat = lowerFormat.toUpper();
    allFormatsString += QString("*.%1 ").arg(lowerFormat);
    if (upperFormat == "JPEG")
      singleFormatsList += QString::fromUtf8("Изображения JPEG (*.jpeg *.jpg)").arg(upperFormat);
    else if (upperFormat != "JPG")
      singleFormatsList += QString::fromUtf8("Изображения %1 (*.%2)").arg(upperFormat).arg(lowerFormat);
  }
  allFormatsString = allFormatsString.trimmed();
  QString formatsList = QString::fromUtf8("Все изображения (%1);;").arg(allFormatsString) + singleFormatsList.join(";;");

  QString imageFile = QFileDialog::getOpenFileName (this, QString::fromUtf8("Укажите путь к изображению — ") + appName(),
                                                    QString(), formatsList, 0);
  if (imageFile.isEmpty()) {
    QTimer::singleShot(0, this, SLOT(close()));
    return;
  }

  QPixmap* image = new QPixmap;
  if (!image->load(imageFile)) {
    QMessageBox::warning(this, appName(), QString::fromUtf8("Не могу открыть изображение \"%1\".").arg(imageFile));
    delete image;
    QTimer::singleShot(0, this, SLOT(close()));
    return;
  }

  QFont statusBarFont = ui->statusBar->font();
  int newSize = QFontInfo(statusBarFont).pointSize() * 1.5;  // In contrast to ``labelFont.pointSize()'' it always works
  statusBarFont.setPointSize(newSize);
  ui->statusBar->setFont(statusBarFont);
  QLabel* scaleLabel  = new QLabel(this);
  QLabel* statusLabel = new QLabel(this);
  ui->statusBar->addPermanentWidget(scaleLabel);
  ui->statusBar->addWidget(statusLabel);

  canvasWidget = new CanvasWidget(image, this, ui->containingScrollArea, scaleLabel, statusLabel, this);
  ui->containingScrollArea->setBackgroundRole(QPalette::Dark);
  ui->containingScrollArea->setWidget(canvasWidget);

  connect(toggleEtalonModeAction, SIGNAL(toggled(bool)),       this,         SLOT(toggleEtalonDefinition(bool)));
  connect(modeActionGroup,        SIGNAL(triggered(QAction*)), this,         SLOT(updateMode(QAction*)));
  connect(toggleRulerAction,      SIGNAL(toggled(bool)),       canvasWidget, SLOT(toggleRuler(bool)));
  connect(aboutAction,            SIGNAL(triggered()),         this,         SLOT(showAbout()));
  canvasWidget->toggleRuler(toggleRulerAction->isChecked());
}

MainWindow::~MainWindow()
{
  delete ui;
}

QString MainWindow::appName() const
{
  return "AreaMeasurement";
}

QList<int> MainWindow::appVersion() const
{
  // TODO: Don't forget to increment it!
  return QList<int>() << 0 << 4;
}

QString MainWindow::appVersionString() const
{
  QString versionString;
  foreach (int x, appVersion())
    versionString += QString::number(x) + '.';
  return versionString.left(versionString.length() - 1);
}

void MainWindow::setMode(Mode newMode)
{
  canvasWidget->setMode(newMode);
}

void MainWindow::updateMode(QAction* modeAction)
{
  if (modeAction == measureSegmentLengthAction)
    return setMode(MEASURE_SEGMENT_LENGTH);
  if (modeAction == measurePolylineLengthAction)
    return setMode(MEASURE_POLYLINE_LENGTH);
  if (modeAction == measureClosedPolylineLengthAction)
    return setMode(MEASURE_CLOSED_POLYLINE_LENGTH);
  if (modeAction == measureRectangleAreaAction)
    return setMode(MEASURE_RECTANGLE_AREA);
  if (modeAction == measurePolygonAreaAction)
    return setMode(MEASURE_POLYGON_AREA);
  abort();
}

void MainWindow::toggleEtalonDefinition(bool isDefiningEtalon)
{
  if (canvasWidget->isEtalonCorrect()) {
    toggleEtalonModeAction->setChecked(isDefiningEtalon);
    canvasWidget->toggleEtalonDefinition(isDefiningEtalon);
  }
  else
    toggleEtalonModeAction->setChecked(true);
}

void MainWindow::showAbout()
{
  QString aboutText = QString::fromUtf8("Программа %1, версия %2.\n\n"
                                        "Приложение предназначено для измерения длин и площадей объектов на чертежах, картах и т.д.\n\n"
                                        "Автор — Матвеякин Андрей.\n\n"
                                        "Программа распространяется бесплатно по принципу «как есть»: автор не несёт ответственности за возможный ущерб, нанесённый в результате работы приложения."
                                        ).arg(appName()).arg(appVersionString());
  QMessageBox::about(this, QString::fromUtf8("О программе %1").arg(appName()), aboutText);
}
<commit_msg>Remove line accidentaly copypasted from Qt help<commit_after>#include <QFileDialog>
#include <QImageReader>
#include <QLabel>
#include <QMessageBox>
#include <QTimer>

#include "canvaswidget.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget* parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  setAttribute(Qt::WA_QuitOnClose);
  setWindowState(windowState() | Qt::WindowMaximized);
  setWindowTitle(appName());

  QActionGroup* modeActionGroup = new QActionGroup(this);
  toggleEtalonModeAction            = new QAction(QIcon(":/pictures/etalon.png"),                 QString::fromUtf8("Включить/выключить режим задания эталона"),  this);
  measureSegmentLengthAction        = new QAction(QIcon(":/pictures/segment_length.png"),         QString::fromUtf8("Измерение длин отрезков"),                   modeActionGroup);
  measurePolylineLengthAction       = new QAction(QIcon(":/pictures/polyline_length.png"),        QString::fromUtf8("Измерение длин кривых"),                     modeActionGroup);
  measureClosedPolylineLengthAction = new QAction(QIcon(":/pictures/closed_polyline_length.png"), QString::fromUtf8("Измерение длин замкнутых кривых"),           modeActionGroup);
  measureRectangleAreaAction        = new QAction(QIcon(":/pictures/rectangle_area.png"),         QString::fromUtf8("Измерение площадей прямоугольников"),        modeActionGroup);
  measurePolygonAreaAction          = new QAction(QIcon(":/pictures/polygon_area.png"),           QString::fromUtf8("Измерение площадей многоугольников"),        modeActionGroup);
  toggleRulerAction                 = new QAction(QIcon(":/pictures/toggle_ruler.png"),           QString::fromUtf8("Показать/скрыть масштабную линейку"),        this);
  aboutAction                       = new QAction(QIcon(":/pictures/about.png"),                  QString::fromUtf8("О программе"),                               this);
  toggleEtalonModeAction->setCheckable(true);
  toggleEtalonModeAction->setChecked(true);
  foreach (QAction* action, modeActionGroup->actions())
    action->setCheckable(true);
  measureSegmentLengthAction->setChecked(true);
  toggleRulerAction->setCheckable(true);
  toggleRulerAction->setChecked(true);
  ui->mainToolBar->addAction(toggleEtalonModeAction);
  ui->mainToolBar->addSeparator();
  ui->mainToolBar->addActions(modeActionGroup->actions());
  ui->mainToolBar->addSeparator();
  ui->mainToolBar->addAction(toggleRulerAction);
  ui->mainToolBar->addSeparator();
  ui->mainToolBar->addAction(aboutAction);
  ui->mainToolBar->setIconSize(QSize(32, 32));
  ui->mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu);

  QList<QByteArray> supportedFormatsList__ = QImageReader::supportedImageFormats();
  QSet<QString> supportedFormatsSet;
  foreach (const QByteArray& format, supportedFormatsList__)
    supportedFormatsSet.insert(QString(format).toLower());
  QStringList supportedFormatsList(supportedFormatsSet.toList());
  qSort(supportedFormatsList);
  QString allFormatsString;
  QStringList singleFormatsList;
  foreach (const QString& lowerFormat, supportedFormatsList) {
    QString upperFormat = lowerFormat.toUpper();
    allFormatsString += QString("*.%1 ").arg(lowerFormat);
    if (upperFormat == "JPEG")
      singleFormatsList += QString::fromUtf8("Изображения JPEG (*.jpeg *.jpg)").arg(upperFormat);
    else if (upperFormat != "JPG")
      singleFormatsList += QString::fromUtf8("Изображения %1 (*.%2)").arg(upperFormat).arg(lowerFormat);
  }
  allFormatsString = allFormatsString.trimmed();
  QString formatsList = QString::fromUtf8("Все изображения (%1);;").arg(allFormatsString) + singleFormatsList.join(";;");

  QString imageFile = QFileDialog::getOpenFileName (this, QString::fromUtf8("Укажите путь к изображению — ") + appName(),
                                                    QString(), formatsList, 0);
  if (imageFile.isEmpty()) {
    QTimer::singleShot(0, this, SLOT(close()));
    return;
  }

  QPixmap* image = new QPixmap;
  if (!image->load(imageFile)) {
    QMessageBox::warning(this, appName(), QString::fromUtf8("Не могу открыть изображение \"%1\".").arg(imageFile));
    delete image;
    QTimer::singleShot(0, this, SLOT(close()));
    return;
  }

  QFont statusBarFont = ui->statusBar->font();
  int newSize = QFontInfo(statusBarFont).pointSize() * 1.5;  // In contrast to ``labelFont.pointSize()'' it always works
  statusBarFont.setPointSize(newSize);
  ui->statusBar->setFont(statusBarFont);
  QLabel* scaleLabel  = new QLabel(this);
  QLabel* statusLabel = new QLabel(this);
  ui->statusBar->addPermanentWidget(scaleLabel);
  ui->statusBar->addWidget(statusLabel);

  canvasWidget = new CanvasWidget(image, this, ui->containingScrollArea, scaleLabel, statusLabel, this);
  ui->containingScrollArea->setWidget(canvasWidget);

  connect(toggleEtalonModeAction, SIGNAL(toggled(bool)),       this,         SLOT(toggleEtalonDefinition(bool)));
  connect(modeActionGroup,        SIGNAL(triggered(QAction*)), this,         SLOT(updateMode(QAction*)));
  connect(toggleRulerAction,      SIGNAL(toggled(bool)),       canvasWidget, SLOT(toggleRuler(bool)));
  connect(aboutAction,            SIGNAL(triggered()),         this,         SLOT(showAbout()));
  canvasWidget->toggleRuler(toggleRulerAction->isChecked());
}

MainWindow::~MainWindow()
{
  delete ui;
}

QString MainWindow::appName() const
{
  return "AreaMeasurement";
}

QList<int> MainWindow::appVersion() const
{
  // TODO: Don't forget to increment it!
  return QList<int>() << 0 << 4;
}

QString MainWindow::appVersionString() const
{
  QString versionString;
  foreach (int x, appVersion())
    versionString += QString::number(x) + '.';
  return versionString.left(versionString.length() - 1);
}

void MainWindow::setMode(Mode newMode)
{
  canvasWidget->setMode(newMode);
}

void MainWindow::updateMode(QAction* modeAction)
{
  if (modeAction == measureSegmentLengthAction)
    return setMode(MEASURE_SEGMENT_LENGTH);
  if (modeAction == measurePolylineLengthAction)
    return setMode(MEASURE_POLYLINE_LENGTH);
  if (modeAction == measureClosedPolylineLengthAction)
    return setMode(MEASURE_CLOSED_POLYLINE_LENGTH);
  if (modeAction == measureRectangleAreaAction)
    return setMode(MEASURE_RECTANGLE_AREA);
  if (modeAction == measurePolygonAreaAction)
    return setMode(MEASURE_POLYGON_AREA);
  abort();
}

void MainWindow::toggleEtalonDefinition(bool isDefiningEtalon)
{
  if (canvasWidget->isEtalonCorrect()) {
    toggleEtalonModeAction->setChecked(isDefiningEtalon);
    canvasWidget->toggleEtalonDefinition(isDefiningEtalon);
  }
  else
    toggleEtalonModeAction->setChecked(true);
}

void MainWindow::showAbout()
{
  QString aboutText = QString::fromUtf8("Программа %1, версия %2.\n\n"
                                        "Приложение предназначено для измерения длин и площадей объектов на чертежах, картах и т.д.\n\n"
                                        "Автор — Матвеякин Андрей.\n\n"
                                        "Программа распространяется бесплатно по принципу «как есть»: автор не несёт ответственности за возможный ущерб, нанесённый в результате работы приложения."
                                        ).arg(appName()).arg(appVersionString());
  QMessageBox::about(this, QString::fromUtf8("О программе %1").arg(appName()), aboutText);
}
<|endoftext|>


<commit_before>#include "d3d12.h"

inline ID3D12Resource *d3d_create_buffer(ID3D12Device *d3d, D3D12_HEAP_TYPE heap_type, u64 size)
{
    assert(heap_type != D3D12_HEAP_TYPE_CUSTOM);

    D3D12_HEAP_PROPERTIES heap_props = { .Type = heap_type };
    D3D12_RESOURCE_DESC buffer_desc = {
        .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
        .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
        .Width = size,
        .Height = 1,
        .DepthOrArraySize = 1,
        .MipLevels = 1,
        .SampleDesc.Count = 1
    };
    D3D12_RESOURCE_STATES state =
        (heap_type == D3D12_HEAP_TYPE_UPLOAD) ? D3D12_RESOURCE_STATE_GENERIC_READ : D3D12_RESOURCE_STATE_COPY_DEST;

    ID3D12Resource *res;
    VHR(ID3D12Device_CreateCommittedResource(d3d, &heap_props, D3D12_HEAP_FLAG_NONE, &buffer_desc, state, NULL,
                                             &IID_ID3D12Resource, &res));
    return res;
}
<commit_msg>Delete d3d12.inl<commit_after><|endoftext|>


<commit_before>/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2014-2020 Couchbase, Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include "mcreq.h"
#include "compress.h"

#include <snappy.h>
#include <snappy-sinksource.h>

class FragBufSource : public snappy::Source
{
  public:
    explicit FragBufSource(const lcb_FRAGBUF *buf_) : buf(buf_)
    {
        if (buf->total_length) {
            left = buf->total_length;
        } else {
            left = 0;
            for (unsigned int ii = 0; ii < buf->niov; ii++) {
                left += buf->iov[ii].iov_len;
            }
        }
        idx = 0;
        ptr = static_cast< const char * >(buf->iov[idx].iov_base);
    }

    virtual ~FragBufSource() {}

    virtual size_t Available() const
    {
        return left;
    }

    virtual const char *Peek(size_t *len)
    {
        *len =
            buf->iov[idx].iov_len - static_cast< size_t >((ptr - static_cast< const char * >(buf->iov[idx].iov_base)));
        return ptr;
    }

    virtual void Skip(size_t n)
    {
        do {
            size_t spanleft = buf->iov[idx].iov_len - (ptr - static_cast< const char * >(buf->iov[idx].iov_base));
            if (n < spanleft) {
                ptr += n;
                left -= n;
                break;
            }
            if (idx + 1 >= buf->niov) {
                left = 0;
                ptr = NULL;
                break;
            }
            left -= spanleft;
            n -= spanleft;
            ptr = static_cast< const char * >(buf->iov[++idx].iov_base);
        } while (n > 0);
        if (left == 0 || idx >= buf->niov) {
            ptr = NULL;
            left = 0;
        }
    }

  private:
    const lcb_FRAGBUF *buf;
    const char *ptr;
    size_t left;
    unsigned int idx;
};

int mcreq_compress_value(mc_PIPELINE *pl, mc_PACKET *pkt, const lcb_VALBUF *vbuf, lcb_settings *settings,
                         int *should_compress)
{
    size_t maxsize, compsize = 0, origsize = 0;

    snappy::Source *source = NULL;
    switch (vbuf->vtype) {
        case LCB_KV_COPY:
        case LCB_KV_CONTIG:
            origsize = vbuf->u_buf.contig.nbytes;
            if (origsize < settings->compress_min_size) {
                *should_compress = 0;
                mcreq_reserve_value(pl, pkt, vbuf);
                return 0;
            }
            source = new snappy::ByteArraySource(static_cast< const char * >(vbuf->u_buf.contig.bytes),
                                                 vbuf->u_buf.contig.nbytes);
            break;

        case LCB_KV_IOV:
        case LCB_KV_IOVCOPY:
            if (vbuf->u_buf.multi.total_length == 0) {
                for (unsigned int ii = 0; ii < vbuf->u_buf.multi.niov; ii++) {
                    origsize += vbuf->u_buf.multi.iov[ii].iov_len;
                }
            }
            if (origsize < settings->compress_min_size) {
                *should_compress = 0;
                mcreq_reserve_value(pl, pkt, vbuf);
                return 0;
            }
            source = new FragBufSource(&vbuf->u_buf.multi);
            break;

        default:
            return -1;
    }

    maxsize = snappy::MaxCompressedLength(source->Available());
    if (mcreq_reserve_value2(pl, pkt, maxsize) != LCB_SUCCESS) {
        return -1;
    }
    nb_SPAN *outspan = &pkt->u_value.single;
    snappy::UncheckedByteArraySink sink(SPAN_BUFFER(outspan));

    Compress(source, &sink);
    compsize = sink.CurrentDestination() - SPAN_BUFFER(outspan);
    delete source;

    if (compsize == 0 || (((float)compsize / origsize) > settings->compress_min_ratio)) {
        netbuf_mblock_release(&pl->nbmgr, outspan);
        *should_compress = 0;
        mcreq_reserve_value(pl, pkt, vbuf);
        return 0;
    }

    if (compsize < maxsize) {
        /* chop off some bytes? */
        nb_SPAN trailspan = *outspan;
        trailspan.offset += compsize;
        trailspan.size = maxsize - compsize;
        netbuf_mblock_release(&pl->nbmgr, &trailspan);
        outspan->size = compsize;
    }
    return 0;
}

int mcreq_inflate_value(const void *compressed, lcb_SIZE ncompressed, const void **bytes, lcb_SIZE *nbytes,
                        void **freeptr)
{
    size_t compsize = 0;

    if (!snappy::GetUncompressedLength(static_cast< const char * >(compressed), (size_t)ncompressed, &compsize)) {
        return -1;
    }
    *freeptr = malloc(compsize);
    if (!snappy::RawUncompress(static_cast< const char * >(compressed), ncompressed, static_cast< char * >(*freeptr))) {
        free(*freeptr);
        *freeptr = NULL;
        return -1;
    }

    *bytes = *freeptr;
    *nbytes = compsize;
    return 0;
}
<commit_msg>[coverity] compress.cc ensure that we never divide by zero<commit_after>/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2014-2020 Couchbase, Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include "mcreq.h"
#include "compress.h"

#include <snappy.h>
#include <snappy-sinksource.h>

class FragBufSource : public snappy::Source
{
  public:
    explicit FragBufSource(const lcb_FRAGBUF *buf_) : buf(buf_)
    {
        if (buf->total_length) {
            left = buf->total_length;
        } else {
            left = 0;
            for (unsigned int ii = 0; ii < buf->niov; ii++) {
                left += buf->iov[ii].iov_len;
            }
        }
        idx = 0;
        ptr = static_cast< const char * >(buf->iov[idx].iov_base);
    }

    virtual ~FragBufSource() {}

    virtual size_t Available() const
    {
        return left;
    }

    virtual const char *Peek(size_t *len)
    {
        *len =
            buf->iov[idx].iov_len - static_cast< size_t >((ptr - static_cast< const char * >(buf->iov[idx].iov_base)));
        return ptr;
    }

    virtual void Skip(size_t n)
    {
        do {
            size_t spanleft = buf->iov[idx].iov_len - (ptr - static_cast< const char * >(buf->iov[idx].iov_base));
            if (n < spanleft) {
                ptr += n;
                left -= n;
                break;
            }
            if (idx + 1 >= buf->niov) {
                left = 0;
                ptr = NULL;
                break;
            }
            left -= spanleft;
            n -= spanleft;
            ptr = static_cast< const char * >(buf->iov[++idx].iov_base);
        } while (n > 0);
        if (left == 0 || idx >= buf->niov) {
            ptr = NULL;
            left = 0;
        }
    }

  private:
    const lcb_FRAGBUF *buf;
    const char *ptr;
    size_t left;
    unsigned int idx;
};

int mcreq_compress_value(mc_PIPELINE *pl, mc_PACKET *pkt, const lcb_VALBUF *vbuf, lcb_settings *settings,
                         int *should_compress)
{
    size_t maxsize, compsize = 0, origsize = 0;

    snappy::Source *source = NULL;
    switch (vbuf->vtype) {
        case LCB_KV_COPY:
        case LCB_KV_CONTIG:
            origsize = vbuf->u_buf.contig.nbytes;
            if (origsize < settings->compress_min_size) {
                *should_compress = 0;
                mcreq_reserve_value(pl, pkt, vbuf);
                return 0;
            }
            source = new snappy::ByteArraySource(static_cast< const char * >(vbuf->u_buf.contig.bytes),
                                                 vbuf->u_buf.contig.nbytes);
            break;

        case LCB_KV_IOV:
        case LCB_KV_IOVCOPY:
            if (vbuf->u_buf.multi.total_length == 0) {
                for (unsigned int ii = 0; ii < vbuf->u_buf.multi.niov; ii++) {
                    origsize += vbuf->u_buf.multi.iov[ii].iov_len;
                }
            }
            if (origsize == 0 || origsize < settings->compress_min_size) {
                *should_compress = 0;
                mcreq_reserve_value(pl, pkt, vbuf);
                return 0;
            }
            source = new FragBufSource(&vbuf->u_buf.multi);
            break;

        default:
            return -1;
    }

    maxsize = snappy::MaxCompressedLength(source->Available());
    if (mcreq_reserve_value2(pl, pkt, maxsize) != LCB_SUCCESS) {
        return -1;
    }
    nb_SPAN *outspan = &pkt->u_value.single;
    snappy::UncheckedByteArraySink sink(SPAN_BUFFER(outspan));

    Compress(source, &sink);
    compsize = sink.CurrentDestination() - SPAN_BUFFER(outspan);
    delete source;

    if (compsize == 0 || (((float)compsize / origsize) > settings->compress_min_ratio)) {
        netbuf_mblock_release(&pl->nbmgr, outspan);
        *should_compress = 0;
        mcreq_reserve_value(pl, pkt, vbuf);
        return 0;
    }

    if (compsize < maxsize) {
        /* chop off some bytes? */
        nb_SPAN trailspan = *outspan;
        trailspan.offset += compsize;
        trailspan.size = maxsize - compsize;
        netbuf_mblock_release(&pl->nbmgr, &trailspan);
        outspan->size = compsize;
    }
    return 0;
}

int mcreq_inflate_value(const void *compressed, lcb_SIZE ncompressed, const void **bytes, lcb_SIZE *nbytes,
                        void **freeptr)
{
    size_t compsize = 0;

    if (!snappy::GetUncompressedLength(static_cast< const char * >(compressed), (size_t)ncompressed, &compsize)) {
        return -1;
    }
    *freeptr = malloc(compsize);
    if (!snappy::RawUncompress(static_cast< const char * >(compressed), ncompressed, static_cast< char * >(*freeptr))) {
        free(*freeptr);
        *freeptr = NULL;
        return -1;
    }

    *bytes = *freeptr;
    *nbytes = compsize;
    return 0;
}
<|endoftext|>


<commit_before>

#include "JsonConverter.h"
#include <json/writer.h>

// #include "abstractable.h"
#include "miracle.h"

using namespace std;
using namespace mgl;
using namespace Json;
using namespace libthing;

//// @param slices list of output slice (output )
void mgl::miracleGrue(const GCoderConfig &gcoderCfg,
                      const SlicerConfig &slicerCfg,
                      const char *modelFile,
                      const char *, // scadFileStr,
                      const char *gcodeFile,
                      int firstSliceIdx,
                      int lastSliceIdx,
                      Tomograph &tomograph,
                      Regions &regions,
                      std::vector< SliceData >  &slices,
                      ProgressBar *progress)
{

	Meshy mesh(slicerCfg.firstLayerZ, slicerCfg.layerH);
	mesh.readStlFile(modelFile);

	Slicer slicer(slicerCfg, progress);

	slicer.tomographyze(mesh, tomograph);

	Regioner regioner(slicerCfg, progress);

	regioner.generateSkeleton(tomograph, regions);

	Pather pather(progress);

	pather.generatePaths(tomograph, regions, slices);

	// pather.writeGcode(gcodeFileStr, modelFile, slices);
	std::ofstream gout(gcodeFile);

        GCoder gcoder(gcoderCfg, progress);
    gcoder.writeGcodeFile(slices, tomograph.layerMeasure, gout, modelFile, firstSliceIdx, lastSliceIdx);

	gout.close();

}

<commit_msg>[finishes 31345487] align the mesh to the bed after reading the stl<commit_after>

#include "JsonConverter.h"
#include <json/writer.h>

// #include "abstractable.h"
#include "miracle.h"

using namespace std;
using namespace mgl;
using namespace Json;
using namespace libthing;

//// @param slices list of output slice (output )
void mgl::miracleGrue(const GCoderConfig &gcoderCfg,
                      const SlicerConfig &slicerCfg,
                      const char *modelFile,
                      const char *, // scadFileStr,
                      const char *gcodeFile,
                      int firstSliceIdx,
                      int lastSliceIdx,
                      Tomograph &tomograph,
                      Regions &regions,
                      std::vector< SliceData >  &slices,
                      ProgressBar *progress)
{

	Meshy mesh(slicerCfg.firstLayerZ, slicerCfg.layerH);
	mesh.readStlFile(modelFile);
	mesh.alignToPlate();

	Slicer slicer(slicerCfg, progress);

	slicer.tomographyze(mesh, tomograph);

	Regioner regioner(slicerCfg, progress);

	regioner.generateSkeleton(tomograph, regions);

	Pather pather(progress);

	pather.generatePaths(tomograph, regions, slices);

	// pather.writeGcode(gcodeFileStr, modelFile, slices);
	std::ofstream gout(gcodeFile);

        GCoder gcoder(gcoderCfg, progress);
    gcoder.writeGcodeFile(slices, tomograph.layerMeasure, gout, modelFile, firstSliceIdx, lastSliceIdx);

	gout.close();

}

<|endoftext|>


<commit_before>//==============================================================================
// Some useful functions
//==============================================================================

#include "utils.h"

//==============================================================================

#include <QCoreApplication>
#include <QDate>
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QFileInfo>
#include <QProcess>
#include <QResource>

//==============================================================================

namespace OpenCOR {

//==============================================================================

QString exec(const QString &pProg, const QString &pArgs)
{
    if (QFileInfo(pProg).exists()) {
        // The program exists, so we can execute it

        QProcess process;

        process.start(pProg,  pArgs.split(' '));
        process.waitForFinished();

        return process.readAll().trimmed();
    } else {
        // The program doesn't exist, so...

        return QString();
    }
}

//==============================================================================

QString getOsName()
{
#ifdef Q_WS_WIN
    switch (QSysInfo::WindowsVersion) {
    case QSysInfo::WV_NT:
        return "Microsoft Windows NT";
    case QSysInfo::WV_2000:
        return "Microsoft Windows 2000";
    case QSysInfo::WV_XP:
        return "Microsoft Windows XP";
    case QSysInfo::WV_2003:
        return "Microsoft Windows 2003";
    case QSysInfo::WV_VISTA:
        return "Microsoft Windows Vista";
    case QSysInfo::WV_WINDOWS7:
        return "Microsoft Windows 7";
    default:
        return "Microsoft Windows";
    }
#elif defined(Q_WS_MAC)
    // Note #1: the version of Qt that we use on OS X only supports Mac OS X
    //          10.5 and above, so...
    // Note #2: from version 10.7, Apple uses OS X rather than Mac OS X...

    switch (QSysInfo::MacintoshVersion) {
    case QSysInfo::MV_10_5:
        return "Mac OS X 10.5 (Leopard)";
    case QSysInfo::MV_10_6:
        return "Mac OS X 10.6 (Snow Leopard)";
    case QSysInfo::MV_10_7:
        return "OS X 10.7 (Lion)";
    case QSysInfo::MV_10_8:
        return "OS X 10.8 (Mountain Lion)";
    default:
        return "Mac OS X";
    }
#else
    QString os = exec("/bin/uname", "-o");

    if (os.isEmpty())
        // We couldn't find /bin/uname, so...

        return "Unknown";
    else
        return os+" "+exec("/bin/uname", "-r");
#endif
}

//==============================================================================

QString getAppVersion(QCoreApplication *pApp)
{
    QString bitVersion;
    static int sizeOfPointer = sizeof(void *);

    switch (sizeOfPointer) {
    case 4:
        bitVersion = " (32-bit)";

        break;
    case 8:
        bitVersion = " (64-bit)";

        break;
    default:
        // Not a size that we could recognise, so...

        bitVersion = "";
    }

    return  pApp->applicationName()+" "+pApp->applicationVersion()+bitVersion;
}

//==============================================================================

QString getAppCopyright(const bool &pHtml)
{
    return QObject::tr("Copyright")+" "+QString(pHtml?"©":"")+"2011-"+QString::number(QDate().year());
}

//==============================================================================

}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Minor fix in the current year for our copyright information.<commit_after>//==============================================================================
// Some useful functions
//==============================================================================

#include "utils.h"

//==============================================================================

#include <QCoreApplication>
#include <QDate>
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QFileInfo>
#include <QProcess>
#include <QResource>

//==============================================================================

namespace OpenCOR {

//==============================================================================

QString exec(const QString &pProg, const QString &pArgs)
{
    if (QFileInfo(pProg).exists()) {
        // The program exists, so we can execute it

        QProcess process;

        process.start(pProg,  pArgs.split(' '));
        process.waitForFinished();

        return process.readAll().trimmed();
    } else {
        // The program doesn't exist, so...

        return QString();
    }
}

//==============================================================================

QString getOsName()
{
#ifdef Q_WS_WIN
    switch (QSysInfo::WindowsVersion) {
    case QSysInfo::WV_NT:
        return "Microsoft Windows NT";
    case QSysInfo::WV_2000:
        return "Microsoft Windows 2000";
    case QSysInfo::WV_XP:
        return "Microsoft Windows XP";
    case QSysInfo::WV_2003:
        return "Microsoft Windows 2003";
    case QSysInfo::WV_VISTA:
        return "Microsoft Windows Vista";
    case QSysInfo::WV_WINDOWS7:
        return "Microsoft Windows 7";
    default:
        return "Microsoft Windows";
    }
#elif defined(Q_WS_MAC)
    // Note #1: the version of Qt that we use on OS X only supports Mac OS X
    //          10.5 and above, so...
    // Note #2: from version 10.7, Apple uses OS X rather than Mac OS X...

    switch (QSysInfo::MacintoshVersion) {
    case QSysInfo::MV_10_5:
        return "Mac OS X 10.5 (Leopard)";
    case QSysInfo::MV_10_6:
        return "Mac OS X 10.6 (Snow Leopard)";
    case QSysInfo::MV_10_7:
        return "OS X 10.7 (Lion)";
    case QSysInfo::MV_10_8:
        return "OS X 10.8 (Mountain Lion)";
    default:
        return "Mac OS X";
    }
#else
    QString os = exec("/bin/uname", "-o");

    if (os.isEmpty())
        // We couldn't find /bin/uname, so...

        return "Unknown";
    else
        return os+" "+exec("/bin/uname", "-r");
#endif
}

//==============================================================================

QString getAppVersion(QCoreApplication *pApp)
{
    QString bitVersion;
    static int sizeOfPointer = sizeof(void *);

    switch (sizeOfPointer) {
    case 4:
        bitVersion = " (32-bit)";

        break;
    case 8:
        bitVersion = " (64-bit)";

        break;
    default:
        // Not a size that we could recognise, so...

        bitVersion = "";
    }

    return  pApp->applicationName()+" "+pApp->applicationVersion()+bitVersion;
}

//==============================================================================

QString getAppCopyright(const bool &pHtml)
{
    return QObject::tr("Copyright")+" "+QString(pHtml?"©":"")+"2011-"+QString::number(QDate().currentDate().year());
}

//==============================================================================

}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>/***************************************************************************
 *                                                                         *
 * Copyright (C) 2007-2015 by frePPLe bv                                   *
 *                                                                         *
 * This library is free software; you can redistribute it and/or modify it *
 * under the terms of the GNU Affero General Public License as published   *
 * by the Free Software Foundation; either version 3 of the License, or    *
 * (at your option) any later version.                                     *
 *                                                                         *
 * This library is distributed in the hope that it will be useful,         *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
 * GNU Affero General Public License for more details.                     *
 *                                                                         *
 * You should have received a copy of the GNU Affero General Public        *
 * License along with this program.                                        *
 * If not, see <http://www.gnu.org/licenses/>.                             *
 *                                                                         *
 ***************************************************************************/

#define FREPPLE_CORE
#include "frepple/model.h"

namespace frepple {

template <class Item>
Tree utils::HasName<Item>::st;
const MetaCategory* Item::metadata;
const MetaClass *ItemMTO::metadata, *ItemMTS::metadata;

int Item::initialize() {
  metadata =
      MetaCategory::registerCategory<Item>("item", "items", reader, finder);
  registerFields<Item>(const_cast<MetaCategory*>(metadata));
  return FreppleCategory<Item>::initialize();
}

int ItemMTS::initialize() {
  ItemMTS::metadata = MetaClass::registerClass<ItemMTS>(
      "item", "item_mts", Object::create<ItemMTS>, true);
  return FreppleClass<ItemMTS, Item>::initialize();
}

int ItemMTO::initialize() {
  ItemMTO::metadata = MetaClass::registerClass<ItemMTO>(
      "item", "item_mto", Object::create<ItemMTO>);
  return FreppleClass<ItemMTO, Item>::initialize();
}

Item::~Item() {
  // Remove references from the buffers
  bufferIterator bufiter(this);
  while (Buffer* buf = bufiter.next()) buf->setItem(nullptr);

  // Remove references from the demands
  for (auto l = Demand::begin(); l != Demand::end(); ++l)
    if (l->getItem() == this) l->setItem(nullptr);

  // Remove all item operations referencing this item
  while (firstOperation) delete firstOperation;

  // The ItemSupplier objects are automatically deleted by the
  // destructor of the Association list class.
}

void Demand::setItem(Item* i) {
  // No change
  if (it == i) return;

  // Unlink from previous item
  if (it) {
    if (it->firstItemDemand == this)
      it->firstItemDemand = nextItemDemand;
    else {
      Demand* dmd = it->firstItemDemand;
      while (dmd && dmd->nextItemDemand != this) dmd = dmd->nextItemDemand;
      if (!dmd) throw LogicException("corrupted demand list for an item");
      dmd->nextItemDemand = nextItemDemand;
    }
  }

  // Link at new item
  it = i;
  if (it) {
    nextItemDemand = it->firstItemDemand;
    it->firstItemDemand = this;
  }

  // Trigger recreation of the delivery operation
  if (oper && oper->getHidden()) oper = uninitializedDelivery;

  // Trigger level calculation
  HasLevel::triggerLazyRecomputation();

  // Mark as changed
  setChanged();
}

Date Item::findEarliestPurchaseOrder(const PooledString& batch) const {
  Date earliest = Date::infiniteFuture;
  bufferIterator buf_iter(this);
  while (Buffer* buf = buf_iter.next()) {
    if (buf->getBatch() != batch) continue;
    for (auto flpln = buf->getFlowPlans().begin();
         flpln != buf->getFlowPlans().end(); ++flpln) {
      if (flpln->getDate() >= earliest) break;
      auto opplan = flpln->getOperationPlan();
      if (opplan && opplan->getOperation()->hasType<OperationItemSupplier>() &&
          opplan->getProposed()) {
        earliest = flpln->getDate();
        break;
      }
    }
  }
  return earliest;
}

}  // namespace frepple
<commit_msg>small todo remarks<commit_after>/***************************************************************************
 *                                                                         *
 * Copyright (C) 2007-2015 by frePPLe bv                                   *
 *                                                                         *
 * This library is free software; you can redistribute it and/or modify it *
 * under the terms of the GNU Affero General Public License as published   *
 * by the Free Software Foundation; either version 3 of the License, or    *
 * (at your option) any later version.                                     *
 *                                                                         *
 * This library is distributed in the hope that it will be useful,         *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
 * GNU Affero General Public License for more details.                     *
 *                                                                         *
 * You should have received a copy of the GNU Affero General Public        *
 * License along with this program.                                        *
 * If not, see <http://www.gnu.org/licenses/>.                             *
 *                                                                         *
 ***************************************************************************/

#define FREPPLE_CORE
#include "frepple/model.h"

namespace frepple {

template <class Item>
Tree utils::HasName<Item>::st;
const MetaCategory* Item::metadata;
const MetaClass *ItemMTO::metadata, *ItemMTS::metadata;

int Item::initialize() {
  metadata =
      MetaCategory::registerCategory<Item>("item", "items", reader, finder);
  registerFields<Item>(const_cast<MetaCategory*>(metadata));
  return FreppleCategory<Item>::initialize();
}

int ItemMTS::initialize() {
  ItemMTS::metadata = MetaClass::registerClass<ItemMTS>(
      "item", "item_mts", Object::create<ItemMTS>, true);
  return FreppleClass<ItemMTS, Item>::initialize();
}

int ItemMTO::initialize() {
  ItemMTO::metadata = MetaClass::registerClass<ItemMTO>(
      "item", "item_mto", Object::create<ItemMTO>);
  return FreppleClass<ItemMTO, Item>::initialize();
}

Item::~Item() {
  // Remove references from the buffers
  // TODO deleting would be better than leaving buffers with a null item
  bufferIterator bufiter(this);
  while (Buffer* buf = bufiter.next()) buf->setItem(nullptr);

  // Remove references from the demands
  // TODO rewrite using item-based demand iterator
  for (auto l = Demand::begin(); l != Demand::end(); ++l)
    if (l->getItem() == this) l->setItem(nullptr);

  // Remove all item operations referencing this item
  while (firstOperation) delete firstOperation;

  // The ItemSupplier objects are automatically deleted by the
  // destructor of the Association list class.
}

void Demand::setItem(Item* i) {
  // No change
  if (it == i) return;

  // Unlink from previous item
  if (it) {
    if (it->firstItemDemand == this)
      it->firstItemDemand = nextItemDemand;
    else {
      Demand* dmd = it->firstItemDemand;
      while (dmd && dmd->nextItemDemand != this) dmd = dmd->nextItemDemand;
      if (!dmd) throw LogicException("corrupted demand list for an item");
      dmd->nextItemDemand = nextItemDemand;
    }
  }

  // Link at new item
  it = i;
  if (it) {
    nextItemDemand = it->firstItemDemand;
    it->firstItemDemand = this;
  }

  // Trigger recreation of the delivery operation
  if (oper && oper->getHidden()) oper = uninitializedDelivery;

  // Trigger level calculation
  HasLevel::triggerLazyRecomputation();

  // Mark as changed
  setChanged();
}

Date Item::findEarliestPurchaseOrder(const PooledString& batch) const {
  Date earliest = Date::infiniteFuture;
  bufferIterator buf_iter(this);
  while (Buffer* buf = buf_iter.next()) {
    if (buf->getBatch() != batch) continue;
    for (auto flpln = buf->getFlowPlans().begin();
         flpln != buf->getFlowPlans().end(); ++flpln) {
      if (flpln->getDate() >= earliest) break;
      auto opplan = flpln->getOperationPlan();
      if (opplan && opplan->getOperation()->hasType<OperationItemSupplier>() &&
          opplan->getProposed()) {
        earliest = flpln->getDate();
        break;
      }
    }
  }
  return earliest;
}

}  // namespace frepple
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "Type.hpp"
#include "VisitorUtils.hpp"
#include "GlobalContext.hpp"
#include "mangling.hpp"
#include "Variable.hpp"

#include "mtac/Utils.hpp"
#include "mtac/Quadruple.hpp"

using namespace eddic;

bool mtac::is_single_int_register(std::shared_ptr<const Type> type){
   return type == INT || type == BOOL || type == CHAR || type->is_pointer();
}

bool mtac::is_single_float_register(std::shared_ptr<const Type> type){
    return type == FLOAT;
}

bool mtac::is_recursive(mtac::Function& function){
    for(auto& basic_block : function){
        for(auto& quadruple : basic_block->statements){
            if(quadruple->op == mtac::Operator::CALL && quadruple->function().mangled_name() == function.definition().mangled_name()){
                return true;
            }
        }
    }

    return false;
}

namespace {

struct VariableUsageCollector {
    mtac::VariableUsage& usage;
    int depth_factor;
    int current_depth;

    VariableUsageCollector(mtac::VariableUsage& usage, int depth_factor) : usage(usage), depth_factor(depth_factor) {}

    void inc_usage(std::shared_ptr<Variable> variable){
        usage[variable] += pow(depth_factor, current_depth);
    }

    template<typename T>
    void collect_optional(T& opt){
        if(opt){
            if(auto* variablePtr = boost::get<std::shared_ptr<Variable>>(&*opt)){
                inc_usage(*variablePtr);
            }
        }
    }

    void collect(std::shared_ptr<mtac::Quadruple> quadruple){
        current_depth = quadruple->depth;

        inc_usage(quadruple->result);
        collect_optional(quadruple->arg1);
        collect_optional(quadruple->arg2);
    }
};

struct BasicBlockUsageCollector {
    std::unordered_set<mtac::basic_block_p>& usage;

    BasicBlockUsageCollector(std::unordered_set<mtac::basic_block_p>& usage) : usage(usage) {}

    void collect(std::shared_ptr<mtac::Quadruple> goto_){
        usage.insert(goto_->block);
    }
};

} //end of anonymous namespace

mtac::VariableUsage mtac::compute_variable_usage(mtac::Function& function){
    return compute_variable_usage_with_depth(function, 1);
}

mtac::VariableUsage mtac::compute_variable_usage_with_depth(mtac::Function& function, int factor){
    mtac::VariableUsage usage;

    VariableUsageCollector collector(usage, factor);

    for(auto& block : function){
        for(auto& quadruple : block->statements){
            collector.collect(quadruple);
        }
    }

    return usage;
}

void eddic::mtac::computeBlockUsage(mtac::Function& function, std::unordered_set<mtac::basic_block_p>& usage){
    BasicBlockUsageCollector collector(usage);

    for(auto& block : function){
        for(auto& quadruple : block->statements){
            collector.collect(quadruple);
        }
    }
}

bool eddic::mtac::safe(const std::string& function){
    //These functions are considered as safe because they save/restore all the registers and does not return anything
    return
        function == "_F5printI" || function == "_F5printF" || function == "_F5printS" || function == "_F5printC" ||
        function == "_F7printlnI" || function == "_F7printlnF" || function == "_F7printlnS" || function == "_F7printlnC" ||
        function == "_F7println";
}

bool eddic::mtac::erase_result(mtac::Operator op){
   return
           op != mtac::Operator::DOT_ASSIGN
        && op != mtac::Operator::DOT_FASSIGN
        && op != mtac::Operator::DOT_PASSIGN
        && op != mtac::Operator::RETURN
        && op != mtac::Operator::GOTO
        && op != mtac::Operator::NOP
        && op != mtac::Operator::PARAM
        && op != mtac::Operator::CALL
        && op != mtac::Operator::LABEL;
}

bool eddic::mtac::is_distributive(mtac::Operator op){
    return op == mtac::Operator::ADD || op == mtac::Operator::FADD || op == mtac::Operator::MUL || op == mtac::Operator::FMUL;
}

bool eddic::mtac::is_expression(mtac::Operator op){
    return op >= mtac::Operator::ADD && op <= mtac::Operator::FDIV;
}

unsigned int eddic::mtac::compute_member_offset(std::shared_ptr<const GlobalContext> context, std::shared_ptr<const Type> type, const std::string& member){
    return compute_member(context, type, member).first;
}

std::pair<unsigned int, std::shared_ptr<const Type>> eddic::mtac::compute_member(std::shared_ptr<const GlobalContext> context, std::shared_ptr<const Type> type, const std::string& member){
    auto struct_type = context->get_struct(type);
    std::shared_ptr<const Type> member_type;
    unsigned int offset = 0;

    do {
        if(struct_type->member_exists(member)){
            member_type = (*struct_type)[member]->type;
            break;
        }

        offset += context->self_size_of_struct(struct_type);

        struct_type = context->get_struct(struct_type->parent_type);
    } while(struct_type);

    eddic_assert(member_type, "The member must exist");

    offset += context->member_offset(struct_type, member);

    return std::make_pair(offset, member_type);
}

//TODO Use the copy constructor instead

std::shared_ptr<mtac::Quadruple> mtac::copy(const std::shared_ptr<mtac::Quadruple>& quadruple){
    return std::make_shared<mtac::Quadruple>(*quadruple);
}
<commit_msg>Fix erase_result<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "Type.hpp"
#include "VisitorUtils.hpp"
#include "GlobalContext.hpp"
#include "mangling.hpp"
#include "Variable.hpp"

#include "mtac/Utils.hpp"
#include "mtac/Quadruple.hpp"

using namespace eddic;

bool mtac::is_single_int_register(std::shared_ptr<const Type> type){
   return type == INT || type == BOOL || type == CHAR || type->is_pointer();
}

bool mtac::is_single_float_register(std::shared_ptr<const Type> type){
    return type == FLOAT;
}

bool mtac::is_recursive(mtac::Function& function){
    for(auto& basic_block : function){
        for(auto& quadruple : basic_block->statements){
            if(quadruple->op == mtac::Operator::CALL && quadruple->function().mangled_name() == function.definition().mangled_name()){
                return true;
            }
        }
    }

    return false;
}

namespace {

struct VariableUsageCollector {
    mtac::VariableUsage& usage;
    int depth_factor;
    int current_depth;

    VariableUsageCollector(mtac::VariableUsage& usage, int depth_factor) : usage(usage), depth_factor(depth_factor) {}

    void inc_usage(std::shared_ptr<Variable> variable){
        usage[variable] += pow(depth_factor, current_depth);
    }

    template<typename T>
    void collect_optional(T& opt){
        if(opt){
            if(auto* variablePtr = boost::get<std::shared_ptr<Variable>>(&*opt)){
                inc_usage(*variablePtr);
            }
        }
    }

    void collect(std::shared_ptr<mtac::Quadruple> quadruple){
        current_depth = quadruple->depth;

        inc_usage(quadruple->result);
        collect_optional(quadruple->arg1);
        collect_optional(quadruple->arg2);
    }
};

struct BasicBlockUsageCollector {
    std::unordered_set<mtac::basic_block_p>& usage;

    BasicBlockUsageCollector(std::unordered_set<mtac::basic_block_p>& usage) : usage(usage) {}

    void collect(std::shared_ptr<mtac::Quadruple> goto_){
        usage.insert(goto_->block);
    }
};

} //end of anonymous namespace

mtac::VariableUsage mtac::compute_variable_usage(mtac::Function& function){
    return compute_variable_usage_with_depth(function, 1);
}

mtac::VariableUsage mtac::compute_variable_usage_with_depth(mtac::Function& function, int factor){
    mtac::VariableUsage usage;

    VariableUsageCollector collector(usage, factor);

    for(auto& block : function){
        for(auto& quadruple : block->statements){
            collector.collect(quadruple);
        }
    }

    return usage;
}

void eddic::mtac::computeBlockUsage(mtac::Function& function, std::unordered_set<mtac::basic_block_p>& usage){
    BasicBlockUsageCollector collector(usage);

    for(auto& block : function){
        for(auto& quadruple : block->statements){
            collector.collect(quadruple);
        }
    }
}

bool eddic::mtac::safe(const std::string& function){
    //These functions are considered as safe because they save/restore all the registers and does not return anything
    return
        function == "_F5printI" || function == "_F5printF" || function == "_F5printS" || function == "_F5printC" ||
        function == "_F7printlnI" || function == "_F7printlnF" || function == "_F7printlnS" || function == "_F7printlnC" ||
        function == "_F7println";
}

bool eddic::mtac::erase_result(mtac::Operator op){
   return
           op != mtac::Operator::DOT_ASSIGN
        && op != mtac::Operator::DOT_FASSIGN
        && op != mtac::Operator::DOT_PASSIGN
        && op != mtac::Operator::RETURN
        && op != mtac::Operator::GOTO
        && op != mtac::Operator::NOP
        && op != mtac::Operator::PARAM
        && op != mtac::Operator::CALL
        && op != mtac::Operator::LABEL
        && !(op >= mtac::Operator::IF_UNARY && op <= mtac::Operator::IF_FALSE_FL);
}

bool eddic::mtac::is_distributive(mtac::Operator op){
    return op == mtac::Operator::ADD || op == mtac::Operator::FADD || op == mtac::Operator::MUL || op == mtac::Operator::FMUL;
}

bool eddic::mtac::is_expression(mtac::Operator op){
    return op >= mtac::Operator::ADD && op <= mtac::Operator::FDIV;
}

unsigned int eddic::mtac::compute_member_offset(std::shared_ptr<const GlobalContext> context, std::shared_ptr<const Type> type, const std::string& member){
    return compute_member(context, type, member).first;
}

std::pair<unsigned int, std::shared_ptr<const Type>> eddic::mtac::compute_member(std::shared_ptr<const GlobalContext> context, std::shared_ptr<const Type> type, const std::string& member){
    auto struct_type = context->get_struct(type);
    std::shared_ptr<const Type> member_type;
    unsigned int offset = 0;

    do {
        if(struct_type->member_exists(member)){
            member_type = (*struct_type)[member]->type;
            break;
        }

        offset += context->self_size_of_struct(struct_type);

        struct_type = context->get_struct(struct_type->parent_type);
    } while(struct_type);

    eddic_assert(member_type, "The member must exist");

    offset += context->member_offset(struct_type, member);

    return std::make_pair(offset, member_type);
}

//TODO Use the copy constructor instead

std::shared_ptr<mtac::Quadruple> mtac::copy(const std::shared_ptr<mtac::Quadruple>& quadruple){
    return std::make_shared<mtac::Quadruple>(*quadruple);
}
<|endoftext|>