Ejemplo n.º 1
0
void
ProjectSerialization::initialize(const Project* project)
{
    ///All the code in this function is MT-safe

    _nodes.initialize(*project);

    project->getAdditionalFormats(&_additionalFormats);

    std::vector< KnobIPtr > knobs = project->getKnobs_mt_safe();
    for (U32 i = 0; i < knobs.size(); ++i) {
        KnobGroupPtr isGroup = toKnobGroup(knobs[i]);
        KnobPagePtr isPage = toKnobPage(knobs[i]);
        KnobButtonPtr isButton = toKnobButton(knobs[i]);
        if ( knobs[i]->getIsPersistant() &&
             !isGroup && !isPage && !isButton &&
             knobs[i]->hasModificationsForSerialization() ) {
            KnobSerializationPtr newKnobSer( new KnobSerialization(knobs[i]) );
            _projectKnobs.push_back(newKnobSer);
        }
    }

    _timelineCurrent = project->currentFrame();

    _creationDate = project->getProjectCreationTime();
}
Ejemplo n.º 2
0
RestoreDefaultsCommand::RestoreDefaultsCommand(const std::list<KnobIPtr > & knobs,
                                               DimSpec targetDim,
                                               ViewSetSpec targetView,
                                               QUndoCommand *parent)
: QUndoCommand(parent)
, _targetDim(targetDim)
, _targetView(targetView)
, _knobs()
{
    setText( tr("Restore Default Value(s)") );


    for (std::list<KnobIPtr >::const_iterator it = knobs.begin(); it != knobs.end(); ++it) {
        KnobButtonPtr isButton = toKnobButton(*it);
        KnobPagePtr isPage = toKnobPage(*it);
        KnobSeparatorPtr isSep = toKnobSeparator(*it);
        if (isSep || isPage || (isButton && !isButton->getIsCheckable())) {
            continue;
        }

        SERIALIZATION_NAMESPACE::KnobSerializationPtr s(new SERIALIZATION_NAMESPACE::KnobSerialization());
        (*it)->toSerialization(s.get());
        _serializations.push_back(s);
        _knobs.push_back(*it);

    }
}
Ejemplo n.º 3
0
void
PythonPanelSerialization::initialize(NATRON_PYTHON_NAMESPACE::PyPanel* tab,
                                     const std::string& func)
{
    name = tab->getLabel();
    pythonFunction = func;
    std::list<NATRON_PYTHON_NAMESPACE::Param*> parameters = tab->getParams();
    for (std::list<NATRON_PYTHON_NAMESPACE::Param*>::iterator it = parameters.begin(); it != parameters.end(); ++it) {
        KnobIPtr knob = (*it)->getInternalKnob();
        KnobGroupPtr isGroup = toKnobGroup(knob);
        KnobPagePtr isPage = toKnobPage(knob);
        KnobButtonPtr isButton = toKnobButton(knob);
        //KnobChoicePtr isChoice = toKnobChoice(knob);

        if (!isGroup && !isPage && !isButton) {
            KnobSerializationPtr k( new KnobSerialization(knob) );
            knobs.push_back(k);
        }
        delete *it;
    }

    userData = tab->save_serialization_thread().toStdString();
}
Ejemplo n.º 4
0
NATRON_NAMESPACE_ENTER


// those parameters should be ignored (they are always secret in Natron)
#define kOCIOParamInputSpace "ocioInputSpace"
#define kOCIOParamOutputSpace "ocioOutputSpace"

// those parameters should not have their options in the help file if generating markdown,
// because the options are dinamlically constructed at run-time from the OCIO config.
#define kOCIOParamInputSpaceChoice "ocioInputSpaceIndex"
#define kOCIOParamOutputSpaceChoice "ocioOutputSpaceIndex"

#define kOCIODisplayPluginIdentifier "fr.inria.openfx.OCIODisplay"
#define kOCIODisplayParamDisplay "display"
#define kOCIODisplayParamDisplayChoice "displayIndex"
#define kOCIODisplayParamView "view"
#define kOCIODisplayParamViewChoice "viewIndex"

// not yet implemented (see OCIOCDLTransform.cpp)
//#define kOCIOCDLTransformPluginIdentifier "fr.inria.openfx.OCIOCDLTransform"
//#define kOCIOCDLTransformParamCCCID "cccId"
//#define kOCIOCDLTransformParamCCCIDChoice "cccIdIndex"

#define kOCIOFileTransformPluginIdentifier "fr.inria.openfx.OCIOFileTransform"
#define kOCIOFileTransformParamCCCID "cccId"
#define kOCIOFileTransformParamCCCIDChoice "cccIdIndex"

// genHTML: true for live HTML output for the internal web-server, false for markdown output
QString
Node::makeDocumentation(bool genHTML) const
{
    QString ret;
    QString markdown;
    QTextStream ts(&ret);
    QTextStream ms(&markdown);

    QString pluginID, pluginLabel, pluginDescription, pluginIcon;
    int majorVersion = getMajorVersion();
    int minorVersion = getMinorVersion();
    std::vector<std::string> pluginGroup;
    bool pluginDescriptionIsMarkdown = false;
    QVector<QStringList> inputs;
    QVector<QStringList> items;

    {
        PluginPtr plugin = getPlugin();
        assert(plugin);

        pluginID = QString::fromUtf8(plugin->getPluginID().c_str());
        pluginLabel =  QString::fromUtf8( Plugin::makeLabelWithoutSuffix( plugin->getPluginLabel() ).c_str());
        pluginDescription =  QString::fromUtf8( plugin->getPropertyUnsafe<std::string>(kNatronPluginPropDescription).c_str() );
        pluginIcon = QString::fromUtf8(plugin->getPropertyUnsafe<std::string>(kNatronPluginPropIconFilePath).c_str());
        pluginGroup = plugin->getPropertyNUnsafe<std::string>(kNatronPluginPropGrouping);
        pluginDescriptionIsMarkdown = plugin->getPropertyUnsafe<bool>(kNatronPluginPropDescriptionIsMarkdown);


        for (int i = 0; i < _imp->effect->getNInputs(); ++i) {
            QStringList input;
            input << convertFromPlainTextToMarkdown( QString::fromStdString( getInputLabel(i) ), genHTML, true );
            input << convertFromPlainTextToMarkdown( QString::fromStdString( getInputHint(i) ), genHTML, true );
            input << ( isInputOptional(i) ? tr("Yes") : tr("No") );
            inputs.push_back(input);

            // Don't show more than doc for 4 inputs otherwise it will just clutter the page
            if (i == 3) {
                break;
            }
        }
    }

    // check for plugin icon
    QString pluginIconUrl;
    if ( !pluginIcon.isEmpty() ) {
        QFile iconFile(pluginIcon);
        if ( iconFile.exists() ) {
            if (genHTML) {
                pluginIconUrl.append( QString::fromUtf8("/LOCAL_FILE/") );
                pluginIconUrl.append(pluginIcon);
                pluginIconUrl.replace( QString::fromUtf8("\\"), QString::fromUtf8("/") );
            } else {
                pluginIconUrl.append(pluginID);
                pluginIconUrl.append(QString::fromUtf8(".png"));
            }
        }
    }

    // check for extra markdown file
    QString extraMarkdown;
    QString pluginMD = pluginIcon;
    pluginMD.replace( QString::fromUtf8(".png"), QString::fromUtf8(".md") );
    QFile pluginMarkdownFile(pluginMD);
    if ( pluginMarkdownFile.exists() ) {
        if ( pluginMarkdownFile.open(QIODevice::ReadOnly | QIODevice::Text) ) {
            extraMarkdown = QString::fromUtf8( pluginMarkdownFile.readAll() );
            pluginMarkdownFile.close();
        }
    }

    // generate knobs info
    KnobsVec knobs = getEffectInstance()->getKnobs_mt_safe();
    for (KnobsVec::const_iterator it = knobs.begin(); it != knobs.end(); ++it) {

#pragma message WARN("TODO: restore getDefaultIsSecret from RB-2.2")
        //if ( (*it)->getDefaultIsSecret() ) {
        if ( (*it)->getIsSecret() ) {
            continue;
        }

        if ((*it)->getKnobDeclarationType() != KnobI::eKnobDeclarationTypePlugin) {
            continue;
        }

        // do not escape characters in the scriptName, since it will be put between backquotes
        QString knobScriptName = /*NATRON_NAMESPACE::convertFromPlainTextToMarkdown(*/ QString::fromUtf8( (*it)->getName().c_str() )/*, genHTML, true)*/;
        QString knobLabel = NATRON_NAMESPACE::convertFromPlainTextToMarkdown( QString::fromUtf8( (*it)->getLabel().c_str() ), genHTML, true);
        QString knobHint = NATRON_NAMESPACE::convertFromPlainTextToMarkdown( QString::fromUtf8( (*it)->getHintToolTip().c_str() ), genHTML, true);

        // totally ignore the documentation for these parameters (which are always secret in Natron)
        if ( knobScriptName.startsWith( QString::fromUtf8("NatronOfxParam") ) ||
             knobScriptName == QString::fromUtf8("exportAsPyPlug") ||
             knobScriptName == QString::fromUtf8(kOCIOParamInputSpace) ||
             knobScriptName == QString::fromUtf8(kOCIOParamOutputSpace) ||
             ( ( pluginID == QString::fromUtf8(kOCIODisplayPluginIdentifier) ) &&
               ( knobScriptName == QString::fromUtf8(kOCIODisplayParamDisplay) ) ) ||
             ( ( pluginID == QString::fromUtf8(kOCIODisplayPluginIdentifier) ) &&
               ( knobScriptName == QString::fromUtf8(kOCIODisplayParamView) ) ) ||
             //( ( pluginID == QString::fromUtf8(kOCIOCDLTransformPluginIdentifier) ) &&
             //  ( knobScriptName == QString::fromUtf8(kOCIOCDLTransformParamCCCID) ) ) ||
             ( ( pluginID == QString::fromUtf8(kOCIOFileTransformPluginIdentifier) ) &&
               ( knobScriptName == QString::fromUtf8(kOCIOFileTransformParamCCCID) ) ) ||
             false) {
            continue;
        }

        QString defValuesStr, knobType;
        std::vector<std::pair<QString, QString> > dimsDefaultValueStr;
        KnobIntPtr isInt = toKnobInt(*it);
        KnobChoicePtr isChoice = toKnobChoice(*it);
        KnobBoolPtr isBool = toKnobBool(*it);
        KnobDoublePtr isDbl = toKnobDouble(*it);
        KnobStringPtr isString = toKnobString(*it);
        bool isLabel = isString && isString->isLabel();
        KnobSeparatorPtr isSep = toKnobSeparator(*it);
        KnobButtonPtr isBtn = toKnobButton(*it);
        KnobParametricPtr isParametric = toKnobParametric(*it);
        KnobGroupPtr isGroup = toKnobGroup(*it);
        KnobPagePtr isPage = toKnobPage(*it);
        KnobColorPtr isColor = toKnobColor(*it);

        if (isInt) {
            knobType = tr("Integer");
        } else if (isChoice) {
            knobType = tr("Choice");
        } else if (isBool) {
            knobType = tr("Boolean");
        } else if (isDbl) {
            knobType = tr("Double");
        } else if (isString) {
            if (isLabel) {
                knobType = tr("Label");
            } else {
                knobType = tr("String");
            }
        } else if (isSep) {
            knobType = tr("Separator");
        } else if (isBtn) {
            knobType = tr("Button");
        } else if (isParametric) {
            knobType = tr("Parametric");
        } else if (isGroup) {
            knobType = tr("Group");
        } else if (isPage) {
            knobType = tr("Page");
        } else if (isColor) {
            knobType = tr("Color");
        } else {
            knobType = tr("N/A");
        }

        if (!isGroup && !isPage) {
            for (int i = 0; i < (*it)->getNDimensions(); ++i) {
                QString valueStr;

                if (!isBtn && !isSep && !isParametric) {
                    // If this is a ChoiceParam and we are not generating live HTML doc,
                    // only add the list of entries and their halp if this node should not be
                    // ignored (eg. OCIO colorspace knobs).
                    if ( isChoice &&
                         (genHTML || !( knobScriptName == QString::fromUtf8(kOCIOParamInputSpaceChoice) ||
                                        knobScriptName == QString::fromUtf8(kOCIOParamOutputSpaceChoice) ||
                                        ( ( pluginID == QString::fromUtf8(kOCIODisplayPluginIdentifier) ) &&
                                          ( knobScriptName == QString::fromUtf8(kOCIODisplayParamDisplayChoice) ) ) ||
                                        ( ( pluginID == QString::fromUtf8(kOCIODisplayPluginIdentifier) ) &&
                                          ( knobScriptName == QString::fromUtf8(kOCIODisplayParamViewChoice) ) ) ||
                                        //( ( pluginID == QString::fromUtf8(kOCIOCDLTransformPluginIdentifier) ) &&
                                        //   ( knobScriptName == QString::fromUtf8(kOCIOCDLTransformParamCCCIDChoice) ) ) ||
                                        ( ( pluginID == QString::fromUtf8(kOCIOFileTransformPluginIdentifier) ) &&
                                          ( knobScriptName == QString::fromUtf8(kOCIOFileTransformParamCCCIDChoice) ) ) ||
                                        ( ( pluginID == QString::fromUtf8("net.fxarena.openfx.Text") ) &&
                                          ( knobScriptName == QString::fromUtf8("name") ) ) || // font family from Text plugin
                                        ( ( pluginID == QString::fromUtf8("net.fxarena.openfx.Polaroid") ) &&
                                          ( knobScriptName == QString::fromUtf8("font") ) ) || // font family from Polaroid plugin
                                        ( ( pluginID == QString::fromUtf8(PLUGINID_NATRON_PRECOMP) ) &&
                                          ( knobScriptName == QString::fromUtf8("writeNode") ) ) ||
                                        ( ( pluginID == QString::fromUtf8(PLUGINID_NATRON_ONEVIEW) ) &&
                                          ( knobScriptName == QString::fromUtf8("view") ) ) ) ) ) {
                        // see also KnobChoice::getHintToolTipFull()
                        int index = isChoice->getDefaultValue(DimIdx(i));
                        std::vector<ChoiceOption> entries = isChoice->getEntries();
                        if ( (index >= 0) && ( index < (int)entries.size() ) ) {
                            valueStr = QString::fromUtf8( entries[index].id.c_str() );
                        }
                        bool first = true;
                        for (size_t i = 0; i < entries.size(); i++) {
                            QString entryHelp = QString::fromUtf8( entries[i].tooltip.c_str() );
                            QString entry;
                            if (entries[i].id != entries[i].label) {
                                entry = QString::fromUtf8( "%1 (%2)" ).arg(QString::fromUtf8( entries[i].label.c_str() )).arg(QString::fromUtf8( entries[i].id.c_str() ));
                            } else {
                                entry = QString::fromUtf8( entries[i].label.c_str() );
                            }
                            if (!entry.isEmpty()) {
                                if (first) {
                                    // empty line before the option descriptions
                                    if (genHTML) {
                                        if ( !knobHint.isEmpty() ) {
                                            knobHint.append( QString::fromUtf8("<br />") );
                                        }
                                        knobHint.append( tr("Possible values:") + QString::fromUtf8("<br />") );
                                    } else {
                                        // we do a hack for multiline elements, because the markdown->rst conversion by pandoc doesn't use the line block syntax.
                                        // what we do here is put a supplementary dot at the beginning of each line, which is then converted to a pipe '|' in the
                                        // genStaticDocs.sh script by a simple sed command after converting to RsT
                                        if ( !knobHint.isEmpty() ) {
                                            if (!knobHint.startsWith( QString::fromUtf8(". ") )) {
                                                knobHint.prepend( QString::fromUtf8(". ") );
                                            }
                                            knobHint.append( QString::fromUtf8("\\\n") );
                                        }
                                        knobHint.append( QString::fromUtf8(". ") + tr("Possible values:") +  QString::fromUtf8("\\\n") );
                                    }
                                    first = false;
                                }
                                if (genHTML) {
                                    knobHint.append( QString::fromUtf8("<br />") );
                                } else {
                                    knobHint.append( QString::fromUtf8("\\\n") );
                                    // we do a hack for multiline elements, because the markdown->rst conversion by pandoc doesn't use the line block syntax.
                                    // what we do here is put a supplementary dot at the beginning of each line, which is then converted to a pipe '|' in the
                                    // genStaticDocs.sh script by a simple sed command after converting to RsT
                                    knobHint.append( QString::fromUtf8(". ") );
                                }
                                if (entryHelp.isEmpty()) {
                                    knobHint.append( QString::fromUtf8("**%1**").arg( convertFromPlainTextToMarkdown(entry, genHTML, true) ) );
                                } else {
                                    knobHint.append( QString::fromUtf8("**%1**: %2").arg( convertFromPlainTextToMarkdown(entry, genHTML, true) ).arg( convertFromPlainTextToMarkdown(entryHelp, genHTML, true) ) );
                                }
                            }
                        }
                    } else if (isInt) {
                        valueStr = QString::number( isInt->getDefaultValue( DimIdx(i) ) );
                    } else if (isDbl) {
                        valueStr = QString::number( isDbl->getDefaultValue( DimIdx(i) ) );
                    } else if (isBool) {
                        valueStr = isBool->getDefaultValue( DimIdx(i) ) ? tr("On") : tr("Off");
                    } else if (isString) {
                        valueStr = QString::fromUtf8( isString->getDefaultValue( DimIdx(i) ).c_str() );
                    } else if (isColor) {
                        valueStr = QString::number( isColor->getDefaultValue( DimIdx(i) ) );
                    }
                }

                dimsDefaultValueStr.push_back( std::make_pair(convertFromPlainTextToMarkdown( QString::fromUtf8( (*it)->getDimensionName( DimIdx(i) ).c_str() ), genHTML, true ),
                                                              convertFromPlainTextToMarkdown(valueStr, genHTML, true)) );
            }

            for (std::size_t i = 0; i < dimsDefaultValueStr.size(); ++i) {
                if ( !dimsDefaultValueStr[i].second.isEmpty() ) {
                    if (dimsDefaultValueStr.size() > 1) {
                        defValuesStr.append(dimsDefaultValueStr[i].first);
                        defValuesStr.append( QString::fromUtf8(": ") );
                    }
                    defValuesStr.append(dimsDefaultValueStr[i].second);
                    if (i < dimsDefaultValueStr.size() - 1) {
                        defValuesStr.append( QString::fromUtf8(" ") );
                    }
                }
            }
            if ( defValuesStr.isEmpty() ) {
                defValuesStr = tr("N/A");
            }
        }

        if (!isPage && !isSep && !isGroup && !isLabel) {
            QStringList row;
            row << knobLabel << knobScriptName << knobType << defValuesStr << knobHint;
            items.append(row);
        }
    } // for (KnobsVec::const_iterator it = knobs.begin(); it!=knobs.end(); ++it) {


    // generate plugin info
    ms << tr("%1 node").arg(pluginLabel) << "\n==========\n\n";

    // a hack to avoid repeating the documentation for the various merge plugins
    if ( pluginID.startsWith( QString::fromUtf8("net.sf.openfx.Merge") ) ) {
        std::string id = pluginID.toStdString();
        std::string op;
        if (id == PLUGINID_OFX_MERGE) {
            // do nothing
        } else if (id == "net.sf.openfx.MergeDifference") {
            op = "difference (a.k.a. absminus)";
        } else if (id == "net.sf.openfx.MergeIn") {
            op = "in";
        } else if (id == "net.sf.openfx.MergeMatte") {
            op = "matte";
        } else if (id == "net.sf.openfx.MergeMax") {
            op = "max";
        } else if (id == "net.sf.openfx.MergeMin") {
            op = "min";
        } else if (id == "net.sf.openfx.MergeMultiply") {
            op = "multiply";
        } else if (id == "net.sf.openfx.MergeOut") {
            op = "out";
        } else if (id == "net.sf.openfx.MergePlus") {
            op = "plus";
        } else if (id == "net.sf.openfx.MergeScreen") {
            op = "screen";
        }
        if ( !op.empty() ) {
            // we should use the custom link "[Merge node](|http::/plugins/" PLUGINID_OFX_MERGE ".html||rst::net.sf.openfx.MergePlugin|)"
            // but pandoc borks it
            ms << tr("The *%1* node is a convenience node identical to the %2, except that the operator is set to *%3* by default.")
            .arg(pluginLabel)
            .arg(genHTML ? QString::fromUtf8("<a href=\"" PLUGINID_OFX_MERGE ".html\">Merge node</a>") :
                 QString::fromUtf8(":ref:`" PLUGINID_OFX_MERGE "`")
                 //QString::fromUtf8("[Merge node](http::/plugins/" PLUGINID_OFX_MERGE ".html)")
                 )
            .arg( QString::fromUtf8( op.c_str() ) );
            goto OUTPUT;
        }

    }

    if (!pluginIconUrl.isEmpty()) {
        // add a nonbreaking space so that pandoc doesn't use the alt-text as a caption
        // http://pandoc.org/MANUAL.html#images
        ms << "![pluginIcon](" << pluginIconUrl << ")";
        if (!genHTML) {
            // specify image width for pandoc-generated printed doc
            // (for hoedown-generated HTML, this handled by the CSS using the alt=pluginIcon attribute)
            // see http://pandoc.org/MANUAL.html#images
            // note that only % units are understood both by pandox and sphinx
            ms << "{ width=10% }";
        }
        ms << "&nbsp;\n\n"; // &nbsp; required so that there is no legend when converted to rst by pandoc
    }
    ms << tr("*This documentation is for version %2.%3 of %1.*").arg(pluginLabel).arg(majorVersion).arg(minorVersion) << "\n\n";

    ms << "\n" << tr("Description") << "\n--------------------------------------------------------------------------------\n\n";

    if (!pluginDescriptionIsMarkdown) {
        if (genHTML) {
            pluginDescription = NATRON_NAMESPACE::convertFromPlainText(pluginDescription, NATRON_NAMESPACE::WhiteSpaceNormal);

            // replace URLs with links
            QRegExp re( QString::fromUtf8("((http|ftp|https)://([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?)") );
            pluginDescription.replace( re, QString::fromUtf8("<a href=\"\\1\">\\1</a>") );
        } else {
            pluginDescription = convertFromPlainTextToMarkdown(pluginDescription, genHTML, false);
        }
    }

    ms << pluginDescription << "\n";

    // create markdown table
    ms << "\n" << tr("Inputs") << "\n--------------------------------------------------------------------------------\n\n";
    ms << tr("Input") << " | " << tr("Description") << " | " << tr("Optional") << "\n";
    ms << "--- | --- | ---\n";
    if (inputs.size() > 0) {
        Q_FOREACH(const QStringList &input, inputs) {
            QString inputName = input.at(0);
            QString inputDesc = input.at(1);
            QString inputOpt = input.at(2);

            ms << inputName << " | " << inputDesc << " | " << inputOpt << "\n";
        }
EditNodeViewerContextDialog::EditNodeViewerContextDialog(const KnobIPtr& knob, QWidget* parent)
: QDialog(parent)
, _imp(new EditNodeViewerContextDialogPrivate(knob))
{

    setWindowTitle(tr("Edit %1 viewer interface").arg(QString::fromUtf8(knob->getName().c_str())));

    _imp->vLayout = new QVBoxLayout(this);
    _imp->vLayout->setContentsMargins(0, 0, TO_DPIX(15), 0);

    _imp->mainContainer = new QWidget(this);
    _imp->mainLayout = new QFormLayout(_imp->mainContainer);
    _imp->mainLayout->setLabelAlignment(Qt::AlignVCenter | Qt::AlignRight);
    _imp->mainLayout->setFormAlignment(Qt::AlignVCenter | Qt::AlignLeft);
    _imp->mainLayout->setSpacing(TO_DPIX(3));
    _imp->mainLayout->setContentsMargins(0, 0, TO_DPIX(15), 0);

    _imp->vLayout->addWidget(_imp->mainContainer);

    if (knob->isUserKnob()) {
        QWidget* rowContainer = new QWidget(this);
        QHBoxLayout* rowLayout = new QHBoxLayout(rowContainer);
        rowLayout->setContentsMargins(0, 0, 0, 0);

        _imp->viewerUILabelLabel = new Label(tr("Viewer Interface Label:"), this);
        _imp->viewerUILabelEdit = new LineEdit(rowContainer);
        QString labelTooltip = NATRON_NAMESPACE::convertFromPlainText(tr("The text label of the parameter that will appear in its viewer interface"), NATRON_NAMESPACE::WhiteSpaceNormal);
        _imp->viewerUILabelEdit->setToolTip(labelTooltip);
        _imp->viewerUILabelLabel->setToolTip(labelTooltip);

        if (knob) {
            _imp->viewerUILabelEdit->setText( QString::fromUtf8( knob->getInViewerContextLabel().c_str() ) );
        }
        rowLayout->addWidget(_imp->viewerUILabelEdit);
        rowLayout->addStretch();

        _imp->mainLayout->addRow(_imp->viewerUILabelLabel, rowContainer);
    }

    KnobButtonPtr isButtonKnob = toKnobButton(knob);

    if (knob->isUserKnob()) {
        QWidget* rowContainer = new QWidget(this);
        QHBoxLayout* rowLayout = new QHBoxLayout(rowContainer);
        rowLayout->setContentsMargins(0, 0, 0, 0);

        QString text;
        if (isButtonKnob) {
            text = tr("Button Checked Icon:");
        } else {
            text = tr("Icon label:");
        }
        QString tooltip;
        if (isButtonKnob) {
            tooltip = NATRON_NAMESPACE::convertFromPlainText(tr("The icon of the button when checked"), NATRON_NAMESPACE::WhiteSpaceNormal);
        } else {
            tooltip = NATRON_NAMESPACE::convertFromPlainText(tr("This icon will be used instead of the text label"), NATRON_NAMESPACE::WhiteSpaceNormal);
        }
        _imp->checkedIconLabel = new Label(text, this);
        _imp->checkedIconLineEdit = new LineEdit(rowContainer);
        _imp->checkedIconLineEdit->setToolTip(tooltip);
        _imp->checkedIconLabel->setToolTip(tooltip);

        _imp->checkedIconLineEdit->setText( QString::fromUtf8( knob->getInViewerContextIconFilePath(true).c_str() ) );

        rowLayout->addWidget(_imp->checkedIconLineEdit);
        rowLayout->addStretch();

        _imp->mainLayout->addRow(_imp->checkedIconLabel, rowContainer);
    }

    if (isButtonKnob && knob->isUserKnob()) {
        QWidget* rowContainer = new QWidget(this);
        QHBoxLayout* rowLayout = new QHBoxLayout(rowContainer);
        rowLayout->setContentsMargins(0, 0, 0, 0);

        QString text;
        text = tr("Button Unchecked Icon:");

        QString tooltip;
        tooltip = NATRON_NAMESPACE::convertFromPlainText(tr("The icon of the button when unchecked"), NATRON_NAMESPACE::WhiteSpaceNormal);

        _imp->uncheckedIconLabel = new Label(text, this);
        _imp->uncheckedIconLineEdit = new LineEdit(rowContainer);
        _imp->uncheckedIconLineEdit->setToolTip(tooltip);
        _imp->uncheckedIconLabel->setToolTip(tooltip);

        _imp->uncheckedIconLineEdit->setText( QString::fromUtf8( knob->getInViewerContextIconFilePath(false).c_str() ) );

        rowLayout->addWidget(_imp->uncheckedIconLineEdit);
        rowLayout->addStretch();

        _imp->mainLayout->addRow(_imp->uncheckedIconLabel, rowContainer);
    }

    {
        QWidget* rowContainer = new QWidget(this);
        QHBoxLayout* rowLayout = new QHBoxLayout(rowContainer);
        rowLayout->setContentsMargins(0, 0, 0, 0);

        QString text = tr("Layout Type:");
        QString tooltip = NATRON_NAMESPACE::convertFromPlainText(tr("The layout type for this parameter"), NATRON_NAMESPACE::WhiteSpaceNormal);
        _imp->layoutTypeLabel = new Label(text, this);
        _imp->layoutTypeChoice = new ComboBox(rowContainer);
        _imp->layoutTypeLabel->setToolTip(tooltip);
        _imp->layoutTypeChoice->setToolTip(tooltip);
        _imp->layoutTypeChoice->addItem(tr("Spacing (px)"), QIcon(), QKeySequence(), tr("The spacing in pixels to add after the parameter"));
        _imp->layoutTypeChoice->addItem(tr("Separator"), QIcon(), QKeySequence(), tr("A vertical line will be added after the parameter"));
        _imp->layoutTypeChoice->addItem(tr("Stretch After"), QIcon(), QKeySequence(), tr("The layout will be stretched between this parameter and the next"));
        _imp->layoutTypeChoice->addItem(tr("New Line"), QIcon(), QKeySequence(), tr("A new line will be added after this parameter"));

        ViewerContextLayoutTypeEnum type = knob->getInViewerContextLayoutType();
        _imp->layoutTypeChoice->setCurrentIndex_no_emit((int)type);

        QObject::connect(_imp->layoutTypeChoice, SIGNAL(currentIndexChanged(int)), this, SLOT(onLayoutTypeChoiceChanged(int)));
        rowLayout->addWidget(_imp->layoutTypeChoice);

        _imp->itemSpacingSpinbox = new SpinBox(rowContainer, SpinBox::eSpinBoxTypeInt);
        _imp->itemSpacingSpinbox->setMinimum(0);
        _imp->itemSpacingSpinbox->setValue(_imp->knob->getInViewerContextItemSpacing());
        _imp->itemSpacingSpinbox->setVisible(_imp->layoutTypeChoice->activeIndex() == 0);
        _imp->itemSpacingSpinbox->setToolTip(NATRON_NAMESPACE::convertFromPlainText(tr("The spacing in pixels to add after the parameter"), NATRON_NAMESPACE::WhiteSpaceNormal));
        rowLayout->addWidget(_imp->itemSpacingSpinbox);
        rowLayout->addStretch();

        _imp->mainLayout->addRow(_imp->layoutTypeLabel, rowContainer);
    }

    {
        QWidget* rowContainer = new QWidget(this);
        QHBoxLayout* rowLayout = new QHBoxLayout(rowContainer);
        rowLayout->setContentsMargins(0, 0, 0, 0);

        QString text = tr("Hidden:");
        QString tooltip = NATRON_NAMESPACE::convertFromPlainText(tr("When checked, the parameter will be hidden from the viewer interface"), NATRON_NAMESPACE::WhiteSpaceNormal);
        _imp->hiddenLabel = new Label(text, this);
        _imp->hiddenCheckbox = new AnimatedCheckBox(rowContainer);
        _imp->hiddenLabel->setToolTip(tooltip);
        _imp->hiddenCheckbox->setToolTip(tooltip);
        _imp->hiddenCheckbox->setChecked(knob->getInViewerContextSecret());
        rowLayout->addWidget(_imp->hiddenCheckbox);
        rowLayout->addStretch();

        _imp->mainLayout->addRow(_imp->hiddenLabel, rowContainer);
    }

   /* if (isButtonKnob) {
        QWidget* rowContainer = new QWidget(this);
        QHBoxLayout* rowLayout = new QHBoxLayout(rowContainer);
        rowLayout->setContentsMargins(0, 0, 0, 0);

        QString text = tr("Add to Shortcut Editor:");
        QString tooltip = GuiUtils::convertFromPlainText(tr("When checked, the parameter can be attributed a shortcut from the Shortcut Editor"), Qt::WhiteSpaceNormal);
        _imp->addToShortcutEditorLabel = new Label(text, this);
        _imp->addToShortcutEditorCheckbox = new AnimatedCheckBox(rowContainer);
        _imp->addToShortcutEditorLabel->setToolTip(tooltip);
        _imp->addToShortcutEditorCheckbox->setToolTip(tooltip);
        _imp->addToShortcutEditorCheckbox->setChecked(knob->getInViewerContextHasShortcut());
        rowLayout->addWidget(_imp->addToShortcutEditorCheckbox);
        rowLayout->addStretch();

        _imp->mainLayout->addRow(_imp->addToShortcutEditorLabel, rowContainer);
    }*/


    QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel), Qt::Horizontal, this);
    QObject::connect( buttons, SIGNAL(rejected()), this, SLOT(reject()) );
    QObject::connect( buttons, SIGNAL(accepted()), this, SLOT(onOkClicked()) );
    _imp->vLayout->addWidget(buttons);
}