SingleCellSimulationViewInformationSimulationWidget::SingleCellSimulationViewInformationSimulationWidget(QWidget *pParent) :
    PropertyEditorWidget(true, pParent),
    mGuiStates(QMap<QString, Core::PropertyEditorWidgetGuiState *>())
{
    // Populate our property editor

    mStartingPointProperty = addDoubleProperty(true, false);
    mEndingPointProperty   = addDoubleProperty(true, false);
    mPointIntervalProperty = addDoubleProperty(true, false);

    // Initialise our property values

    setDoublePropertyItem(mStartingPointProperty->value(), 0.0);
    setDoublePropertyItem(mEndingPointProperty->value(), 1000.0);
    setDoublePropertyItem(mPointIntervalProperty->value(), 1.0);

    // Some further initialisations which are done as part of retranslating the
    // GUI (so that they can be updated when changing languages)

    retranslateUi();

    // Retrieve our default GUI state

    mDefaultGuiState = guiState();
}
void InstrumentWidgetMaskTab::setProperties() {
  clearProperties();
  m_userEditing = false;

  // bounding rect property
  QtProperty *boundingRectGroup = m_groupManager->addProperty("Bounding Rect");
  m_browser->addProperty(boundingRectGroup);
  m_left = addDoubleProperty("left");
  m_top = addDoubleProperty("top");
  m_right = addDoubleProperty("right");
  m_bottom = addDoubleProperty("bottom");
  boundingRectGroup->addSubProperty(m_left);
  boundingRectGroup->addSubProperty(m_top);
  boundingRectGroup->addSubProperty(m_right);
  boundingRectGroup->addSubProperty(m_bottom);

  // point properties
  QStringList pointProperties =
      m_instrWidget->getSurface()->getCurrentPointNames();
  foreach (QString name, pointProperties) {
    QtProperty *point = m_groupManager->addProperty(name);
    QtProperty *prop_x = addDoubleProperty("x");
    QtProperty *prop_y = addDoubleProperty("y");
    point->addSubProperty(prop_x);
    point->addSubProperty(prop_y);
    m_browser->addProperty(point);
    m_pointComponentsMap[prop_x] = name;
    m_pointComponentsMap[prop_y] = name;
    m_pointPropertyMap[name] = point;
  }
 foreach (QString name, doubleProperties) {
   QtProperty *prop = addDoubleProperty(name);
   m_browser->addProperty(prop);
   m_doublePropertyMap[prop] = name;
 }
void SimulationExperimentViewInformationParametersWidget::populateModel(CellMLSupport::CellmlFileRuntime *pRuntime)
{
    // Populate our property editor with the parameters

    QString componentHierarchy = QString();
    Core::Property *sectionProperty = nullptr;

    for (auto parameter : pRuntime->parameters()) {
        // Check whether the current parameter is in the same component
        // hierarchy as the previous one

        QString crtComponentHierarchy = parameter->formattedComponentHierarchy();

        if (crtComponentHierarchy != componentHierarchy) {
            // The current parameter is in a different component hierarchy, so
            // create a new section hierarchy for our 'new' component, reusing
            // existing sections, whenever possible

            Core::Property *parentSectionProperty = nullptr;

            for (const auto &component : parameter->componentHierarchy()) {
                // Check whether we already have a section for our current
                // component

                sectionProperty = nullptr;

                if (parentSectionProperty != nullptr) {
                    // We have a parent section, so go through its children and
                    // retrieve the one for our current component

                    for (auto object : parentSectionProperty->children()) {
                        auto property = qobject_cast<Core::Property *>(object);

                        if (   (property != nullptr)
                            && (property->type() == Core::Property::Type::Section)
                            && (property->name() == component)) {
                            sectionProperty = property;

                            break;
                        }
                    }
                } else {
                    // We don't have a parent section, so go through our
                    // properties and retrieve the one for our current component

                    for (auto property : properties()) {
                        if (   (property->type() == Core::Property::Type::Section)
                            && (property->name() == component)) {
                            sectionProperty = property;

                            break;
                        }
                    }
                }

                // Create a new section for our current component, if none could
                // be found

                if (sectionProperty == nullptr) {
                    sectionProperty = addSectionProperty(component, parentSectionProperty);
                }

                // Get ready for the next component in our component hierarchy

                parentSectionProperty = sectionProperty;
            }

            // Keep track of the new component hierarchy

            componentHierarchy = crtComponentHierarchy;
        }

        // Add the current parameter to the current section property, after
        // having retrieved its current value

        double propertyValue = 0.0;
        CellMLSupport::CellmlFileRuntimeParameter::Type parameterType = parameter->type();

        if (parameterType == CellMLSupport::CellmlFileRuntimeParameter::Type::Voi) {
            propertyValue = mSimulation->data()->startingPoint();
        } else if (   (parameterType == CellMLSupport::CellmlFileRuntimeParameter::Type::Constant)
                   || (parameterType == CellMLSupport::CellmlFileRuntimeParameter::Type::ComputedConstant)) {
            propertyValue = mSimulation->data()->constants()[parameter->index()];
        } else if (parameterType == CellMLSupport::CellmlFileRuntimeParameter::Type::Rate) {
            propertyValue = mSimulation->data()->rates()[parameter->index()];
        } else if (parameterType == CellMLSupport::CellmlFileRuntimeParameter::Type::State) {
            propertyValue = mSimulation->data()->states()[parameter->index()];
        } else if (parameterType == CellMLSupport::CellmlFileRuntimeParameter::Type::Algebraic) {
            propertyValue = mSimulation->data()->algebraic()[parameter->index()];
        }

        Core::Property *property = addDoubleProperty(propertyValue, sectionProperty);

        property->setEditable(   (parameter->type() == CellMLSupport::CellmlFileRuntimeParameter::Type::Constant)
                              || (parameter->type() == CellMLSupport::CellmlFileRuntimeParameter::Type::State));
        property->setIcon(CellMLSupport::CellmlFileRuntimeParameter::icon(parameter->type()));
        property->setName(parameter->formattedName(), false);
        property->setUnit(parameter->formattedUnit(pRuntime->voi()->unit()), false);

        // Keep track of the link between our property value and parameter

        mParameters.insert(property, parameter);
    }

    // Update (well, set here) the extra info of all our parameters

    updateExtraInfos();

    // Expand all our properties

    expandAll();
}
void SimulationExperimentViewInformationParametersWidget::importData(DataStore::DataStoreImportData *pImportData)
{
    // Create our general import "component", if needed

    if (mImportComponent == nullptr) {
        mImportComponent = addSectionProperty("imports");
    }

    // Create our import "sub-component"

    Core::Property *importSubComponent = addSectionProperty(pImportData->hierarchy().last(), mImportComponent);

    // Add the given data to our model

    CellMLSupport::CellmlFileRuntimeParameters parameters = mSimulation->runtime()->dataParameters(mSimulation->data()->data(pImportData->importDataStore()));

    for (auto parameter : parameters) {
        Core::Property *property = addDoubleProperty(importSubComponent);

        property->setEditable(false);
        property->setIcon(CellMLSupport::CellmlFileRuntimeParameter::icon(parameter->type()));
        property->setName(parameter->formattedName(), false);

        // Keep track of the link between our property value and parameter

        mParameters.insert(property, parameter);
    }

    // Update (well, set for our imported data) the extra info of all our
    // properties

    updateExtraInfos();

    // Expand our import component and sub-component

    expand(mImportComponent->index());
    expand(importSubComponent->index());

    // Create our general import menu, if needed

    if (mImportMenu == nullptr) {
        mImportMenu = new QMenu("imports", mPlotAgainstMenu);

        mPlotAgainstMenu->addMenu(mImportMenu);
    }

    // Create our import sub-menu

    auto importSubMenu = new QMenu(pImportData->hierarchy().last(), mImportMenu);

    mImportMenu->addMenu(importSubMenu);

    // Populate our import sub-menu with the given data

    for (auto parameter : parameters) {
        QAction *parameterAction = importSubMenu->addAction(CellMLSupport::CellmlFileRuntimeParameter::icon(parameter->type()),
                                                            parameter->formattedName());

        // Create a connection to handle the graph requirement against our
        // parameter

        connect(parameterAction, &QAction::triggered,
                this, &SimulationExperimentViewInformationParametersWidget::emitGraphRequired);

        // Keep track of the parameter associated with our parameter action

        mParameterActions.insert(parameterAction, parameter);
    }
}
SimulationExperimentViewInformationSolversWidgetData * SimulationExperimentViewInformationSolversWidget::addSolverProperties(Solver::Type pSolverType)
{
    // Retrieve the name of the solvers which type is the one in which we are
    // interested

    QMap<QString, SolverInterface *> solversInterfaces = QMap<QString, SolverInterface *>();
    Core::Property *solversProperty = nullptr;
    Core::Property *solversListProperty = nullptr;
    QStringList solversNames = QStringList();
    QMap<QString, Core::Properties> solversProperties = QMap<QString, Core::Properties>();

    for (auto solverInterface : Core::solverInterfaces()) {
        if (solverInterface->solverType() == pSolverType) {
            // Keep track of the solver's interface

            solversInterfaces.insert(solverInterface->solverName(), solverInterface);

            // Keep track of the solver's name

            solversNames << solverInterface->solverName();

            // Add our solvers section property and list property for our
            // solvers, if needed

            if (solversProperty == nullptr) {
                solversProperty = addSectionProperty();

                solversListProperty = addListProperty(solversProperty);
            }

            // Add the solver's properties

            Core::Property *property = nullptr;
            Core::Properties properties = Core::Properties();

            for (const auto &solverInterfaceProperty : solverInterface->solverProperties()) {
                // Add the solver's property and set its default value

                switch (solverInterfaceProperty.type()) {
                case Solver::Property::Type::Boolean:
                    property = addBooleanProperty(solverInterfaceProperty.defaultValue().toBool(),
                                                  solversProperty);

                    break;
                case Solver::Property::Type::Integer:
                    property = addIntegerProperty(solverInterfaceProperty.defaultValue().toInt(),
                                                  solversProperty);

                    break;
                case Solver::Property::Type::IntegerGe0:
                    property = addIntegerGe0Property(solverInterfaceProperty.defaultValue().toInt(),
                                                     solversProperty);

                    break;
                case Solver::Property::Type::IntegerGt0:
                    property = addIntegerGt0Property(solverInterfaceProperty.defaultValue().toInt(),
                                                     solversProperty);

                    break;
                case Solver::Property::Type::Double:
                    property = addDoubleProperty(solverInterfaceProperty.defaultValue().toDouble(),
                                                 solversProperty);

                    break;
                case Solver::Property::Type::DoubleGe0:
                    property = addDoubleGe0Property(solverInterfaceProperty.defaultValue().toDouble(),
                                                    solversProperty);

                    break;
                case Solver::Property::Type::DoubleGt0:
                    property = addDoubleGt0Property(solverInterfaceProperty.defaultValue().toDouble(),
                                                    solversProperty);

                    break;
                case Solver::Property::Type::List:
                    property = addListProperty(solverInterfaceProperty.listValues(),
                                               solverInterfaceProperty.defaultValue().toString(),
                                               solversProperty);

                    break;
                }

                property->setId(solverInterfaceProperty.id());

                // Set the solver's property's 'unit', if needed

                if (solverInterfaceProperty.hasVoiUnit()) {
                    property->setUnit("???");
                    // Note: to assign a non-empty string to our unit item is
                    //       just a way for us to make sure that the property's
                    //       will get initialised (see setPropertiesUnit())...
                }

                // Keep track of the solver's property

                properties << property;

                // Keep track of the solver's property's descriptions

                mDescriptions.insert(property, solverInterfaceProperty.descriptions());
            }

            // Keep track of the solver's properties

            solversProperties.insert(solverInterface->solverName(), properties);
        }
    }

    // Check whether we have at least one solver

    if (solversListProperty != nullptr) {
        // We have a solvers list property, which means that we have at least
        // one solver, so sort our list

        solversNames.sort(Qt::CaseInsensitive);

        // Assign the list of solvers to our list property

        solversListProperty->setListValues(solversNames);

        // Create and return our solver data

        return new SimulationExperimentViewInformationSolversWidgetData(solversInterfaces,
                                                                        solversProperty,
                                                                        solversListProperty,
                                                                        solversProperties);
    }

    return nullptr;
}