<commit_before>//==============================================================================
// CellML annotation view CellML details widget
//==============================================================================

#include "borderedwidget.h"
#include "cellmlannotationviewcellmldetailswidget.h"
#include "cellmlannotationviewmetadatabiomodelsdotnetviewdetailswidget.h"
#include "cellmlannotationviewwidget.h"
#include "cellmlannotationviewmetadataviewdetailswidget.h"
#include "coreutils.h"

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

#include "ui_cellmlannotationviewcellmldetailswidget.h"

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

#include <QComboBox>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QWebView>

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

#include <QJsonParser>

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

namespace OpenCOR {
namespace CellMLAnnotationView {

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

CellmlAnnotationViewCellmlDetailsWidget::CellmlAnnotationViewCellmlDetailsWidget(CellmlAnnotationViewWidget *pParent) :
    QSplitter(pParent),
    CommonWidget(pParent),
    mParent(pParent),
    mGui(new Ui::CellmlAnnotationViewCellmlDetailsWidget)
{
    // Set up the GUI

    mGui->setupUi(this);

    // Create our details widgets

    mCellmlElementDetails = new CellmlAnnotationViewCellmlElementDetailsWidget(pParent);
    mMetadataViewDetails  = new CellmlAnnotationViewMetadataViewDetailsWidget(pParent);
    mWebView              = new QWebView(pParent);

    // A connection to handle the looking up of a resource and a resource id

    connect(mMetadataViewDetails->bioModelsDotNetView(), SIGNAL(qualifierLookupRequested(const QString &, const bool &)),
            this, SLOT(qualifierLookupRequested(const QString &, const bool &)));
    connect(mMetadataViewDetails->bioModelsDotNetView(), SIGNAL(resourceLookupRequested(const QString &, const bool &)),
            this, SLOT(resourceLookupRequested(const QString &, const bool &)));
    connect(mMetadataViewDetails->bioModelsDotNetView(), SIGNAL(resourceIdLookupRequested(const QString &, const QString &, const bool &)),
            this, SLOT(resourceIdLookupRequested(const QString &, const QString &, const bool &)));

    // Add our details widgets to our splitter

    addWidget(new Core::BorderedWidget(mCellmlElementDetails,
                                       false, true, true, false));
    addWidget(new Core::BorderedWidget(mMetadataViewDetails,
                                       true, true, true, false));
    addWidget(new Core::BorderedWidget(mWebView,
                                       true, true, false, false));

    // Keep track of our splitter being moved

    connect(this, SIGNAL(splitterMoved(int,int)),
            this, SLOT(emitSplitterMoved()));

    // Retrieve the output template

    QFile qualifierInformationFile(":qualifierInformation");

    qualifierInformationFile.open(QIODevice::ReadOnly);

    mQualifierInformationTemplate = QString(qualifierInformationFile.readAll());

    qualifierInformationFile.close();

    // Retrieve the SVG diagrams

    QFile modelQualifierFile(":modelQualifier");
    QFile biologyQualifierFile(":biologyQualifier");

    modelQualifierFile.open(QIODevice::ReadOnly);
    biologyQualifierFile.open(QIODevice::ReadOnly);

    mModelQualifierSvg   = QString(modelQualifierFile.readAll());
    mBiologyQualifierSvg = QString(biologyQualifierFile.readAll());

    modelQualifierFile.close();
    biologyQualifierFile.close();
}

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

CellmlAnnotationViewCellmlDetailsWidget::~CellmlAnnotationViewCellmlDetailsWidget()
{
    // Delete the GUI

    delete mGui;
}

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

void CellmlAnnotationViewCellmlDetailsWidget::retranslateUi()
{
    // Retranslate our GUI
    // Note: we must also update the connection for our cmeta:id widget since it
    //       gets recreated as a result of the retranslation...

    if (mCellmlElementDetails->cmetaIdValue())
        disconnect(mCellmlElementDetails->cmetaIdValue(), SIGNAL(editTextChanged(const QString &)),
                   this, SLOT(newCmetaId(const QString &)));

    mGui->retranslateUi(this);

    mCellmlElementDetails->retranslateUi();
    mMetadataViewDetails->retranslateUi();

    if (mCellmlElementDetails->cmetaIdValue())
        connect(mCellmlElementDetails->cmetaIdValue(), SIGNAL(editTextChanged(const QString &)),
                this, SLOT(newCmetaId(const QString &)));
}

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

void CellmlAnnotationViewCellmlDetailsWidget::updateGui(const CellmlAnnotationViewCellmlElementDetailsWidget::Items &pItems)
{
    // Stop tracking changes to the cmeta:id value of our CellML element

    if (mCellmlElementDetails->cmetaIdValue())
        disconnect(mCellmlElementDetails->cmetaIdValue(), SIGNAL(editTextChanged(const QString &)),
                   this, SLOT(newCmetaId(const QString &)));

    // 'Clean up' our web view

    mWebView->setUrl(QString());

    // Update our CellML element details GUI

    mCellmlElementDetails->updateGui(pItems);

    // Re-track changes to the cmeta:id value of our CellML element and update
    // our metadata details GUI

    if (mCellmlElementDetails->cmetaIdValue()) {
        connect(mCellmlElementDetails->cmetaIdValue(), SIGNAL(editTextChanged(const QString &)),
                this, SLOT(newCmetaId(const QString &)));

        newCmetaId(mCellmlElementDetails->cmetaIdValue()->currentText());
    }
}

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

void CellmlAnnotationViewCellmlDetailsWidget::updateSizes(const QList<int> &pSizes)
{
    // The splitter of another CellmlAnnotationViewCellmlDetailsWidget object
    // has been moved, so update our sizes

    setSizes(pSizes);
}

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

void CellmlAnnotationViewCellmlDetailsWidget::emitSplitterMoved()
{
    // Let whoever know that our splitter has been moved

    emit splitterMoved(sizes());
}

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

void CellmlAnnotationViewCellmlDetailsWidget::newCmetaId(const QString &pCmetaId)
{
    // Retrieve the RDF triples for the cmeta:id

    CellMLSupport::CellmlFileRdfTriples rdfTriples = pCmetaId.isEmpty()?
                                                         CellMLSupport::CellmlFileRdfTriples():
                                                         mParent->cellmlFile()->rdfTriples(pCmetaId);

    // Check that we are not dealing with the same RDF triples
    // Note: this may happen when manually typing the name of a cmeta:id and the
    //       QComboBox suggesting something for you, e.g. you start typing "C_"
    //       and the QComboBox suggests "C_C" (which will get us here) and then
    //       you finish typing "C_C" (which will also get us here)

    static CellMLSupport::CellmlFileRdfTriples oldRdfTriples = CellMLSupport::CellmlFileRdfTriples(mParent->cellmlFile());

    if (rdfTriples == oldRdfTriples)
        return;

    oldRdfTriples = rdfTriples;

    // 'Clean up' our web view

    mWebView->setUrl(QString());

    // Update its metadata details

    mMetadataViewDetails->updateGui(rdfTriples);
}

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

void CellmlAnnotationViewCellmlDetailsWidget::qualifierLookupRequested(const QString &pQualifier,
                                                                       const bool &pRetranslate)
{
    Q_UNUSED(pRetranslate);

    // The user requested a qualifier to be looked up, so generate a web page
    // containing some information about the qualifier
    // Note: ideally, there would be a way to refer to a particular qualifier
    //       using http://biomodels.net/qualifiers/, but that would require
    //       anchors and they don't have any, so instead we use the information
    //       which can be found on that site and present it to the user in the
    //       form of a web page...

    if (pQualifier.isEmpty())
        return;

    // Generate the web page containing some information about the qualifier

    QString qualifierSvg;
    QString shortDescription;
    QString longDescription;

    if (!pQualifier.compare("model:is")) {
        qualifierSvg = mModelQualifierSvg;

        shortDescription = tr("Identity");
        longDescription  = tr("The modelling object represented by the model element is identical with the subject of the referenced resource (\"Modelling Object B\"). For instance, this qualifier might be used to link an encoded model to a database of models.");
    } else if (!pQualifier.compare("model:isDerivedFrom")) {
        qualifierSvg = mModelQualifierSvg;

        shortDescription = tr("Origin");
        longDescription  = tr("The modelling object represented by the model element is derived from the modelling object represented by the referenced resource (\"Modelling Object B\"). This relation may be used, for instance, to express a refinement or adaptation in usage for a previously described modelling component.");
    } else if (!pQualifier.compare("model:isDescribedBy")) {
        qualifierSvg = mModelQualifierSvg;

        shortDescription = tr("Description");
        longDescription  = tr("The modelling object represented by the model element is described by the subject of the referenced resource (\"Modelling Object B\"). This relation might be used to link a model or a kinetic law to the literature that describes it.");
    } else if (!pQualifier.compare("bio:encodes")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Encodement");
        longDescription  = tr("The biological entity represented by the model element encodes, directly or transitively, the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to express, for example, that a specific DNA sequence encodes a particular protein.");
    } else if (!pQualifier.compare("bio:hasPart")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Part");
        longDescription  = tr("The biological entity represented by the model element includes the subject of the referenced resource (\"Biological Entity B\"), either physically or logically. This relation might be used to link a complex to the description of its components.");
    } else if (!pQualifier.compare("bio:hasProperty")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Property");
        longDescription  = tr("The subject of the referenced resource (\"Biological Entity B\") is a property of the biological entity represented by the model element. This relation might be used when a biological entity exhibits a certain enzymatic activity or exerts a specific function.");
    } else if (!pQualifier.compare("bio:hasVersion")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Version");
        longDescription  = tr("The subject of the referenced resource (\"Biological Entity B\") is a version or an instance of the biological entity represented by the model element. This relation may be used to represent an isoform or modified form of a biological entity.");
    } else if (!pQualifier.compare("bio:is")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Indentity");
        longDescription  = tr("The biological entity represented by the model element has identity with the subject of the referenced resource (\"Biological Entity B\"). This relation might be used to link a reaction to its exact counterpart in a database, for instance.");
    } else if (!pQualifier.compare("bio:isDescribedBy")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Description");
        longDescription  = tr("The biological entity represented by the model element is described by the subject of the referenced resource (\"Biological Entity B\"). This relation should be used, for instance, to link a species or a parameter to the literature that describes the concentration of that species or the value of that parameter.");
    } else if (!pQualifier.compare("bio:isEncodedBy")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Encoder");
        longDescription  = tr("The biological entity represented by the model element is encoded, directly or transitively, by the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to express, for example, that a protein is encoded by a specific DNA sequence.");
    } else if (!pQualifier.compare("bio:isHomologTo")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Homolog");
        longDescription  = tr("The biological entity represented by the model element is homologous to the subject of the referenced resource (\"Biological Entity B\"). This relation can be used to represent biological entities that share a common ancestor.");
    } else if (!pQualifier.compare("bio:isPartOf")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Parthood");
        longDescription  = tr("The biological entity represented by the model element is a physical or logical part of the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to link a model component to a description of the complex in which it is a part.");
    } else if (!pQualifier.compare("bio:isPropertyOf")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Property bearer");
        longDescription  = tr("The biological entity represented by the model element is a property of the referenced resource (\"Biological Entity B\").");
    } else if (!pQualifier.compare("bio:isVersionOf")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Hypernym");
        longDescription  = tr("The biological entity represented by the model element is a version or an instance of the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to represent, for example, the 'superclass' or 'parent' form of a particular biological entity.");
    } else if (!pQualifier.compare("bio:occursIn")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Container");
        longDescription  = tr("The biological entity represented by the model element is physically limited to a location, which is the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to ascribe a compartmental location, within which a reaction takes place.");
    } else if (!pQualifier.compare("bio:hasTaxon")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Taxon");
        longDescription  = tr("The biological entity represented by the model element is taxonomically restricted, where the restriction is the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to ascribe a species restriction to a biochemical reaction.");
    } else {
        qualifierSvg = "";

        shortDescription = tr("Unknown");
        longDescription  = tr("Unknown");
    }

    // Show the information

    mWebView->setHtml(mQualifierInformationTemplate.arg(pQualifier,
                                                        qualifierSvg,
                                                        shortDescription,
                                                        longDescription,
                                                        Core::copyright()));
}

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

void CellmlAnnotationViewCellmlDetailsWidget::resourceLookupRequested(const QString &pResource,
                                                                      const bool &pRetranslate)
{
    // The user requested a resource to be looked up, so retrieve it using
    // identifiers.org, but only if we are not retranslating since the looking
    // up would already be correct

    if (!pRetranslate)
        mWebView->setUrl("http://identifiers.org/"+pResource+"/?redirect=true");
        //---GRY--- NOTE THAT redirect=true DOESN'T WORK AT THE MOMENT, SO WE DO
        //          END UP WITH A FRAME, BUT THE identifiers.org GUYS ARE GOING
        //          TO 'FIX' THAT, SO WE SHOULD BE READY FOR WHEN IT'S DONE...
}

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

void CellmlAnnotationViewCellmlDetailsWidget::resourceIdLookupRequested(const QString &pResource,
                                                                        const QString &pId,
                                                                        const bool &pRetranslate)
{
    // The user requested a resource id to be looked up, so retrieve it using
    // identifiers.org, but only if we are not retranslating since the looking
    // up would already be correct

    if (!pRetranslate)
        mWebView->setUrl("http://identifiers.org/"+pResource+"/"+pId+"?profile=most_reliable&redirect=true");
}

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

void CellmlAnnotationViewCellmlDetailsWidget::metadataUpdated()
{
    // Some metadata has been updated, so we need to update the metadata
    // information we show to the user

    if (mCellmlElementDetails->cmetaIdValue())
        newCmetaId(mCellmlElementDetails->cmetaIdValue()->currentText());
}

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

}   // namespace CellMLAnnotationView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Display the model-level metadata (i.e. cmeta:id == "") when there is no cmeta:id for a CellML element.<commit_after>//==============================================================================
// CellML annotation view CellML details widget
//==============================================================================

#include "borderedwidget.h"
#include "cellmlannotationviewcellmldetailswidget.h"
#include "cellmlannotationviewmetadatabiomodelsdotnetviewdetailswidget.h"
#include "cellmlannotationviewwidget.h"
#include "cellmlannotationviewmetadataviewdetailswidget.h"
#include "coreutils.h"

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

#include "ui_cellmlannotationviewcellmldetailswidget.h"

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

#include <QComboBox>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QWebView>

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

#include <QJsonParser>

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

namespace OpenCOR {
namespace CellMLAnnotationView {

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

CellmlAnnotationViewCellmlDetailsWidget::CellmlAnnotationViewCellmlDetailsWidget(CellmlAnnotationViewWidget *pParent) :
    QSplitter(pParent),
    CommonWidget(pParent),
    mParent(pParent),
    mGui(new Ui::CellmlAnnotationViewCellmlDetailsWidget)
{
    // Set up the GUI

    mGui->setupUi(this);

    // Create our details widgets

    mCellmlElementDetails = new CellmlAnnotationViewCellmlElementDetailsWidget(pParent);
    mMetadataViewDetails  = new CellmlAnnotationViewMetadataViewDetailsWidget(pParent);
    mWebView              = new QWebView(pParent);

    // A connection to handle the looking up of a resource and a resource id

    connect(mMetadataViewDetails->bioModelsDotNetView(), SIGNAL(qualifierLookupRequested(const QString &, const bool &)),
            this, SLOT(qualifierLookupRequested(const QString &, const bool &)));
    connect(mMetadataViewDetails->bioModelsDotNetView(), SIGNAL(resourceLookupRequested(const QString &, const bool &)),
            this, SLOT(resourceLookupRequested(const QString &, const bool &)));
    connect(mMetadataViewDetails->bioModelsDotNetView(), SIGNAL(resourceIdLookupRequested(const QString &, const QString &, const bool &)),
            this, SLOT(resourceIdLookupRequested(const QString &, const QString &, const bool &)));

    // Add our details widgets to our splitter

    addWidget(new Core::BorderedWidget(mCellmlElementDetails,
                                       false, true, true, false));
    addWidget(new Core::BorderedWidget(mMetadataViewDetails,
                                       true, true, true, false));
    addWidget(new Core::BorderedWidget(mWebView,
                                       true, true, false, false));

    // Keep track of our splitter being moved

    connect(this, SIGNAL(splitterMoved(int,int)),
            this, SLOT(emitSplitterMoved()));

    // Retrieve the output template

    QFile qualifierInformationFile(":qualifierInformation");

    qualifierInformationFile.open(QIODevice::ReadOnly);

    mQualifierInformationTemplate = QString(qualifierInformationFile.readAll());

    qualifierInformationFile.close();

    // Retrieve the SVG diagrams

    QFile modelQualifierFile(":modelQualifier");
    QFile biologyQualifierFile(":biologyQualifier");

    modelQualifierFile.open(QIODevice::ReadOnly);
    biologyQualifierFile.open(QIODevice::ReadOnly);

    mModelQualifierSvg   = QString(modelQualifierFile.readAll());
    mBiologyQualifierSvg = QString(biologyQualifierFile.readAll());

    modelQualifierFile.close();
    biologyQualifierFile.close();
}

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

CellmlAnnotationViewCellmlDetailsWidget::~CellmlAnnotationViewCellmlDetailsWidget()
{
    // Delete the GUI

    delete mGui;
}

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

void CellmlAnnotationViewCellmlDetailsWidget::retranslateUi()
{
    // Retranslate our GUI
    // Note: we must also update the connection for our cmeta:id widget since it
    //       gets recreated as a result of the retranslation...

    if (mCellmlElementDetails->cmetaIdValue())
        disconnect(mCellmlElementDetails->cmetaIdValue(), SIGNAL(editTextChanged(const QString &)),
                   this, SLOT(newCmetaId(const QString &)));

    mGui->retranslateUi(this);

    mCellmlElementDetails->retranslateUi();
    mMetadataViewDetails->retranslateUi();

    if (mCellmlElementDetails->cmetaIdValue())
        connect(mCellmlElementDetails->cmetaIdValue(), SIGNAL(editTextChanged(const QString &)),
                this, SLOT(newCmetaId(const QString &)));
}

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

void CellmlAnnotationViewCellmlDetailsWidget::updateGui(const CellmlAnnotationViewCellmlElementDetailsWidget::Items &pItems)
{
    // Stop tracking changes to the cmeta:id value of our CellML element

    if (mCellmlElementDetails->cmetaIdValue())
        disconnect(mCellmlElementDetails->cmetaIdValue(), SIGNAL(editTextChanged(const QString &)),
                   this, SLOT(newCmetaId(const QString &)));

    // 'Clean up' our web view

    mWebView->setUrl(QString());

    // Update our CellML element details GUI

    mCellmlElementDetails->updateGui(pItems);

    // Re-track changes to the cmeta:id value of our CellML element and update
    // our metadata details GUI

    if (mCellmlElementDetails->cmetaIdValue()) {
        connect(mCellmlElementDetails->cmetaIdValue(), SIGNAL(editTextChanged(const QString &)),
                this, SLOT(newCmetaId(const QString &)));

        newCmetaId(mCellmlElementDetails->cmetaIdValue()->currentText());
    }
}

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

void CellmlAnnotationViewCellmlDetailsWidget::updateSizes(const QList<int> &pSizes)
{
    // The splitter of another CellmlAnnotationViewCellmlDetailsWidget object
    // has been moved, so update our sizes

    setSizes(pSizes);
}

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

void CellmlAnnotationViewCellmlDetailsWidget::emitSplitterMoved()
{
    // Let whoever know that our splitter has been moved

    emit splitterMoved(sizes());
}

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

void CellmlAnnotationViewCellmlDetailsWidget::newCmetaId(const QString &pCmetaId)
{
    // Retrieve the RDF triples for the cmeta:id

    CellMLSupport::CellmlFileRdfTriples rdfTriples = mParent->cellmlFile()->rdfTriples(pCmetaId);

    // Check that we are not dealing with the same RDF triples
    // Note: this may happen when manually typing the name of a cmeta:id and the
    //       QComboBox suggesting something for you, e.g. you start typing "C_"
    //       and the QComboBox suggests "C_C" (which will get us here) and then
    //       you finish typing "C_C" (which will also get us here)

    static CellMLSupport::CellmlFileRdfTriples oldRdfTriples = CellMLSupport::CellmlFileRdfTriples(mParent->cellmlFile());

    if (rdfTriples == oldRdfTriples)
        return;

    oldRdfTriples = rdfTriples;

    // 'Clean up' our web view

    mWebView->setUrl(QString());

    // Update its metadata details

    mMetadataViewDetails->updateGui(rdfTriples);
}

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

void CellmlAnnotationViewCellmlDetailsWidget::qualifierLookupRequested(const QString &pQualifier,
                                                                       const bool &pRetranslate)
{
    Q_UNUSED(pRetranslate);

    // The user requested a qualifier to be looked up, so generate a web page
    // containing some information about the qualifier
    // Note: ideally, there would be a way to refer to a particular qualifier
    //       using http://biomodels.net/qualifiers/, but that would require
    //       anchors and they don't have any, so instead we use the information
    //       which can be found on that site and present it to the user in the
    //       form of a web page...

    if (pQualifier.isEmpty())
        return;

    // Generate the web page containing some information about the qualifier

    QString qualifierSvg;
    QString shortDescription;
    QString longDescription;

    if (!pQualifier.compare("model:is")) {
        qualifierSvg = mModelQualifierSvg;

        shortDescription = tr("Identity");
        longDescription  = tr("The modelling object represented by the model element is identical with the subject of the referenced resource (\"Modelling Object B\"). For instance, this qualifier might be used to link an encoded model to a database of models.");
    } else if (!pQualifier.compare("model:isDerivedFrom")) {
        qualifierSvg = mModelQualifierSvg;

        shortDescription = tr("Origin");
        longDescription  = tr("The modelling object represented by the model element is derived from the modelling object represented by the referenced resource (\"Modelling Object B\"). This relation may be used, for instance, to express a refinement or adaptation in usage for a previously described modelling component.");
    } else if (!pQualifier.compare("model:isDescribedBy")) {
        qualifierSvg = mModelQualifierSvg;

        shortDescription = tr("Description");
        longDescription  = tr("The modelling object represented by the model element is described by the subject of the referenced resource (\"Modelling Object B\"). This relation might be used to link a model or a kinetic law to the literature that describes it.");
    } else if (!pQualifier.compare("bio:encodes")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Encodement");
        longDescription  = tr("The biological entity represented by the model element encodes, directly or transitively, the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to express, for example, that a specific DNA sequence encodes a particular protein.");
    } else if (!pQualifier.compare("bio:hasPart")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Part");
        longDescription  = tr("The biological entity represented by the model element includes the subject of the referenced resource (\"Biological Entity B\"), either physically or logically. This relation might be used to link a complex to the description of its components.");
    } else if (!pQualifier.compare("bio:hasProperty")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Property");
        longDescription  = tr("The subject of the referenced resource (\"Biological Entity B\") is a property of the biological entity represented by the model element. This relation might be used when a biological entity exhibits a certain enzymatic activity or exerts a specific function.");
    } else if (!pQualifier.compare("bio:hasVersion")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Version");
        longDescription  = tr("The subject of the referenced resource (\"Biological Entity B\") is a version or an instance of the biological entity represented by the model element. This relation may be used to represent an isoform or modified form of a biological entity.");
    } else if (!pQualifier.compare("bio:is")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Indentity");
        longDescription  = tr("The biological entity represented by the model element has identity with the subject of the referenced resource (\"Biological Entity B\"). This relation might be used to link a reaction to its exact counterpart in a database, for instance.");
    } else if (!pQualifier.compare("bio:isDescribedBy")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Description");
        longDescription  = tr("The biological entity represented by the model element is described by the subject of the referenced resource (\"Biological Entity B\"). This relation should be used, for instance, to link a species or a parameter to the literature that describes the concentration of that species or the value of that parameter.");
    } else if (!pQualifier.compare("bio:isEncodedBy")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Encoder");
        longDescription  = tr("The biological entity represented by the model element is encoded, directly or transitively, by the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to express, for example, that a protein is encoded by a specific DNA sequence.");
    } else if (!pQualifier.compare("bio:isHomologTo")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Homolog");
        longDescription  = tr("The biological entity represented by the model element is homologous to the subject of the referenced resource (\"Biological Entity B\"). This relation can be used to represent biological entities that share a common ancestor.");
    } else if (!pQualifier.compare("bio:isPartOf")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Parthood");
        longDescription  = tr("The biological entity represented by the model element is a physical or logical part of the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to link a model component to a description of the complex in which it is a part.");
    } else if (!pQualifier.compare("bio:isPropertyOf")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Property bearer");
        longDescription  = tr("The biological entity represented by the model element is a property of the referenced resource (\"Biological Entity B\").");
    } else if (!pQualifier.compare("bio:isVersionOf")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Hypernym");
        longDescription  = tr("The biological entity represented by the model element is a version or an instance of the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to represent, for example, the 'superclass' or 'parent' form of a particular biological entity.");
    } else if (!pQualifier.compare("bio:occursIn")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Container");
        longDescription  = tr("The biological entity represented by the model element is physically limited to a location, which is the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to ascribe a compartmental location, within which a reaction takes place.");
    } else if (!pQualifier.compare("bio:hasTaxon")) {
        qualifierSvg = mBiologyQualifierSvg;

        shortDescription = tr("Taxon");
        longDescription  = tr("The biological entity represented by the model element is taxonomically restricted, where the restriction is the subject of the referenced resource (\"Biological Entity B\"). This relation may be used to ascribe a species restriction to a biochemical reaction.");
    } else {
        qualifierSvg = "";

        shortDescription = tr("Unknown");
        longDescription  = tr("Unknown");
    }

    // Show the information

    mWebView->setHtml(mQualifierInformationTemplate.arg(pQualifier,
                                                        qualifierSvg,
                                                        shortDescription,
                                                        longDescription,
                                                        Core::copyright()));
}

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

void CellmlAnnotationViewCellmlDetailsWidget::resourceLookupRequested(const QString &pResource,
                                                                      const bool &pRetranslate)
{
    // The user requested a resource to be looked up, so retrieve it using
    // identifiers.org, but only if we are not retranslating since the looking
    // up would already be correct

    if (!pRetranslate)
        mWebView->setUrl("http://identifiers.org/"+pResource+"/?redirect=true");
        //---GRY--- NOTE THAT redirect=true DOESN'T WORK AT THE MOMENT, SO WE DO
        //          END UP WITH A FRAME, BUT THE identifiers.org GUYS ARE GOING
        //          TO 'FIX' THAT, SO WE SHOULD BE READY FOR WHEN IT'S DONE...
}

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

void CellmlAnnotationViewCellmlDetailsWidget::resourceIdLookupRequested(const QString &pResource,
                                                                        const QString &pId,
                                                                        const bool &pRetranslate)
{
    // The user requested a resource id to be looked up, so retrieve it using
    // identifiers.org, but only if we are not retranslating since the looking
    // up would already be correct

    if (!pRetranslate)
        mWebView->setUrl("http://identifiers.org/"+pResource+"/"+pId+"?profile=most_reliable&redirect=true");
}

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

void CellmlAnnotationViewCellmlDetailsWidget::metadataUpdated()
{
    // Some metadata has been updated, so we need to update the metadata
    // information we show to the user

    if (mCellmlElementDetails->cmetaIdValue())
        newCmetaId(mCellmlElementDetails->cmetaIdValue()->currentText());
}

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

}   // namespace CellMLAnnotationView
}   // namespace OpenCOR

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


<commit_before>#include "VXGI.h"
#include "BindIndexInfo.h"
#include "ShaderFactory.hpp"
#include "MainRenderer.h"

using namespace Device;
using namespace Core;
using namespace Rendering;
using namespace Rendering::Light;
using namespace Rendering::Shadow;
using namespace Rendering::Manager;
using namespace Rendering::Buffer;
using namespace Rendering::View;
using namespace Rendering::GI;
using namespace Rendering::Shader;
using namespace Rendering::Factory;
using namespace Rendering::Renderer;

void VXGI::InitializeClearVoxelMap(DirectX& dx, ShaderManager& shaderMgr, uint dimension)
{
	ShaderFactory factory(&shaderMgr);
	_clearVoxelMap = *factory.LoadComputeShader(dx, "ClearVoxelMap", "CS", nullptr, "@ClearVoxelMap");
}

void VXGI::ClearInjectColorVoxelMap(DirectX& dx)
{
	auto Clear = [&dx, &shader = _clearVoxelMap](UnorderedAccessView& uav, uint sideLength, bool isAnisotropic)
	{
		auto ComputeThreadGroupSideLength = [](uint sideLength)
		{
			return static_cast<uint>( static_cast<float>(sideLength + 8 - 1) / 8.0f );
		};

		ComputeShader::BindUnorderedAccessView(dx, UAVBindIndex(0), uav);

		uint yz = ComputeThreadGroupSideLength(sideLength);
		shader.Dispatch(dx, ComputeShader::ThreadGroup(ComputeThreadGroupSideLength(sideLength * (isAnisotropic ? (uint)VoxelMap::Direction::Num : 1)), yz, yz));
		ComputeShader::UnBindUnorderedAccessView(dx, UAVBindIndex(0));
	};

	Clear(_injectionSourceMap.GetSourceMapUAV(), _staticInfo.dimension, false);
	Clear(_mipmappedInjectionMap.GetSourceMapUAV(), _staticInfo.dimension / 2, true);
}

void VXGI::Initialize(DirectX& dx, ShaderManager& shaderMgr, const Size<uint>& renderSize, const VXGIStaticInfo&& info)
{
	// Setting Infos
	{
		_staticInfo = info;
		_infoCB.staticInfoCB.Initialize(dx);
		_infoCB.staticInfoCB.UpdateSubResource(dx, info);

		_infoCB.dynamicInfoCB.Initialize(dx);
		UpdateGIDynamicInfoCB(dx);
	}

	// Init Voxelization
	_voxelization.Initialize(dx, shaderMgr, _staticInfo.dimension, _staticInfo.voxelSize);

	// Injection
	{
		_injectionSourceMap.Initialize(dx, _staticInfo.dimension, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R32_UINT, 1, false);
		_mipmappedInjectionMap.Initialize(dx, _staticInfo.dimension / 2, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R32_UINT, uint(_staticInfo.maxMipLevel) - 1, true);

		_injectPointLight.Initialize(dx, shaderMgr, _staticInfo.dimension);
		_injectSpotLight.Initialize(dx, shaderMgr, _staticInfo.dimension);
	}

	// Mipmap
	_mipmap.Initialize(dx, shaderMgr);

	// Voxel Cone Tracing
	_voxelConeTracing.Initialize(dx, shaderMgr, renderSize);

	InitializeClearVoxelMap(dx, shaderMgr, _staticInfo.dimension);

	_indirectColorMap.Initialize(dx, renderSize, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, 0, 1);
}

void VXGI::Run(DirectX& dx, const VXGI::Param&& param)
{
	ClearInjectColorVoxelMap(dx);

	const auto& lightMgr		= param.lightMgr;
	const auto& tbrCB			= param.main.renderer.GetTBRParamCB();

	// 1. Voxelization Pass
	{
		// Clear Voxel Map and voxelize
		_voxelization.Voxelize(dx, _injectionSourceMap,
			Voxelization::Param{_dynamicInfo.startCenterWorldPos, _infoCB, lightMgr, param.shadowParam,
								tbrCB, param.cullParam, param.meshRenderParam, param.materialMgr}
		);
	}

	// 2. Injection Pass
	{
		InjectRadianceFormUtility::BindParam injParam{
			_infoCB, _voxelization, tbrCB, param.shadowParam.manager.GetGlobalCB()
		};

		if(lightMgr.GetLightCount<PointLight>() > 0)
			_injectPointLight.Inject(dx, _injectionSourceMap, lightMgr, param.shadowParam, injParam);

		if(lightMgr.GetLightCount<SpotLight>() > 0)
			_injectSpotLight.Inject(dx, _injectionSourceMap, lightMgr, param.shadowParam, injParam);
	}

	// 3. Mipmap Pass
	_mipmap.Mipmapping(dx, _injectionSourceMap, _mipmappedInjectionMap);

	// 4. Voxel Cone Tracing Pass
	_indirectColorMap.Clear(dx, Color::Clear());
	_voxelConeTracing.Run(dx, _indirectColorMap, {_injectionSourceMap, _mipmappedInjectionMap, _infoCB, param.main});
}

void VXGI::UpdateGIDynamicInfoCB(DirectX& dx)
{
	_infoCB.dynamicInfoCB.UpdateSubResource(dx, _dynamicInfo);
	_dirty = false;
}<commit_msg>VXGI - Clear할때 ComputeShader::Bind가 아닌 AutoBinder를 사용하도록 함<commit_after>#include "VXGI.h"
#include "BindIndexInfo.h"
#include "ShaderFactory.hpp"
#include "MainRenderer.h"
#include "AutoBinder.hpp"

using namespace Device;
using namespace Core;
using namespace Rendering;
using namespace Rendering::Light;
using namespace Rendering::Shadow;
using namespace Rendering::Manager;
using namespace Rendering::Buffer;
using namespace Rendering::View;
using namespace Rendering::GI;
using namespace Rendering::Shader;
using namespace Rendering::Factory;
using namespace Rendering::Renderer;

void VXGI::InitializeClearVoxelMap(DirectX& dx, ShaderManager& shaderMgr, uint dimension)
{
	ShaderFactory factory(&shaderMgr);
	_clearVoxelMap = *factory.LoadComputeShader(dx, "ClearVoxelMap", "CS", nullptr, "@ClearVoxelMap");
}

void VXGI::ClearInjectColorVoxelMap(DirectX& dx)
{
	auto Clear = [&dx, &shader = _clearVoxelMap](UnorderedAccessView& uav, uint sideLength, bool isAnisotropic)
	{
		auto ComputeThreadGroupSideLength = [](uint sideLength)
		{
			return static_cast<uint>( static_cast<float>(sideLength + 8 - 1) / 8.0f );
		};

		AutoBinderUAV outUAV(dx, UAVBindIndex(0), uav);
		uint yz = ComputeThreadGroupSideLength(sideLength);
		shader.Dispatch(dx, ComputeShader::ThreadGroup(ComputeThreadGroupSideLength(sideLength * (isAnisotropic ? (uint)VoxelMap::Direction::Num : 1)), yz, yz));
	};

	Clear(_injectionSourceMap.GetSourceMapUAV(), _staticInfo.dimension, false);
	Clear(_mipmappedInjectionMap.GetSourceMapUAV(), _staticInfo.dimension / 2, true);
}

void VXGI::Initialize(DirectX& dx, ShaderManager& shaderMgr, const Size<uint>& renderSize, const VXGIStaticInfo&& info)
{
	// Setting Infos
	{
		_staticInfo = info;
		_infoCB.staticInfoCB.Initialize(dx);
		_infoCB.staticInfoCB.UpdateSubResource(dx, info);

		_infoCB.dynamicInfoCB.Initialize(dx);
		UpdateGIDynamicInfoCB(dx);
	}

	// Init Voxelization
	_voxelization.Initialize(dx, shaderMgr, _staticInfo.dimension, _staticInfo.voxelSize);

	// Injection
	{
		_injectionSourceMap.Initialize(dx, _staticInfo.dimension, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R32_UINT, 1, false);
		_mipmappedInjectionMap.Initialize(dx, _staticInfo.dimension / 2, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R32_UINT, uint(_staticInfo.maxMipLevel) - 1, true);

		_injectPointLight.Initialize(dx, shaderMgr, _staticInfo.dimension);
		_injectSpotLight.Initialize(dx, shaderMgr, _staticInfo.dimension);
	}

	// Mipmap
	_mipmap.Initialize(dx, shaderMgr);

	// Voxel Cone Tracing
	_voxelConeTracing.Initialize(dx, shaderMgr, renderSize);

	InitializeClearVoxelMap(dx, shaderMgr, _staticInfo.dimension);

	_indirectColorMap.Initialize(dx, renderSize, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, 0, 1);
}

void VXGI::Run(DirectX& dx, const VXGI::Param&& param)
{
	ClearInjectColorVoxelMap(dx);

	const auto& lightMgr		= param.lightMgr;
	const auto& tbrCB			= param.main.renderer.GetTBRParamCB();

	// 1. Voxelization Pass
	{
		// Clear Voxel Map and voxelize
		_voxelization.Voxelize(dx, _injectionSourceMap,
			Voxelization::Param{_dynamicInfo.startCenterWorldPos, _infoCB, lightMgr, param.shadowParam,
								tbrCB, param.cullParam, param.meshRenderParam, param.materialMgr}
		);
	}

	// 2. Injection Pass
	{
		InjectRadianceFormUtility::BindParam injParam{
			_infoCB, _voxelization, tbrCB, param.shadowParam.manager.GetGlobalCB()
		};

		if(lightMgr.GetLightCount<PointLight>() > 0)
			_injectPointLight.Inject(dx, _injectionSourceMap, lightMgr, param.shadowParam, injParam);

		if(lightMgr.GetLightCount<SpotLight>() > 0)
			_injectSpotLight.Inject(dx, _injectionSourceMap, lightMgr, param.shadowParam, injParam);
	}

	// 3. Mipmap Pass
	_mipmap.Mipmapping(dx, _injectionSourceMap, _mipmappedInjectionMap);

	// 4. Voxel Cone Tracing Pass
	_indirectColorMap.Clear(dx, Color::Clear());
	_voxelConeTracing.Run(dx, _indirectColorMap, {_injectionSourceMap, _mipmappedInjectionMap, _infoCB, param.main});
}

void VXGI::UpdateGIDynamicInfoCB(DirectX& dx)
{
	_infoCB.dynamicInfoCB.UpdateSubResource(dx, _dynamicInfo);
	_dirty = false;
}<|endoftext|>


<commit_before>#ifndef __OPERANDS_HH__
#define __OPERANDS_HH__

#include <memory>
#include <stack>
#include <string>

#include "exprtoken.hh"

// fwd decl
namespace Evaluators
{
class Visitor;
} // namespace Evaluators

namespace Operands
{

typedef double NumericType;

class Operand: public ExpressionToken
{
public:
    typedef std::shared_ptr< Operand > Ptr;
};

/**
 * class Bool
 */
class Bool
   : public Operand
   , public std::enable_shared_from_this< Bool >
{
public:
    typedef std::shared_ptr< Bool > Ptr;

public:
    Bool(): iValue(0)
    {}

    Bool( bool aValue ): iValue( aValue )
    {}

public:
    bool getValue() const { return iValue; }
    void setValue( bool aValue ) { iValue = aValue; }

public:
    void accept( Evaluators::Visitor & );

private:
    bool iValue;
};

/**
 * class Numeric
 */
class Numeric
    : public Operand
    , public std::enable_shared_from_this< Numeric >
{
public:
    typedef std::shared_ptr< Numeric > Ptr;

public:
    Numeric(): iValue(0)
    {}

    Numeric( NumericType aValue ): iValue( aValue )
    {}

public:
    NumericType getValue() const { return iValue; }
    void setValue( NumericType aValue ) { iValue = aValue; }

public:
    void accept( Evaluators::Visitor & );

private:
    NumericType iValue;
};

/**
 * class Text
 */
class Text
    : public Operand
    , public std::enable_shared_from_this< Text >
{
public:
    typedef std::shared_ptr< Text > Ptr;

public:
    Text()
    {}

    Text( const std::string & aValue ): iValue( aValue )
    {}

public:
    const std::string & getValue() const { return iValue; }
    void setValue( const std::string & aValue ) { iValue = aValue; }

public:
    void accept( Evaluators::Visitor & );

private:
    std::string iValue;
};

typedef std::shared_ptr< Operand >       OperandPtr;
typedef std::shared_ptr< Bool >          BoolPtr;
typedef std::shared_ptr< Numeric >       NumericPtr;
typedef std::shared_ptr< Text >          TextPtr;

typedef std::stack< OperandPtr >              OperandsStack;

} // namespace Operands

#endif // __OPERANDS_HH__
<commit_msg>Class Variable added<commit_after>#ifndef __OPERANDS_HH__
#define __OPERANDS_HH__

#include <memory>
#include <stack>
#include <string>

#include "exprtoken.hh"

// fwd decl
namespace Evaluators
{
class Visitor;
} // namespace Evaluators

namespace Operands
{

typedef double NumericType;

class Operand: public ExpressionToken
{
public:
    typedef std::shared_ptr< Operand > Ptr;
};

/**
 * class Bool
 */
class Bool
   : public Operand
   , public std::enable_shared_from_this< Bool >
{
public:
    typedef std::shared_ptr< Bool > Ptr;

public:
    Bool(): iValue(0)
    {}

    Bool( bool aValue ): iValue( aValue )
    {}

public:
    bool getValue() const { return iValue; }
    void setValue( bool aValue ) { iValue = aValue; }

public:
    void accept( Evaluators::Visitor & );

private:
    bool iValue;
};

/**
 * class Numeric
 */
class Numeric
    : public Operand
    , public std::enable_shared_from_this< Numeric >
{
public:
    typedef std::shared_ptr< Numeric > Ptr;

public:
    Numeric(): iValue(0)
    {}

    Numeric( NumericType aValue ): iValue( aValue )
    {}

public:
    NumericType getValue() const { return iValue; }
    void setValue( NumericType aValue ) { iValue = aValue; }

public:
    void accept( Evaluators::Visitor & );

private:
    NumericType iValue;
};

/**
 * class Text
 */
class Text
    : public Operand
    , public std::enable_shared_from_this< Text >
{
public:
    typedef std::shared_ptr< Text > Ptr;

public:
    Text()
    {}

    Text( const std::string & aValue ): iValue( aValue )
    {}

public:
    const std::string & getValue() const { return iValue; }
    void setValue( const std::string & aValue ) { iValue = aValue; }

public:
    void accept( Evaluators::Visitor & );

private:
    std::string iValue;
};

/**
 * class Variable
 */
class Variable
    : public Operand
    , public std::enable_shared_from_this< Variable >
{
public:
    typedef std::shared_ptr< Variable > Ptr;
};

typedef std::shared_ptr< Operand >       OperandPtr;
typedef std::shared_ptr< Bool >          BoolPtr;
typedef std::shared_ptr< Numeric >       NumericPtr;
typedef std::shared_ptr< Text >          TextPtr;

typedef std::stack< OperandPtr >              OperandsStack;

} // namespace Operands

#endif // __OPERANDS_HH__
<|endoftext|>


<commit_before>// Copyright 2018 Global Phasing Ltd.

#define GEMMI_PROG na
#include "options.h"
#include <cstdio>   // for fprintf, fopen
#include <cstdlib>  // for strtol, strtod, exit
#include <cstring>  // for strcmp, strchr
#include <gemmi/fileutil.hpp>  // for expand_if_pdb_code, file_open_or
#include <gemmi/version.hpp>   // for GEMMI_VERSION
#include <gemmi/util.hpp>   // for trim_str
#include <gemmi/model.hpp>  // for gemmi::CoorFormat
#include <gemmi/atox.hpp>   // for skip_blank

using std::fprintf;

const option::Descriptor CommonUsage[] = {
  { 0, 0, 0, 0, 0, 0 }, // this makes CommonUsage[Help] return Help item, etc
  { Help, 0, "h", "help", Arg::None, "  -h, --help  \tPrint usage and exit." },
  { Version, 0, "V", "version", Arg::None,
    "  -V, --version  \tPrint version and exit." },
  { Verbose, 0, "v", "verbose", Arg::None,
    "  -v, --verbose  \tVerbose output." }
};

std::vector<int> parse_comma_separated_ints(const char* arg) {
  std::vector<int> result;
  char* endptr = nullptr;
  do {
    result.push_back(std::strtol(endptr ? endptr + 1 : arg, &endptr, 10));
  } while (*endptr == ',');
  if (*endptr != '\0')
    result.clear();
  return result;
}

option::ArgStatus Arg::Required(const option::Option& option, bool msg) {
  if (option.arg != nullptr)
    return option::ARG_OK;
  if (msg)
    fprintf(stderr, "Option '%s' requires an argument\n", option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Char(const option::Option& option, bool msg) {
  if (Required(option, msg) == option::ARG_ILLEGAL)
    return option::ARG_ILLEGAL;
  if (option.arg[0] != '\0' || option.arg[1] == '\0')
    return option::ARG_OK;
  if (msg)
    fprintf(stderr, "Argument of '%s' must be one character\n", option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Choice(const option::Option& option, bool msg,
                              std::vector<const char*> choices) {
  if (Required(option, msg) == option::ARG_ILLEGAL)
    return option::ARG_ILLEGAL;
  for (const char* a : choices)
    if (std::strcmp(option.arg, a) == 0)
      return option::ARG_OK;
  if (msg)
    // option.name here is a string "--option=arg"
    fprintf(stderr, "Invalid argument for %.*s: %s\n",
            option.namelen, option.name, option.arg);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::ColonPair(const option::Option& option, bool msg) {
  if (Required(option, msg) == option::ARG_ILLEGAL)
    return option::ARG_ILLEGAL;
  const char* sep = std::strchr(option.arg, ':');
  if (sep != nullptr && std::strchr(sep+1, ':') == nullptr)
    return option::ARG_OK;
  if (msg)
    fprintf(stderr, "Option '%.*s' requires two colon-separated names "
                    "as an argument,\n for example: %.*s=A:B\n",
                    option.namelen, option.name, option.namelen, option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Int(const option::Option& option, bool msg) {
  if (option.arg) {
    char* endptr = nullptr;
    std::strtol(option.arg, &endptr, 10);
    if (endptr != option.arg && *endptr == '\0')
      return option::ARG_OK;
  }
  if (msg)
    fprintf(stderr, "Option '%s' requires an integer argument\n", option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Int3(const option::Option& option, bool msg) {
  if (option.arg && parse_comma_separated_ints(option.arg).size() == 3)
    return option::ARG_OK;
  if (msg)
    fprintf(stderr, "Option '%.*s' requires three comma-separated integers "
                    "as an argument,\n for example: %.*s=11,12,13\n",
                    option.namelen, option.name, option.namelen, option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Float(const option::Option& option, bool msg) {
  if (option.arg) {
    char* endptr = nullptr;
    std::strtod(option.arg, &endptr);
    if (endptr != option.arg && *endptr == '\0')
      return option::ARG_OK;
  }
  if (msg)
    fprintf(stderr, "Option '%s' requires a numeric argument\n", option.name);
  return option::ARG_ILLEGAL;
}

// we wrap fwrite because passing it directly may cause warning
// "ignoring attributes on template argument" [-Wignored-attributes]
static
size_t write_func(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
  return fwrite(ptr, size, nmemb, stream);
}

void OptParser::simple_parse(int argc, char** argv,
                             const option::Descriptor usage[]) {
  if (argc < 1)
    std::exit(2);
  option::Stats stats(/*reordering*/true, usage, argc-1, argv+1);
  options.resize(stats.options_max);
  buffer.resize(stats.buffer_max);
  parse(usage, argc-1, argv+1, options.data(), buffer.data());
  if (error())
    std::exit(2);
  if (options[Help]) {
    option::printUsage(write_func, stdout, usage);
    std::exit(0);
  }
  if (options[Version]) {
    print_version(program_name);
    std::exit(0);
  }
  if (options[NoOp]) {
    fprintf(stderr, "Invalid option.\n");
    option::printUsage(write_func, stderr, usage);
    std::exit(2);
  }
}

void OptParser::check_exclusive_group(const std::vector<int>& group) {
  int first = -1;
  for (int opt : group)
    if (options[opt]) {
      if (first == -1)
        first = opt;
      else
        exit_exclusive(first, opt);
    }
}

void OptParser::print_try_help_and_exit(const char* msg) {
  fprintf(stderr, "%s\nTry '%s --help' for more information.\n",
                  msg, program_name);
  std::exit(2);
}

void OptParser::require_positional_args(int n) {
  if (nonOptionsCount() != n) {
    fprintf(stderr, "%s requires %d arguments but got %d.",
                    program_name, n, nonOptionsCount());
    print_try_help_and_exit("");
  }
}

void OptParser::require_input_files_as_args(int other_args) {
  if (nonOptionsCount() <= other_args)
    print_try_help_and_exit("No input files. Nothing to do.");
}

void OptParser::exit_exclusive(int opt1, int opt2) {
  std::fprintf(stderr, "Options -%s and -%s cannot be used together.\n",
               given_name(opt1), given_name(opt2));
  std::exit(1);
}

std::string OptParser::coordinate_input_file(int n, char pdb_code_type) {
  return gemmi::expand_if_pdb_code(nonOption(n), pdb_code_type);
}

bool starts_with_pdb_code(const std::string& s) {
  return (s.length() == 4 && gemmi::is_pdb_code(s)) ||
         (s.length() > 4 && std::strchr(" \t\r\n:,;|", s[4]) &&
          gemmi::is_pdb_code(s.substr(0, 4)));
}

std::vector<std::string>
OptParser::paths_from_args_or_file(int opt, int other) {
  std::vector<std::string> paths;
  const option::Option& file_option = options[opt];
  if (file_option) {
    if (nonOptionsCount() > other)
      print_try_help_and_exit("Error: File arguments together with option -f.");
    std::FILE *f = std::fopen(file_option.arg, "r");
    if (!f) {
      std::perror(file_option.arg);
      std::exit(2);
    }
    char buf[512];
    while (std::fgets(buf, 512, f)) {
      std::string s = gemmi::trim_str(buf);
      if (!s.empty())
        paths.emplace_back(s);
    }
    std::fclose(f);
  } else {
    require_input_files_as_args(other);
    for (int i = other; i < nonOptionsCount(); ++i)
      paths.emplace_back(nonOption(i));
  }
  return paths;
}

gemmi::CoorFormat coor_format_as_enum(const option::Option& format_in) {
  gemmi::CoorFormat format = gemmi::CoorFormat::Unknown;
  if (format_in) {
    if (strcmp(format_in.arg, "cif") == 0)
      format = gemmi::CoorFormat::Mmcif;
    else if (strcmp(format_in.arg, "pdb") == 0)
      format = gemmi::CoorFormat::Pdb;
    else if (strcmp(format_in.arg, "json") == 0)
      format = gemmi::CoorFormat::Mmjson;
    else if (strcmp(format_in.arg, "chemcomp") == 0)
      format = gemmi::CoorFormat::ChemComp;
  }
  return format;
}

void print_version(const char* program_name) {
  std::printf("%s " GEMMI_VERSION
#ifdef GEMMI_VERSION_INFO
         " (" GEMMI_XSTRINGIZE(GEMMI_VERSION_INFO) ")"
#endif
         "\n", program_name);
}

void read_spec_file(const char* path, std::vector<std::string>& output) {
  char buf[256];
  gemmi::fileptr_t f_spec = gemmi::file_open_or(path, "r", stdin);
  while (std::fgets(buf, sizeof(buf), f_spec.get()) != NULL) {
    const char* start = gemmi::skip_blank(buf);
    if (*start != '\0' && *start != '\r' && *start != '\n' && *start != '#')
      output.emplace_back(start);
  }
}
<commit_msg>src/options.cpp: print allowed options in Choice<commit_after>// Copyright 2018 Global Phasing Ltd.

#define GEMMI_PROG na
#include "options.h"
#include <cstdio>   // for fprintf, fopen
#include <cstdlib>  // for strtol, strtod, exit
#include <cstring>  // for strcmp, strchr
#include <gemmi/fileutil.hpp>  // for expand_if_pdb_code, file_open_or
#include <gemmi/version.hpp>   // for GEMMI_VERSION
#include <gemmi/util.hpp>   // for trim_str
#include <gemmi/model.hpp>  // for gemmi::CoorFormat
#include <gemmi/atox.hpp>   // for skip_blank

using std::fprintf;

const option::Descriptor CommonUsage[] = {
  { 0, 0, 0, 0, 0, 0 }, // this makes CommonUsage[Help] return Help item, etc
  { Help, 0, "h", "help", Arg::None, "  -h, --help  \tPrint usage and exit." },
  { Version, 0, "V", "version", Arg::None,
    "  -V, --version  \tPrint version and exit." },
  { Verbose, 0, "v", "verbose", Arg::None,
    "  -v, --verbose  \tVerbose output." }
};

std::vector<int> parse_comma_separated_ints(const char* arg) {
  std::vector<int> result;
  char* endptr = nullptr;
  do {
    result.push_back(std::strtol(endptr ? endptr + 1 : arg, &endptr, 10));
  } while (*endptr == ',');
  if (*endptr != '\0')
    result.clear();
  return result;
}

option::ArgStatus Arg::Required(const option::Option& option, bool msg) {
  if (option.arg != nullptr)
    return option::ARG_OK;
  if (msg)
    fprintf(stderr, "Option '%s' requires an argument\n", option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Char(const option::Option& option, bool msg) {
  if (Required(option, msg) == option::ARG_ILLEGAL)
    return option::ARG_ILLEGAL;
  if (option.arg[0] != '\0' || option.arg[1] == '\0')
    return option::ARG_OK;
  if (msg)
    fprintf(stderr, "Argument of '%s' must be one character\n", option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Choice(const option::Option& option, bool msg,
                              std::vector<const char*> choices) {
  if (Required(option, msg) == option::ARG_ILLEGAL)
    return option::ARG_ILLEGAL;
  for (const char* a : choices)
    if (std::strcmp(option.arg, a) == 0)
      return option::ARG_OK;
  if (msg) {
    // option.name here is a string "--option=arg"
    fprintf(stderr, "Invalid argument for %.*s: %s\nAllowed arguments:",
            option.namelen, option.name, option.arg);
    for (const char* a : choices)
      fprintf(stderr, " %s", a);
    fprintf(stderr, "\n");
  }
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::ColonPair(const option::Option& option, bool msg) {
  if (Required(option, msg) == option::ARG_ILLEGAL)
    return option::ARG_ILLEGAL;
  const char* sep = std::strchr(option.arg, ':');
  if (sep != nullptr && std::strchr(sep+1, ':') == nullptr)
    return option::ARG_OK;
  if (msg)
    fprintf(stderr, "Option '%.*s' requires two colon-separated names "
                    "as an argument,\n for example: %.*s=A:B\n",
                    option.namelen, option.name, option.namelen, option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Int(const option::Option& option, bool msg) {
  if (option.arg) {
    char* endptr = nullptr;
    std::strtol(option.arg, &endptr, 10);
    if (endptr != option.arg && *endptr == '\0')
      return option::ARG_OK;
  }
  if (msg)
    fprintf(stderr, "Option '%s' requires an integer argument\n", option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Int3(const option::Option& option, bool msg) {
  if (option.arg && parse_comma_separated_ints(option.arg).size() == 3)
    return option::ARG_OK;
  if (msg)
    fprintf(stderr, "Option '%.*s' requires three comma-separated integers "
                    "as an argument,\n for example: %.*s=11,12,13\n",
                    option.namelen, option.name, option.namelen, option.name);
  return option::ARG_ILLEGAL;
}

option::ArgStatus Arg::Float(const option::Option& option, bool msg) {
  if (option.arg) {
    char* endptr = nullptr;
    std::strtod(option.arg, &endptr);
    if (endptr != option.arg && *endptr == '\0')
      return option::ARG_OK;
  }
  if (msg)
    fprintf(stderr, "Option '%s' requires a numeric argument\n", option.name);
  return option::ARG_ILLEGAL;
}

// we wrap fwrite because passing it directly may cause warning
// "ignoring attributes on template argument" [-Wignored-attributes]
static
size_t write_func(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
  return fwrite(ptr, size, nmemb, stream);
}

void OptParser::simple_parse(int argc, char** argv,
                             const option::Descriptor usage[]) {
  if (argc < 1)
    std::exit(2);
  option::Stats stats(/*reordering*/true, usage, argc-1, argv+1);
  options.resize(stats.options_max);
  buffer.resize(stats.buffer_max);
  parse(usage, argc-1, argv+1, options.data(), buffer.data());
  if (error())
    std::exit(2);
  if (options[Help]) {
    option::printUsage(write_func, stdout, usage);
    std::exit(0);
  }
  if (options[Version]) {
    print_version(program_name);
    std::exit(0);
  }
  if (options[NoOp]) {
    fprintf(stderr, "Invalid option.\n");
    option::printUsage(write_func, stderr, usage);
    std::exit(2);
  }
}

void OptParser::check_exclusive_group(const std::vector<int>& group) {
  int first = -1;
  for (int opt : group)
    if (options[opt]) {
      if (first == -1)
        first = opt;
      else
        exit_exclusive(first, opt);
    }
}

void OptParser::print_try_help_and_exit(const char* msg) {
  fprintf(stderr, "%s\nTry '%s --help' for more information.\n",
                  msg, program_name);
  std::exit(2);
}

void OptParser::require_positional_args(int n) {
  if (nonOptionsCount() != n) {
    fprintf(stderr, "%s requires %d arguments but got %d.",
                    program_name, n, nonOptionsCount());
    print_try_help_and_exit("");
  }
}

void OptParser::require_input_files_as_args(int other_args) {
  if (nonOptionsCount() <= other_args)
    print_try_help_and_exit("No input files. Nothing to do.");
}

void OptParser::exit_exclusive(int opt1, int opt2) {
  std::fprintf(stderr, "Options -%s and -%s cannot be used together.\n",
               given_name(opt1), given_name(opt2));
  std::exit(1);
}

std::string OptParser::coordinate_input_file(int n, char pdb_code_type) {
  return gemmi::expand_if_pdb_code(nonOption(n), pdb_code_type);
}

bool starts_with_pdb_code(const std::string& s) {
  return (s.length() == 4 && gemmi::is_pdb_code(s)) ||
         (s.length() > 4 && std::strchr(" \t\r\n:,;|", s[4]) &&
          gemmi::is_pdb_code(s.substr(0, 4)));
}

std::vector<std::string>
OptParser::paths_from_args_or_file(int opt, int other) {
  std::vector<std::string> paths;
  const option::Option& file_option = options[opt];
  if (file_option) {
    if (nonOptionsCount() > other)
      print_try_help_and_exit("Error: File arguments together with option -f.");
    std::FILE *f = std::fopen(file_option.arg, "r");
    if (!f) {
      std::perror(file_option.arg);
      std::exit(2);
    }
    char buf[512];
    while (std::fgets(buf, 512, f)) {
      std::string s = gemmi::trim_str(buf);
      if (!s.empty())
        paths.emplace_back(s);
    }
    std::fclose(f);
  } else {
    require_input_files_as_args(other);
    for (int i = other; i < nonOptionsCount(); ++i)
      paths.emplace_back(nonOption(i));
  }
  return paths;
}

gemmi::CoorFormat coor_format_as_enum(const option::Option& format_in) {
  gemmi::CoorFormat format = gemmi::CoorFormat::Unknown;
  if (format_in) {
    if (strcmp(format_in.arg, "cif") == 0)
      format = gemmi::CoorFormat::Mmcif;
    else if (strcmp(format_in.arg, "pdb") == 0)
      format = gemmi::CoorFormat::Pdb;
    else if (strcmp(format_in.arg, "json") == 0)
      format = gemmi::CoorFormat::Mmjson;
    else if (strcmp(format_in.arg, "chemcomp") == 0)
      format = gemmi::CoorFormat::ChemComp;
  }
  return format;
}

void print_version(const char* program_name) {
  std::printf("%s " GEMMI_VERSION
#ifdef GEMMI_VERSION_INFO
         " (" GEMMI_XSTRINGIZE(GEMMI_VERSION_INFO) ")"
#endif
         "\n", program_name);
}

void read_spec_file(const char* path, std::vector<std::string>& output) {
  char buf[256];
  gemmi::fileptr_t f_spec = gemmi::file_open_or(path, "r", stdin);
  while (std::fgets(buf, sizeof(buf), f_spec.get()) != NULL) {
    const char* start = gemmi::skip_blank(buf);
    if (*start != '\0' && *start != '\r' && *start != '\n' && *start != '#')
      output.emplace_back(start);
  }
}
<|endoftext|>


<commit_before>//@author A0094446X
#include "stdafx.h"
#include "CppUnitTest.h"
#include "You-GUI\main_window.h"
#include "You-GUI\system_tray_manager.h"
#include "You-QueryEngine\api.h"
#include "You-GUI\task_panel_manager.h"

using Assert = Microsoft::VisualStudio::CppUnitTestFramework::Assert;
using Task = You::Controller::Task;
using TaskList = You::Controller::TaskList;
using Date = boost::gregorian::date;
namespace You {
namespace GUI {
namespace UnitTests {
QApplication *app;
// Simulate running the main() function
// Sets up the logging facility and the Qt event loop

TEST_MODULE_INITIALIZE(ModuleInitialize) {
	int argc = 1;
	char *argv[] = { "You.exe" };
	app = new QApplication(argc, argv);
}

// Cleans up what we set up
TEST_MODULE_CLEANUP(ModuleCleanup) {
	app->quit();
	delete app;
}

TEST_CLASS(MainWindowTests) {
public:
	TEST_METHOD(isMainWindowVisible) {
		MainWindow w;
		Assert::IsTrue(w.isVisible());
	}

	TEST_METHOD(isCentralWidgetVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.centralWidget->isVisible());
	}

	TEST_METHOD(isTaskPanelVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.taskTreePanel->isVisible());
	}

	TEST_METHOD(isCommandEnterButtonVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.commandEnterButton->isVisible());
	}

	TEST_METHOD(isCommandInputBoxVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.commandInputBox->isVisible());
	}

	TEST_METHOD(isStatusBarVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.statusBar->isVisible());
	}

	TEST_METHOD(isStatusIconVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.statusIcon->isVisible());
	}

	TEST_METHOD(isStatusMessageVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.statusMessage->isVisible());
	}

	TEST_METHOD(isMainToolBarHidden) {
		MainWindow w;
		Assert::IsFalse(w.ui.mainToolBar->isVisible());
	}

	TEST_METHOD(isMenuBarHidden) {
		MainWindow w;
		Assert::IsFalse(w.ui.menuBar->isVisible());
	}

	TEST_METHOD(addSingleTaskCount) {
		MainWindow w;
		w.clearTasks();
		w.ui.commandInputBox->setText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1);
	}

	TEST_METHOD(addSingleTaskContent) {
		MainWindow w;
		w.clearTasks();
		w.ui.commandInputBox->setText(QString("/add test by Nov 2099"));
		w.commandEnterPressed();
		QTreeWidgetItem item = *w.ui.taskTreePanel->topLevelItem(0);
		int column1 = QString::compare(item.text(1), QString("0"));
		int column2 = QString::compare(item.text(2), QString("test"));
		int column3 = QString::compare(
			item.text(3), QString("More than a month away (2099-Nov-01 00:00:00)"));
		int column4 = QString::compare(item.text(4), QString("Normal"));
		Assert::IsTrue((column1 == 0) && (column2 == 0) &&
			(column3 == 0) && (column4 == 0));
	}

	TEST_METHOD(testDueToday1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		Assert::IsTrue(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	TEST_METHOD(testDueToday2) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::hours(24) + boost::posix_time::minutes(1);
		Assert::IsFalse(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	TEST_METHOD(testDueToday3) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= (boost::posix_time::hours(24) + boost::posix_time::minutes(1));
		Assert::IsFalse(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	/// Test if is past due, 1 minute before
	TEST_METHOD(testPastDue1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= boost::posix_time::minutes(1);
		Assert::IsTrue(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, 1 day and 1 minute before
	TEST_METHOD(testPastDue2) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= (boost::posix_time::hours(24) + boost::posix_time::minutes(1));
		Assert::IsTrue(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, on the same time
	TEST_METHOD(testPastDue3) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		Assert::IsFalse(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, with deadline 1 minute after
	TEST_METHOD(testPastDue4) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::minutes(1);
		Assert::IsFalse(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	TEST_METHOD(deleteSingleTaskCount) {
		MainWindow w;
		w.clearTasks();
		w.ui.commandInputBox->setText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		w.ui.commandInputBox->setText(QString("/add test2 by Nov 20"));
		w.commandEnterPressed();
		w.ui.commandInputBox->setText(QString("/delete 1"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1);
	}

	TEST_METHOD(deleteSingleTaskFind) {
		MainWindow w;
		w.clearTasks();
		w.ui.commandInputBox->setText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		w.ui.commandInputBox->setText(QString("/add test2 by Nov 20"));
		w.commandEnterPressed();
		w.ui.commandInputBox->setText(QString("/delete 1"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->findItems(
			QString("1"), Qt::MatchExactly, 1).size() == 0);
	}
};
}  // namespace UnitTests
}  // namespace GUI
}  // namespace You
<commit_msg>Updated unit tests.<commit_after>//@author A0094446X
#include "stdafx.h"
#include "CppUnitTest.h"
#include "You-GUI\main_window.h"
#include "You-GUI\system_tray_manager.h"
#include "You-QueryEngine\api.h"
#include "You-GUI\task_panel_manager.h"

using Assert = Microsoft::VisualStudio::CppUnitTestFramework::Assert;
using Task = You::Controller::Task;
using TaskList = You::Controller::TaskList;
using Date = boost::gregorian::date;
namespace You {
namespace GUI {
namespace UnitTests {
QApplication *app;
// Simulate running the main() function
// Sets up the logging facility and the Qt event loop

TEST_MODULE_INITIALIZE(ModuleInitialize) {
	int argc = 1;
	char *argv[] = { "You.exe" };
	app = new QApplication(argc, argv);
}

// Cleans up what we set up
TEST_MODULE_CLEANUP(ModuleCleanup) {
	app->quit();
	delete app;
}

TEST_CLASS(MainWindowTests) {
public:
	TEST_METHOD(isMainWindowVisible) {
		MainWindow w;
		Assert::IsTrue(w.isVisible());
	}

	TEST_METHOD(isCentralWidgetVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.centralWidget->isVisible());
	}

	TEST_METHOD(isTaskPanelVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.taskTreePanel->isVisible());
	}

	TEST_METHOD(isCommandEnterButtonVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.commandEnterButton->isVisible());
	}

	TEST_METHOD(isCommandInputBoxVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.commandInputBox->isVisible());
	}

	TEST_METHOD(isStatusBarVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.statusBar->isVisible());
	}

	TEST_METHOD(isStatusIconVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.statusIcon->isVisible());
	}

	TEST_METHOD(isStatusMessageVisible) {
		MainWindow w;
		Assert::IsTrue(w.ui.statusMessage->isVisible());
	}

	TEST_METHOD(isMainToolBarHidden) {
		MainWindow w;
		Assert::IsFalse(w.ui.mainToolBar->isVisible());
	}

	TEST_METHOD(isMenuBarHidden) {
		MainWindow w;
		Assert::IsFalse(w.ui.menuBar->isVisible());
	}

	TEST_METHOD(addSingleTaskCount) {
		MainWindow w;
		w.clearTasks();
		w.ui.commandInputBox->setText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1);
	}

	TEST_METHOD(addSingleTaskContent) {
		MainWindow w;
		w.clearTasks();
		w.ui.commandInputBox->setText(QString("/add test by Nov 2099"));
		w.commandEnterPressed();
		QTreeWidgetItem item = *w.ui.taskTreePanel->topLevelItem(0);
		int column1 = QString::compare(item.text(1), QString("0"));
		int column2 = QString::compare(item.text(2), QString("test"));
		int column3 = QString::compare(
			item.text(3),
			QString("More than a month away (2099-Nov-01 00:00:00)"));
		int column4 = QString::compare(item.text(4), QString("Normal"));
		Assert::IsTrue((column1 == 0) && (column2 == 0) &&
			(column3 == 0) && (column4 == 0));
	}

	TEST_METHOD(testDueToday1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		Assert::IsTrue(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	TEST_METHOD(testDueToday2) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::hours(24) + boost::posix_time::minutes(1);
		Assert::IsFalse(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	TEST_METHOD(testDueToday3) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= (boost::posix_time::hours(24) + boost::posix_time::minutes(1));
		Assert::IsFalse(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	/// Test if is past due, 1 minute before
	TEST_METHOD(testPastDue1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= boost::posix_time::minutes(1);
		Assert::IsTrue(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, 1 day and 1 minute before
	TEST_METHOD(testPastDue2) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= (boost::posix_time::hours(24) + boost::posix_time::minutes(1));
		Assert::IsTrue(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, on the same time
	TEST_METHOD(testPastDue3) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		Assert::IsFalse(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, with deadline 1 minute after
	TEST_METHOD(testPastDue4) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::minutes(1);
		Assert::IsFalse(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	TEST_METHOD(deleteSingleTaskCount) {
		MainWindow w;
		w.clearTasks();
		w.ui.commandInputBox->setText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		w.ui.commandInputBox->setText(QString("/add test2 by Nov 20"));
		w.commandEnterPressed();
		w.ui.commandInputBox->setText(QString("/delete 1"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1);
	}

	TEST_METHOD(deleteSingleTaskFind) {
		MainWindow w;
		w.clearTasks();
		w.ui.commandInputBox->setText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		w.ui.commandInputBox->setText(QString("/add test2 by Nov 20"));
		w.commandEnterPressed();
		w.ui.commandInputBox->setText(QString("/delete 1"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->findItems(
			QString("1"), Qt::MatchExactly, 1).size() == 0);
	}
};
}  // namespace UnitTests
}  // namespace GUI
}  // namespace You
<|endoftext|>


<commit_before>#include "_mobs.hpp"
#include "_player.hpp"
#include <iostream>
#include <cstdlib>
#include <windows.h>

player battle(pplayer account);
player calcEXP(player account, classMob creature);
player levelUp(player account);
void death();

int main()
{
	std::string name;
	int option1;
	std::cout<<"Welcome, please enter your name\n";
	std::getline(std::cin, name);
	std::string location [4] = {"in a hole","in a cave","in the mountains","in a castle"};
	std::cout<<"\nWelcome"<<account.getName()<<" you find yourself "<<account.getArea()<<" and you're not sure how you got there\n";
	while (1)
	{
		std::this_thread::sleep_for(500);
		std::cout<<"Write 1 to walk forward, 2 to walk left and 3 to walk right \n";
		std::getline(std::cin, option1);
		if (option1 == 1)
		{
			std::this_thread::sleep_for(50*(option1));
			srand(time(NULL));
			if (rand()%3 == option1-1){
				account = battle(account);
			}
		}
		else{
			std::cout<<"ERROR \n\nPlease enter a number between 1 and 3. \n\n";
			std::cin.clear();
			std::cin.ignore();
		}
	}
	return 0;
}

player battle(plater account)
{
	std::string option;
	std::string location[4] = {"in a hole", "in a cave", "in the mountains", "in a castle"};
	std::string monsters[5][3] = {{"worm", "lizzard", "snake"},{"rat", "snake", "trolls"},{"Dragon", "Dragon", "Dragon"},{"Evil knight", "The Mad King", "Dark Prince"}};
	std::this_thread::sleep_for(20);
	int ranM = (rand()%3);
	int ranD = (rand()%5)+1;
	classMob monster(monsters[account.getLevel()-1][ranM],account.getLevel(),account.getArea(),ranD);
	std::cout<<"Suddenly you meet a "<<monster.getName()<<", prepare for battle!\n";
	std::this_thread::sleep_for(2000);
	do
	{
		std::cout<<"\n\n############################################# \n\n HP:"<<account.getHealth()<<"\n\n";
		std::cout<<monster.getName()<<"HP: "<<monster.getHealth()<<" Level: "<<monster.getLevel()<<"\n";
		std::cout<<"Select A for Attack or R for retreat"<<"\n";
		std::cin>>option;
		srand(time(NULL));
		if (option=="R" || option=="r")
		{
			if ((rand()%2) == 1){
				std::cout<<"retreat sucessfull"<<"/n";
				monster.setHealth(0);
			}
			else{
				std::cout<<"You try to run, but it failed. \nThemonster attacks. You lose 5 health. \n";
				account.setHealth(account.getHealth()-5);
				option = "A";
			}
		}
		if (option == "A" || option =="a")
		{
			int attack = rand()%(account.getDamage());
			srand(time(NULL));
			int mobAttack = rand()%(monster.getDamage());
			monster.setHealth(monster.getHealth()-attack);
			account.setHealth(account.getHealth()-mobAttack);
			std::cout<<"You attack the damage for "<<attack<<" damage.\n";
			std::this_thread::sleep_for(500);
			std::cout<<"The monster attacks for "<< mobAttack<<" damage\n";
			std::this_thread::sleep_for(500);
		}
	}
	while (monster.getHealth() > 0 && account.getHealth() > 0);
	std::cout<<"\n\n############################################# \n\n HP:"<<account.getHealth()<<"\n\n";
	std::cout<<monster.getName()<<"HP: "<<monster.getHealth()<<" Level: "<<monster.getLevel()<<"\n";
	if (account.getHealth() <= 0)
	{
		death();
		exit(0);
	}
	account = calcEXP(account,monster);
	return account;
}

void death()
{
	std::cout<< "You have died\n";
}

player calcEXP(player account, classMob monster)
{
	std::cout<<"#######\ncalculating EXP\n########\n";
	std::this_thread::sleep_for(500);
	account.setEXP(account.getEXP() + monster.getEXP());
	std::cout<<"EXP: " << account.getEXP()<<"/"<< account.getEXPReq()<<"\n";
	if (account.getEXP()>=account.getEXPReq())
	{
		levelUp(account);
	}
	return account;
}

player levelUp(player account)
{
	account.setLevel(account.getLevel()+1);
	account.setEXPReq();
	account.setMaxHealth();
	account.setHealth(account.getMaxHealth());
	std::cout<<"Level up! You are now level: "<<account.getLevel()<<"!\n";
	return account;
}

<commit_msg>Update main.cpp<commit_after>#include "_mobs.h"
#include "_player.h"
#include <iostream>
#include <cstdlib>
#include <windows.h>

player battle(pplayer account);
player calcEXP(player account, classMob creature);
player levelUp(player account);
void death();

int main()
{
	std::string name;
	int option1;
	std::cout<<"Welcome, please enter your name\n";
	std::getline(std::cin, name);
	std::string location [4] = {"in a hole","in a cave","in the mountains","in a castle"};
	std::cout<<"\nWelcome"<<account.getName()<<" you find yourself "<<account.getArea()<<" and you're not sure how you got there\n";
	while (1)
	{
		std::this_thread::sleep_for(500);
		std::cout<<"Write 1 to walk forward, 2 to walk left and 3 to walk right \n";
		std::getline(std::cin, option1);
		if (option1 == 1)
		{
			std::this_thread::sleep_for(50*(option1));
			srand(time(NULL));
			if (rand()%3 == option1-1){
				account = battle(account);
			}
		}
		else{
			std::cout<<"ERROR \n\nPlease enter a number between 1 and 3. \n\n";
			std::cin.clear();
			std::cin.ignore();
		}
	}
	return 0;
}

player battle(plater account)
{
	std::string option;
	std::string location[4] = {"in a hole", "in a cave", "in the mountains", "in a castle"};
	std::string monsters[5][3] = {{"worm", "lizzard", "snake"},{"rat", "snake", "trolls"},{"Dragon", "Dragon", "Dragon"},{"Evil knight", "The Mad King", "Dark Prince"}};
	std::this_thread::sleep_for(20);
	int ranM = (rand()%3);
	int ranD = (rand()%5)+1;
	classMob monster(monsters[account.getLevel()-1][ranM],account.getLevel(),account.getArea(),ranD);
	std::cout<<"Suddenly you meet a "<<monster.getName()<<", prepare for battle!\n";
	std::this_thread::sleep_for(2000);
	do
	{
		std::cout<<"\n\n############################################# \n\n HP:"<<account.getHealth()<<"\n\n";
		std::cout<<monster.getName()<<"HP: "<<monster.getHealth()<<" Level: "<<monster.getLevel()<<"\n";
		std::cout<<"Select A for Attack or R for retreat"<<"\n";
		std::cin>>option;
		srand(time(NULL));
		if (option=="R" || option=="r")
		{
			if ((rand()%2) == 1){
				std::cout<<"retreat sucessfull"<<"/n";
				monster.setHealth(0);
			}
			else{
				std::cout<<"You try to run, but it failed. \nThemonster attacks. You lose 5 health. \n";
				account.setHealth(account.getHealth()-5);
				option = "A";
			}
		}
		if (option == "A" || option =="a")
		{
			int attack = rand()%(account.getDamage());
			srand(time(NULL));
			int mobAttack = rand()%(monster.getDamage());
			monster.setHealth(monster.getHealth()-attack);
			account.setHealth(account.getHealth()-mobAttack);
			std::cout<<"You attack the damage for "<<attack<<" damage.\n";
			std::this_thread::sleep_for(500);
			std::cout<<"The monster attacks for "<< mobAttack<<" damage\n";
			std::this_thread::sleep_for(500);
		}
	}
	while (monster.getHealth() > 0 && account.getHealth() > 0);
	std::cout<<"\n\n############################################# \n\n HP:"<<account.getHealth()<<"\n\n";
	std::cout<<monster.getName()<<"HP: "<<monster.getHealth()<<" Level: "<<monster.getLevel()<<"\n";
	if (account.getHealth() <= 0)
	{
		death();
		exit(0);
	}
	account = calcEXP(account,monster);
	return account;
}

void death()
{
	std::cout<< "You have died\n";
}

player calcEXP(player account, classMob monster)
{
	std::cout<<"#######\ncalculating EXP\n########\n";
	std::this_thread::sleep_for(500);
	account.setEXP(account.getEXP() + monster.getEXP());
	std::cout<<"EXP: " << account.getEXP()<<"/"<< account.getEXPReq()<<"\n";
	if (account.getEXP()>=account.getEXPReq())
	{
		levelUp(account);
	}
	return account;
}

player levelUp(player account)
{
	account.setLevel(account.getLevel()+1);
	account.setEXPReq();
	account.setMaxHealth();
	account.setHealth(account.getMaxHealth());
	std::cout<<"Level up! You are now level: "<<account.getLevel()<<"!\n";
	return account;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <thread>
#include <string>
#include <map>
#include <vector>
#include <boost/program_options.hpp>

#include "time_helper.h"
#include "options.h"
#include "pipeline_data.h"
#include "array_prepare.h"
#include "benchmark.h"
#include "statistics.h"
#include "test.h"
#include "output.h"

using namespace std;
using namespace time_helper;
namespace output = benchmark_output;

int main(int argc, char* argv[])
{
	options opts = initialize_options(argc, argv);

	// benchmark map
	std::map<std::string, void(*)(pipeline_data& data)> benchmark_map;
	benchmark_map["bubble"] = benchmark_bubble;
	benchmark_map["insertion"] = benchmark_insertion;
	benchmark_map["selection"] = benchmark_selection;
	benchmark_map["merge"] = benchmark_merge;
	benchmark_map["count"] = benchmark_count;

	// checking if the user specified a valid algorithm for benchmarking
	auto benchmark = benchmark_map[opts.algorithm];
	if (benchmark == nullptr)
	{
		cerr << "No such algorithm: " << opts.algorithm << endl;
		return 1;
	}

	// prepairing pipeline
	vector<void(*)(pipeline_data& data)> pipeline;
	pipeline.push_back(prepare_array);
	pipeline.push_back(benchmark);
	pipeline.push_back(aggregate_statistics);

	if (opts.test)
		pipeline.push_back(test);

	// printing greeting according to output mode and adding appropriate output method to the pipeline
	if (opts.output == "hs")
	{
		pipeline.push_back(output::human_sparse);
		output::human_sparse_greetings(opts);
	}
	else if (opts.output == "hv")
	{
		pipeline.push_back(output::human_verbose);
		output::human_verbose_greetings(opts);
	}
	else if (opts.output == "m")
		pipeline.push_back(output::machine);
	else
	{
		cout << "Unknown output mode: " << opts.output << endl;
		exit(2);
	}

	// preparing pipeline data
	pipeline_data data{};
	data.array_size = opts.array_size;
	data.unsorted_array = new int[data.array_size];
	data.sorted_array = new int[data.array_size];
	data.iterations = opts.iterations;
	data.min_number = opts.arr_min_num;
	data.max_number = opts.arr_max_num;
	data.test = opts.test;

	// the pipeline itself
	for (unsigned int i = 0; i < opts.iterations; i++)
	{
		data.iteration = i;

		for (auto step : pipeline)
			step(data);
	}

	// presenting the report according to the set output tipe
	if (opts.output == "hs")
		output::human_sparse_report(data);
	else if (opts.output == "hv")
		output::human_verbose_report(data);

	// clearing data
	delete[] data.unsorted_array;
	delete[] data.sorted_array;
}<commit_msg>Replaced an exit in main by return.<commit_after>#include <iostream>
#include <iomanip>
#include <thread>
#include <string>
#include <map>
#include <vector>
#include <boost/program_options.hpp>

#include "time_helper.h"
#include "options.h"
#include "pipeline_data.h"
#include "array_prepare.h"
#include "benchmark.h"
#include "statistics.h"
#include "test.h"
#include "output.h"

using namespace std;
using namespace time_helper;
namespace output = benchmark_output;

int main(int argc, char* argv[])
{
	options opts = initialize_options(argc, argv);

	// benchmark map
	std::map<std::string, void(*)(pipeline_data& data)> benchmark_map;
	benchmark_map["bubble"] = benchmark_bubble;
	benchmark_map["insertion"] = benchmark_insertion;
	benchmark_map["selection"] = benchmark_selection;
	benchmark_map["merge"] = benchmark_merge;
	benchmark_map["count"] = benchmark_count;

	// checking if the user specified a valid algorithm for benchmarking
	auto benchmark = benchmark_map[opts.algorithm];
	if (benchmark == nullptr)
	{
		cerr << "No such algorithm: " << opts.algorithm << endl;
		return 1;
	}

	// prepairing pipeline
	vector<void(*)(pipeline_data& data)> pipeline;
	pipeline.push_back(prepare_array);
	pipeline.push_back(benchmark);
	pipeline.push_back(aggregate_statistics);

	if (opts.test)
		pipeline.push_back(test);

	// printing greeting according to output mode and adding appropriate output method to the pipeline
	if (opts.output == "hs")
	{
		pipeline.push_back(output::human_sparse);
		output::human_sparse_greetings(opts);
	}
	else if (opts.output == "hv")
	{
		pipeline.push_back(output::human_verbose);
		output::human_verbose_greetings(opts);
	}
	else if (opts.output == "m")
		pipeline.push_back(output::machine);
	else
	{
		cout << "Unknown output mode: " << opts.output << endl;
        return 2;
	}

	// preparing pipeline data
	pipeline_data data{};
	data.array_size = opts.array_size;
	data.unsorted_array = new int[data.array_size];
	data.sorted_array = new int[data.array_size];
	data.iterations = opts.iterations;
	data.min_number = opts.arr_min_num;
	data.max_number = opts.arr_max_num;
	data.test = opts.test;

	// the pipeline itself
	for (unsigned int i = 0; i < opts.iterations; i++)
	{
		data.iteration = i;

		for (auto step : pipeline)
			step(data);
	}

	// presenting the report according to the set output tipe
	if (opts.output == "hs")
		output::human_sparse_report(data);
	else if (opts.output == "hv")
		output::human_verbose_report(data);

	// clearing data
	delete[] data.unsorted_array;
	delete[] data.sorted_array;
}
<|endoftext|>


<commit_before>// main.cpp

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "metasorter.h"

#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>

void generate_skeleton_config();

using namespace std;
using namespace boost::filesystem;

int main(int argc, char* argv[])
{
	std::cout << "Metasort 1.4.5" << std::endl << std::endl;
	//std::cout << "Copyright 2013 Eric Griffin" << std::endl << std::endl;

	int err = 0;
	int ok_to_run = 0;
	int required_flags = 0;
	int config_num = 0;
	int input_file_process = 0;
	int input_file_num = 0;
	char input_file[255][255];
	char config_file[255][255];
	boost::property_tree::ptree pt[255];

	if (argc > 1)
	{
		for (int i = 1; i < argc; i++)
		{
			if (strcmp(argv[i], "-g") == 0 )
			{
				generate_skeleton_config();
				exit(0);
            }

			if (strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "/h") == 0)
			{
				std::cout << "Usage: metasort -c <config file> [-i <filename>] [-g]" << std::endl;
				std::cout << "-c <config file>  --  specify configuration file to run" << std::endl;
				std::cout << "-i <filename>  --  specify a single file to process (requires -c)" << std::endl;
				std::cout << "-g  --  create a skeleton configuration file in the current directory" << std::endl;
				exit(0);
            }

			if (i + 1 != argc)
			{
                if (strcmp(argv[i], "-c") == 0)
				{
                    strcpy(config_file[config_num], argv[i + 1]);
					config_num++;
					required_flags++;
                }
				if (strcmp(argv[i], "-i") == 0)
				{
					input_file_process = 1;
                    strcpy(input_file[input_file_num], argv[i + 1]);
					input_file_num++;
                }
			}
		}
		if(required_flags > 0)
		{
			ok_to_run = 1;
		}
	}

	if(ok_to_run)
	{
		for(int q = 0; q < config_num; q++)
		{
			boost::property_tree::info_parser::read_info(config_file[q], pt[q]);

			// check for folders entry
			optional<const boost::property_tree::ptree&> pt_check_existence;
			pt_check_existence = pt[q].get_child_optional("folders");

			if(input_file_process == 0)  // if processing folders from config
			{
				if(pt_check_existence)
				{
					BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt[q].get_child("folders"))
					{
						int recurse = 0;
						std::cout << "Searching Root Folder: " << v.first.data() << std::endl;
						if(strcmp(v.second.data().c_str(), "R") == 0)
						{
							recurse = 1;
						}
						metasorter sorter((char*)v.first.data(), pt[q]);
						sorter.traverse_directory(recurse);
						sorter.tp.wait();
					}
					std::cout << endl << "Finished." << std::endl;
				}
				else
				{
					cout << endl << "No folders defined in config file - aborting" << std::endl;
					exit(0);
				}
			}
			else  // processing files from argv[]
			{
				for(int input_file_counter = 0; input_file_counter < input_file_num; input_file_counter++)
				{
					metasorter sorter(input_file[input_file_counter], pt[q]);
					sorter.process_file();
				}
				std::cout << endl << "Finished." << std::endl;
			}
		}
	}
	else
	{
		std::cout << "Usage: metasort -c <config file> [-i <filename>] [-g]" << std::endl;
	}
	return err;
}

void generate_skeleton_config()
{
	boost::filesystem::path working_path_raw(boost::filesystem::current_path());
	std::string *config = new std::string();
	std::string *working_path = new std::string(working_path_raw.string().c_str());

	//change back-slashes to forward-slashes
	std::replace(working_path->begin(), working_path->end(), '\\', '/');

	config->append("folders\n{\n\t;\"");
	config->append(working_path->c_str());
	config->append("/\" R\n}\n\nextensions\n{\n");
	config->append("\t[REGEX].*");
	config->append("\n}\n\nconfig\n{\n");
	config->append("\tlogfile \"");
	config->append(working_path->c_str());
	config->append("/metasort.log\"");
	config->append("\n}\n\nrules\n{\n");
	config->append("\tRule1_list \"");
	config->append(working_path->c_str());
	config->append("/metasort_list.txt\"\n\t{\n");
	config->append("\t\tGeneral_0\n\t\t{\n");
	config->append("\t\t\tfile_size > 50\n\t\t}\n");
	config->append("\n\t}\n}\n");

	std::ofstream f;
	std::string *skeleton_config_file = new std::string(working_path_raw.string().c_str());
	skeleton_config_file->append("\\metasort_config.ini");
	std::cout << "Generating skeleton config file: " << skeleton_config_file->c_str() << std::endl;
    f.open(skeleton_config_file->c_str(), std::ios::out);
	f << config->c_str();
	f.close();
}
<commit_msg>portability fixes<commit_after>// main.cpp

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "metasorter.h"

#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>

void generate_skeleton_config();

using namespace std;
using namespace boost::filesystem;

int main(int argc, char* argv[])
{
	std::cout << "Metasort 1.4.5" << std::endl << std::endl;
	//std::cout << "Copyright 2013 Eric Griffin" << std::endl << std::endl;

	int err = 0;
	int ok_to_run = 0;
	int required_flags = 0;
	int config_num = 0;
	int input_file_process = 0;
	int input_file_num = 0;
	char input_file[255][255];
	char config_file[255][255];
	boost::property_tree::ptree pt[255];

	if (argc > 1)
	{
		for (int i = 1; i < argc; i++)
		{
			if (strcmp(argv[i], "-g") == 0 )
			{
				generate_skeleton_config();
				exit(0);
            }

			if (strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "/h") == 0)
			{
				std::cout << "Usage: metasort -c <config file> [-i <filename>] [-g]" << std::endl;
				std::cout << "-c <config file>  --  specify configuration file to run" << std::endl;
				std::cout << "-i <filename>  --  specify a single file to process (requires -c)" << std::endl;
				std::cout << "-g  --  create a skeleton configuration file in the current directory" << std::endl << std::endl;
				exit(0);
            }

			if (i + 1 != argc)
			{
                if (strcmp(argv[i], "-c") == 0)
				{
                    strcpy(config_file[config_num], argv[i + 1]);
					config_num++;
					required_flags++;
                }
				if (strcmp(argv[i], "-i") == 0)
				{
					input_file_process = 1;
                    strcpy(input_file[input_file_num], argv[i + 1]);
					input_file_num++;
                }
			}
		}
		if(required_flags > 0)
		{
			ok_to_run = 1;
		}
	}

	if(ok_to_run)
	{
		for(int q = 0; q < config_num; q++)
		{
			boost::property_tree::info_parser::read_info(config_file[q], pt[q]);

			// check for folders entry
			optional<const boost::property_tree::ptree&> pt_check_existence;
			pt_check_existence = pt[q].get_child_optional("folders");

			if(input_file_process == 0)  // if processing folders from config
			{
				if(pt_check_existence)
				{
					BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt[q].get_child("folders"))
					{
						int recurse = 0;
						std::cout << "Searching Root Folder: " << v.first.data() << std::endl;
						if(strcmp(v.second.data().c_str(), "R") == 0)
						{
							recurse = 1;
						}
						metasorter sorter((char*)v.first.data(), pt[q]);
						sorter.traverse_directory(recurse);
						sorter.tp.wait();
					}
					std::cout << endl << "Finished." << std::endl;
				}
				else
				{
					cout << endl << "No folders defined in config file - aborting" << std::endl;
					exit(0);
				}
			}
			else  // processing files from argv[]
			{
				for(int input_file_counter = 0; input_file_counter < input_file_num; input_file_counter++)
				{
					metasorter sorter(input_file[input_file_counter], pt[q]);
					sorter.process_file();
				}
				std::cout << endl << "Finished." << std::endl;
			}
		}
	}
	else
	{
		std::cout << "Usage: metasort -c <config file> [-i <filename>] [-g]" << std::endl << std::endl;
	}
	return err;
}

void generate_skeleton_config()
{
	boost::filesystem::path working_path_raw(boost::filesystem::current_path());
	std::string *config = new std::string();
	std::string *working_path = new std::string(working_path_raw.string().c_str());

	//change back-slashes to forward-slashes
	std::replace(working_path->begin(), working_path->end(), '\\', '/');

	config->append("folders\n{\n\t;\"");
	config->append(working_path->c_str());
	config->append("/\" R\n}\n\nextensions\n{\n");
	config->append("\t[REGEX].*");
	config->append("\n}\n\nconfig\n{\n");
	config->append("\tlogfile \"");
	config->append(working_path->c_str());
	config->append("/metasort.log\"");
	config->append("\n}\n\nrules\n{\n");
	config->append("\tRule1_list \"");
	config->append(working_path->c_str());
	config->append("/metasort_list.txt\"\n\t{\n");
	config->append("\t\tGeneral_0\n\t\t{\n");
	config->append("\t\t\tfile_size > 50\n\t\t}\n");
	config->append("\n\t}\n}\n");

	std::ofstream f;
	std::string *skeleton_config_file = new std::string(working_path_raw.string().c_str());
	skeleton_config_file->append("/metasort_config.ini");
	std::cout << "Generating skeleton config file: " << skeleton_config_file->c_str() << std::endl << std::endl;
    f.open(skeleton_config_file->c_str(), std::ios::out);
	f << config->c_str();
	f.close();
}
<|endoftext|>