<commit_before>//==============================================================================
// Single cell simulation view widget
//==============================================================================

#include "cellmlfilemanager.h"
#include "cellmlfileruntime.h"
#include "coredaesolver.h"
#include "coreodesolver.h"
#include "coreutils.h"
#include "singlecellsimulationviewgraphpanel.h"
#include "singlecellsimulationviewgraphpanels.h"
#include "singlecellsimulationviewwidget.h"
#include "toolbar.h"

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

#include "ui_singlecellsimulationviewwidget.h"

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

#include <QDesktopWidget>
#include <QFileInfo>
#include <QProgressBar>
#include <QSettings>
#include <QSplitter>
#include <QTextEdit>
#include <QTime>

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

#include "qwt_plot.h"
#include "qwt_plot_curve.h"

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

namespace OpenCOR {
namespace SingleCellSimulationView {

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

SingleCellSimulationViewWidget::SingleCellSimulationViewWidget(QWidget *pParent) :
    Widget(pParent),
    mUi(new Ui::SingleCellSimulationViewWidget),
    mCellmlFileRuntime(0), mModel(Unknown),
    mStatesCount(0), mCondVarCount(0),
    mConstants(0), mRates(0), mStates(0), mAlgebraic(0), mCondVar(0),
    mVoiEnd(0), mVoiStep(0), mVoiMaximumStep(0), mVoiOutput(0), mStatesIndex(0),
    mOdeSolverName("CVODE"),
    mSlowPlotting(true),
    mSolverInterfaces(SolverInterfaces()),
    mSolverErrorMsg(QString())
{
    // Set up the UI

    mUi->setupUi(this);

    // Create a toolbar with different buttons

    Core::ToolBar *toolbar = new Core::ToolBar(this);

    toolbar->addAction(mUi->actionRun);
    toolbar->addAction(mUi->actionStop);
    toolbar->addSeparator();
    toolbar->addAction(mUi->actionDebugMode);
    toolbar->addSeparator();
    toolbar->addAction(mUi->actionAdd);
    toolbar->addAction(mUi->actionRemove);
    toolbar->addSeparator();
    toolbar->addAction(mUi->actionCsvExport);

    mUi->verticalLayout->addWidget(toolbar);
    mUi->verticalLayout->addWidget(Core::newLineWidget(this));

    // Create our vertical splitter

    mVerticalSplitter = new QSplitter(Qt::Vertical, this);

    // Create a splitter for our graph panels and create a connection to keep
    // track of whether we can remove graph panels

    mGraphPanels = new SingleCellSimulationViewGraphPanels(this);

    mGraphPanels->setObjectName("GraphPanels");

    connect(mGraphPanels, SIGNAL(removeGraphPanelsEnabled(const bool &)),
            mUi->actionRemove, SLOT(setEnabled(bool)));

    // Create a simulation output widget with a vertical layout on which we put
    // a separating line and our simulation output list view
    // Note: the separating line is because we remove, for aesthetical reasons,
    //       the border of our simulation output list view...

    QWidget *simulationOutputWidget = new QWidget(this);
    QVBoxLayout *simulationOutputVerticalLayout= new QVBoxLayout(simulationOutputWidget);

    simulationOutputVerticalLayout->setContentsMargins(0, 0, 0, 0);
    simulationOutputVerticalLayout->setSpacing(0);

    simulationOutputWidget->setLayout(simulationOutputVerticalLayout);

    mOutput = new QTextEdit(this);

    mOutput->setFrameStyle(QFrame::NoFrame);

    simulationOutputVerticalLayout->addWidget(Core::newLineWidget(this));
    simulationOutputVerticalLayout->addWidget(mOutput);

    // Populate our vertical splitter and use as much space as possible for the
    // graph panels (by asking their height to be that of the desktop's), and
    // add it to our single cell simulation view widget
    // Note: we add some spacing before our vertical splitter to match the space
    //       that exists between the graph panels and the simulation output
    //       widget. So, yes, it's purely about aesthetic...

    mVerticalSplitter->addWidget(mGraphPanels);
    mVerticalSplitter->addWidget(simulationOutputWidget);

    mVerticalSplitter->setSizes(QList<int>() << qApp->desktop()->screenGeometry().height() << 1);

    mUi->verticalLayout->addSpacing(mVerticalSplitter->handleWidth());
    mUi->verticalLayout->addWidget(mVerticalSplitter);

    // Create our (thin) simulation progress widget

    mProgressBar = new QProgressBar(this);

    mProgressBar->setAlignment(Qt::AlignCenter);
    mProgressBar->setFixedHeight(3);
    mProgressBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    mProgressBar->setTextVisible(false);

    setProgressBarStyleSheet();

    mUi->verticalLayout->addWidget(Core::newLineWidget(this));
    mUi->verticalLayout->addWidget(mProgressBar);
}

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

SingleCellSimulationViewWidget::~SingleCellSimulationViewWidget()
{
    // Delete the arrays for our model

    delete[] mConstants;
    delete[] mRates;
    delete[] mStates;
    delete[] mAlgebraic;
    delete[] mCondVar;

    // Delete the UI

    delete mUi;
}

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

void SingleCellSimulationViewWidget::retranslateUi()
{
    // Retranslate the whole view

    mUi->retranslateUi(this);
}

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

static const QString SettingsVerticalSplitterSizesCount = "GraphPanelsSizesCount";
static const QString SettingsVerticalSplitterSize       = "GraphPanelsSize%1";

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

void SingleCellSimulationViewWidget::loadSettings(QSettings *pSettings)
{
    foreach (SolverInterface *solverInterface, mSolverInterfaces) {
        qDebug("---------------------------------------");
        qDebug("'%s' solver:", qPrintable(solverInterface->name()));
        qDebug(" - Type: %s", (solverInterface->type() == Solver::Ode)?"ODE":"DAE");

        Solver::Properties properties = solverInterface->properties();

        if (properties.count()) {
            qDebug(" - Properties:");

            Solver::Properties::const_iterator iter = properties.constBegin();
            Solver::Properties::const_iterator iterEnd = properties.constEnd();

            while (iter != iterEnd) {
                QString type;

                switch (iter.value()) {
                case Solver::Double:
                    type = "Double";

                    break;
                case Solver::Integer:
                    type = "Integer";

                    break;
                default:
                    type = "???";
                }

                qDebug("    - %s: %s", qPrintable(iter.key()), qPrintable(type));

                ++iter;
            }
        } else {
            qDebug(" - Properties: none");
        }
    }



    // Retrieve and set the sizes of our vertical splitter

    int sizesCount = pSettings->value(SettingsVerticalSplitterSizesCount, 0).toInt();

    if (sizesCount) {
        QList<int> sizes = QList<int>();

        for (int i = 0; i < sizesCount; ++i)
            sizes << pSettings->value(SettingsVerticalSplitterSize.arg(QString::number(i))).toInt();

        mVerticalSplitter->setSizes(sizes);
    }

    // Retrieve the settings of our graph panels widget

    pSettings->beginGroup(mGraphPanels->objectName());
        mGraphPanels->loadSettings(pSettings);
    pSettings->endGroup();
}

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

void SingleCellSimulationViewWidget::saveSettings(QSettings *pSettings) const
{
    // Keep track of our vertical splitter sizes

    QList<int> sizes = mVerticalSplitter->sizes();

    pSettings->setValue(SettingsVerticalSplitterSizesCount, sizes.count());

    for (int i = 0, iMax = sizes.count(); i < iMax; ++i)
        pSettings->setValue(SettingsVerticalSplitterSize.arg(QString::number(i)), sizes.at(i));

    // Keep track of the settings of our graph panels widget

    pSettings->beginGroup(mGraphPanels->objectName());
        mGraphPanels->saveSettings(pSettings);
    pSettings->endGroup();
}

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

void SingleCellSimulationViewWidget::addSolverInterface(SolverInterface *pSolverInterface)
{
    // Add the solver interface to our list

    if (!mSolverInterfaces.contains(pSolverInterface))
        // The solver interface is not yet in our list, so...

        mSolverInterfaces.append(pSolverInterface);
}<commit_msg>Addressed the height issue of the graph panels in the SingleCellSimulation plugin. Closes #89.<commit_after>//==============================================================================
// Single cell simulation view widget
//==============================================================================

#include "cellmlfilemanager.h"
#include "cellmlfileruntime.h"
#include "coredaesolver.h"
#include "coreodesolver.h"
#include "coreutils.h"
#include "singlecellsimulationviewgraphpanel.h"
#include "singlecellsimulationviewgraphpanels.h"
#include "singlecellsimulationviewwidget.h"
#include "toolbar.h"

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

#include "ui_singlecellsimulationviewwidget.h"

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

#include <QDesktopWidget>
#include <QFileInfo>
#include <QProgressBar>
#include <QSettings>
#include <QSplitter>
#include <QTextEdit>
#include <QTime>

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

#include "qwt_plot.h"
#include "qwt_plot_curve.h"

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

namespace OpenCOR {
namespace SingleCellSimulationView {

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

SingleCellSimulationViewWidget::SingleCellSimulationViewWidget(QWidget *pParent) :
    Widget(pParent),
    mUi(new Ui::SingleCellSimulationViewWidget),
    mCellmlFileRuntime(0), mModel(Unknown),
    mStatesCount(0), mCondVarCount(0),
    mConstants(0), mRates(0), mStates(0), mAlgebraic(0), mCondVar(0),
    mVoiEnd(0), mVoiStep(0), mVoiMaximumStep(0), mVoiOutput(0), mStatesIndex(0),
    mOdeSolverName("CVODE"),
    mSlowPlotting(true),
    mSolverInterfaces(SolverInterfaces()),
    mSolverErrorMsg(QString())
{
    // Set up the UI

    mUi->setupUi(this);

    // Create a toolbar with different buttons

    Core::ToolBar *toolbar = new Core::ToolBar(this);

    toolbar->addAction(mUi->actionRun);
    toolbar->addAction(mUi->actionStop);
    toolbar->addSeparator();
    toolbar->addAction(mUi->actionDebugMode);
    toolbar->addSeparator();
    toolbar->addAction(mUi->actionAdd);
    toolbar->addAction(mUi->actionRemove);
    toolbar->addSeparator();
    toolbar->addAction(mUi->actionCsvExport);

    mUi->verticalLayout->addWidget(toolbar);
    mUi->verticalLayout->addWidget(Core::newLineWidget(this));

    // Create our vertical splitter

    mVerticalSplitter = new QSplitter(Qt::Vertical, this);

    // Create a splitter for our graph panels and create a connection to keep
    // track of whether we can remove graph panels

    mGraphPanels = new SingleCellSimulationViewGraphPanels(this);

    mGraphPanels->setObjectName("GraphPanels");

    connect(mGraphPanels, SIGNAL(removeGraphPanelsEnabled(const bool &)),
            mUi->actionRemove, SLOT(setEnabled(bool)));

    // Create a simulation output widget with a vertical layout on which we put
    // a separating line and our simulation output list view
    // Note: the separating line is because we remove, for aesthetical reasons,
    //       the border of our simulation output list view...

    QWidget *simulationOutputWidget = new QWidget(this);
    QVBoxLayout *simulationOutputVerticalLayout= new QVBoxLayout(simulationOutputWidget);

    simulationOutputVerticalLayout->setContentsMargins(0, 0, 0, 0);
    simulationOutputVerticalLayout->setSpacing(0);

    simulationOutputWidget->setLayout(simulationOutputVerticalLayout);

    mOutput = new QTextEdit(this);

    mOutput->setFrameStyle(QFrame::NoFrame);

    simulationOutputVerticalLayout->addWidget(Core::newLineWidget(this));
    simulationOutputVerticalLayout->addWidget(mOutput);

    // Populate our vertical splitter and use as much space as possible for the
    // graph panels (by asking their height to be that of the desktop's), and
    // add it to our single cell simulation view widget
    // Note: we add some spacing before our vertical splitter to match the space
    //       that exists between the graph panels and the simulation output
    //       widget. So, yes, it's purely about aesthetic...

    mVerticalSplitter->addWidget(mGraphPanels);
    mVerticalSplitter->addWidget(simulationOutputWidget);

    mVerticalSplitter->setSizes(QList<int>() << qApp->desktop()->screenGeometry().height() << 1);

    mUi->verticalLayout->addSpacing(mVerticalSplitter->handleWidth());
    mUi->verticalLayout->addWidget(mVerticalSplitter);

    // Create our (thin) simulation progress widget

    mProgressBar = new QProgressBar(this);

    mProgressBar->setAlignment(Qt::AlignCenter);
    mProgressBar->setFixedHeight(3);
    mProgressBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    mProgressBar->setTextVisible(false);

    setProgressBarStyleSheet();

    mUi->verticalLayout->addWidget(Core::newLineWidget(this));
    mUi->verticalLayout->addWidget(mProgressBar);
}

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

SingleCellSimulationViewWidget::~SingleCellSimulationViewWidget()
{
    // Delete the arrays for our model

    delete[] mConstants;
    delete[] mRates;
    delete[] mStates;
    delete[] mAlgebraic;
    delete[] mCondVar;

    // Delete the UI

    delete mUi;
}

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

void SingleCellSimulationViewWidget::retranslateUi()
{
    // Retranslate the whole view

    mUi->retranslateUi(this);
}

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

static const QString SettingsVerticalSplitterSizesCount = "GraphPanelsSizesCount";
static const QString SettingsVerticalSplitterSize       = "GraphPanelsSize%1";

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

void SingleCellSimulationViewWidget::loadSettings(QSettings *pSettings)
{
    foreach (SolverInterface *solverInterface, mSolverInterfaces) {
        qDebug("---------------------------------------");
        qDebug("'%s' solver:", qPrintable(solverInterface->name()));
        qDebug(" - Type: %s", (solverInterface->type() == Solver::Ode)?"ODE":"DAE");

        Solver::Properties properties = solverInterface->properties();

        if (properties.count()) {
            qDebug(" - Properties:");

            Solver::Properties::const_iterator iter = properties.constBegin();
            Solver::Properties::const_iterator iterEnd = properties.constEnd();

            while (iter != iterEnd) {
                QString type;

                switch (iter.value()) {
                case Solver::Double:
                    type = "Double";

                    break;
                case Solver::Integer:
                    type = "Integer";

                    break;
                default:
                    type = "???";
                }

                qDebug("    - %s: %s", qPrintable(iter.key()), qPrintable(type));

                ++iter;
            }
        } else {
            qDebug(" - Properties: none");
        }
    }



    // Retrieve and set the sizes of our vertical splitter

    int sizesCount = pSettings->value(SettingsVerticalSplitterSizesCount, 0).toInt();

    if (sizesCount) {
        QList<int> sizes = QList<int>();

        for (int i = 0; i < sizesCount; ++i)
            sizes << pSettings->value(SettingsVerticalSplitterSize.arg(QString::number(i))).toInt();

        mVerticalSplitter->setSizes(sizes);
    }

    // Retrieve the settings of our graph panels widget

    pSettings->beginGroup(mGraphPanels->objectName());
        mGraphPanels->loadSettings(pSettings);
    pSettings->endGroup();
}

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

void SingleCellSimulationViewWidget::saveSettings(QSettings *pSettings) const
{
    // Keep track of our vertical splitter sizes

    QList<int> sizes = mVerticalSplitter->sizes();

    if (!sizes.count() || !sizes.first())
        // Either we have no vertical splitter sizes (how could this ever be the
        // case?!) or our first vertical splitter size has a value of zero
        // (which would mean that we previously left OpenCOR without going into
        // Simulation mode and the vertical splitter sizes are not meaningful),
        // so...

        return;

    pSettings->setValue(SettingsVerticalSplitterSizesCount, sizes.count());

    for (int i = 0, iMax = sizes.count(); i < iMax; ++i)
        pSettings->setValue(SettingsVerticalSplitterSize.arg(QString::number(i)), sizes.at(i));

    // Keep track of the settings of our graph panels widget

    pSettings->beginGroup(mGraphPanels->objectName());
        mGraphPanels->saveSettings(pSettings);
    pSettings->endGroup();
}

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

void SingleCellSimulationViewWidget::addSolverInterface(SolverInterface *pSolverInterface)
{
    // Add the solver interface to our list

    if (!mSolverInterfaces.contains(pSolverInterface))
        // The solver interface is not yet in our list, so...

        mSolverInterfaces.append(pSolverInterface);
}
{'fraction_non_alphanumeric': 0.2205454951933825, 'fraction_numerical': 0.002794545048066175, 'mean_word_length': 3.981347438752784, 'pattern_counts': {'":': 2, '<': 41, '<?xml version=': 0, '>': 153, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5455885', 'n_tokens_mistral': 4824, 'n_tokens_neox': 4532, 'n_words': 1032}