示例#1
0
void
KnobGuiColor::addExtraWidgets(QHBoxLayout* containerLayout)
{
    containerLayout->addSpacing( TO_DPIX(10) );
    KnobColorPtr knob = _knob.lock();
    if (!knob) {
        return;
    }
    KnobGuiPtr knobUI = getKnobGui();
    if (!knobUI) {
        return;
    }
    _colorLabel = new ColorPickerLabel( _useSimplifiedUI, knobUI->getLayoutType(), this, containerLayout->widget() );
    if (!_useSimplifiedUI && knobUI->getLayoutType() != KnobGui::eKnobLayoutTypeTableItemWidget) {
        _colorLabel->setToolTip( NATRON_NAMESPACE::convertFromPlainText(tr("To pick a color on a viewer, click this and then press control + left click on any viewer.\n"
                                                                   "You can also pick the average color of a given rectangle by holding control + shift + left click\n. "
                                                                   "To deselect the picker left click anywhere."
                                                                   "Note that by default %1 converts to linear the color picked\n"
                                                                   "because all the processing pipeline is linear, but you can turn this off in the\n"
                                                                   "preferences panel.").arg( QString::fromUtf8(NATRON_APPLICATION_NAME) ), NATRON_NAMESPACE::WhiteSpaceNormal) );
    }

    QSize medSize( TO_DPIX(NATRON_MEDIUM_BUTTON_SIZE), TO_DPIY(NATRON_MEDIUM_BUTTON_SIZE) );
    QSize medIconSize( TO_DPIX(NATRON_MEDIUM_BUTTON_ICON_SIZE), TO_DPIY(NATRON_MEDIUM_BUTTON_ICON_SIZE) );

    _colorLabel->setFixedSize(medSize);
    QObject::connect( _colorLabel, SIGNAL(pickingEnabled(bool)), this, SLOT(onColorLabelPickingEnabled(bool)) );
    containerLayout->addWidget(_colorLabel);

    if (_useSimplifiedUI) {
        containerLayout->addSpacing( TO_DPIX(5) );
    }

    if (knobUI->getLayoutType() != KnobGui::eKnobLayoutTypeTableItemWidget) {
        QPixmap buttonPix;
        appPTR->getIcon(NATRON_PIXMAP_COLORWHEEL, NATRON_MEDIUM_BUTTON_ICON_SIZE, &buttonPix);
        _colorDialogButton = new Button( QIcon(buttonPix), QString(), containerLayout->widget() );
        _colorDialogButton->setFixedSize(medSize);
        _colorDialogButton->setIconSize(medIconSize);
        _colorDialogButton->setToolTip( NATRON_NAMESPACE::convertFromPlainText(tr("Open the color dialog."), NATRON_NAMESPACE::WhiteSpaceNormal) );
        _colorDialogButton->setFocusPolicy(Qt::NoFocus);
        QObject::connect( _colorDialogButton, SIGNAL(clicked()), this, SLOT(showColorDialog()) );
        containerLayout->addWidget(_colorDialogButton);
    }
    if (_useSimplifiedUI) {
        setWidgetsVisibleInternal(false);
        KnobGuiWidgets::enableRightClickMenu(getKnobGui(), _colorLabel, DimSpec::all(), getView());
    }
}
示例#2
0
void
BackdropGui::getInitialSize(int *w,
                            int *h) const
{
    *w = TO_DPIX(NATRON_BACKDROP_DEFAULT_WIDTH);
    *h = TO_DPIY(NATRON_BACKDROP_DEFAULT_HEIGHT);
}
示例#3
0
ComboBox::ComboBox(QWidget* parent)
    : QFrame(parent)
    , _readOnly(false)
    , _enabled(true)
    , _animation(0)
    , _clicked(false)
    , _dirty(false)
    , _altered(false)
    , _cascading(false)
    , _cascadingIndex(0)
    , _currentIndex(-1)
    , _currentText()
    , _separators()
    , _rootNode( new ComboBoxMenuNode() )
    , _sh()
    , _msh()
    , _sizePolicy()
    , _validHints(false)
    , _align(Qt::AlignLeft | Qt::AlignVCenter | Qt::TextExpandTabs)
    , _currentDelta(0)
    , ignoreWheelEvent(false)
{
    setFrameShape(QFrame::Box);

    setCurrentIndex(0);

    _rootNode->isMenu = new MenuWithToolTips(this);

    setSizePolicy( QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed, QSizePolicy::Label) );
    setFocusPolicy(Qt::StrongFocus);
    setFixedHeight( TO_DPIY(NATRON_MEDIUM_BUTTON_SIZE) );
}
示例#4
0
void
BackdropGui::resizeExtraContent(int /*w*/,
                                int /*h*/,
                                bool forceResize)
{
    QPointF p = pos();
    QPointF thisItemPos = mapFromParent(p);
    int nameHeight = getFrameNameHeight();

    _imp->label->setPos( thisItemPos.x(), thisItemPos.y() + nameHeight + TO_DPIY(10) );
    if (!forceResize) {
        _imp->label->adjustSize();
    }
}
示例#5
0
PreferencesPanel::PreferencesPanel(boost::shared_ptr<Settings> settings,
                                   Gui *parent)
    : QWidget(parent)
    , _gui(parent)
    , _settings(settings)
    , _changedKnobs()
    , _closeIsOK(false)
{
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);

    setWindowFlags(Qt::Window);
    setWindowTitle( tr("Preferences") );
    _mainLayout = new QVBoxLayout(this);
    _mainLayout->setContentsMargins(0, 0, 0, 0);
    _mainLayout->setSpacing(0);

    _panel = new DockablePanel(_gui, _settings.get(), _mainLayout, DockablePanel::eHeaderModeNoHeader, true, boost::shared_ptr<QUndoStack>(), QString(), QString(), false, QString(), this);
    _panel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _mainLayout->addWidget(_panel);

    _buttonBox = new QDialogButtonBox(Qt::Horizontal);
    _restoreDefaultsB = new Button( tr("Restore defaults") );
    _restoreDefaultsB->setToolTip( GuiUtils::convertFromPlainText(tr("Restore default values for all preferences."), Qt::WhiteSpaceNormal) );

    _prefsHelp = new Button( tr("Help") );
    _prefsHelp->setToolTip( tr("Show help for preference") );

    _cancelB = new Button( tr("Discard") );
    _cancelB->setToolTip( GuiUtils::convertFromPlainText(tr("Cancel changes that were not saved and close the window."), Qt::WhiteSpaceNormal) );
    _okB = new Button( tr("Save") );
    _okB->setToolTip( GuiUtils::convertFromPlainText(tr("Save changes on disk and close the window."), Qt::WhiteSpaceNormal) );
    _buttonBox->addButton(_restoreDefaultsB, QDialogButtonBox::ResetRole);
    _buttonBox->addButton(_prefsHelp, QDialogButtonBox::ResetRole);
    _buttonBox->addButton(_cancelB, QDialogButtonBox::RejectRole);
    _buttonBox->addButton(_okB, QDialogButtonBox::AcceptRole);

    // _mainLayout->addStretch();
    _mainLayout->addWidget(_buttonBox);

    QObject::connect( _restoreDefaultsB, SIGNAL(clicked()), this, SLOT(restoreDefaults()) );
    QObject::connect( _prefsHelp, SIGNAL(clicked()), this, SLOT(openHelp()) );
    QObject::connect( _buttonBox, SIGNAL(rejected()), this, SLOT(cancelChanges()) );
    QObject::connect( _buttonBox, SIGNAL(accepted()), this, SLOT(saveChangesAndClose()) );
    QObject::connect( _settings.get(), SIGNAL(settingChanged(KnobI*)), this, SLOT(onSettingChanged(KnobI*)) );

    _panel->initializeKnobs();

    resize( TO_DPIX(900), TO_DPIY(600) );
}
AnimItemDimViewKeyFrame
AnimationModuleViewPrivate::isNearbyKeyFrameText(const QPoint& pt) const
{
    AnimItemDimViewKeyFrame ret;
    
    QFontMetrics fm( _publicInterface->font() );
    int yOffset = TO_DPIY(4);
    AnimationModuleBasePtr model = _model.lock();
    const AnimItemDimViewKeyFramesMap& selectedKeys = model->getSelectionModel()->getCurrentKeyFramesSelection();
    if (selectedKeys.empty() || selectedKeys.size() > 1) {
        return ret;
    }

    AnimItemDimViewKeyFramesMap::const_iterator curveIT = selectedKeys.begin();
    const KeyFrameWithStringSet& keys = curveIT->second;
    if (keys.empty() || keys.size() > 1) {
        return ret;
    }

    const KeyFrameWithString& key = *keys.begin();


    QPointF topLeftWidget = curveEditorZoomContext.toWidgetCoordinates( key.key.getTime(), key.key.getValue() );
    topLeftWidget.ry() += yOffset;

    QString coordStr =  QString::fromUtf8("x: %1, y: %2").arg( key.key.getTime() ).arg( key.key.getValue() );
    QPointF btmRightWidget( topLeftWidget.x() + fm.width(coordStr), topLeftWidget.y() + fm.height() );

    if ( (pt.x() >= topLeftWidget.x() - TO_DPIX(CLICK_DISTANCE_TOLERANCE)) && (pt.x() <= btmRightWidget.x() + TO_DPIX(CLICK_DISTANCE_TOLERANCE)) &&
        ( pt.y() >= topLeftWidget.y() - TO_DPIX(CLICK_DISTANCE_TOLERANCE)) && ( pt.y() <= btmRightWidget.y() + TO_DPIX(CLICK_DISTANCE_TOLERANCE)) ) {
        ret.key.key = key.key;
        StringAnimationManagerPtr stringAnim = curveIT->first.item->getInternalAnimItem()->getStringAnimation();
        if (stringAnim) {
            stringAnim->stringFromInterpolatedIndex(key.key.getValue(), curveIT->first.view, &ret.key.string);
        }
        ret.id = curveIT->first;

        return ret;
    }


    return ret;
}
示例#7
0
void
EditScriptDialog::create(const QString& initialScript,
                         bool makeUseRetButton)
{
    setTitle();

    _imp->mainLayout = new QVBoxLayout(this);

    QStringList modules;
    getImportedModules(modules);
    std::list<std::pair<QString, QString> > variables;
    getDeclaredVariables(variables);
    QString labelHtml( tr("%1 script:").arg( QString::fromUtf8("<b>Python</b>") ) + QString::fromUtf8("<br />") );
    if ( !modules.empty() ) {
        labelHtml.append( tr("For convenience, the following module(s) have been imported:") + QString::fromUtf8("<br />") );
        for (int i = 0; i < modules.size(); ++i) {
            QString toAppend = QString::fromUtf8("<i><font color=orange>from %1 import *</font></i><br />").arg(modules[i]);
            labelHtml.append(toAppend);
        }
        labelHtml.append( QString::fromUtf8("<br />") );
    }
    if ( !variables.empty() ) {
        labelHtml.append( tr("Also the following variables have been declared:") + QString::fromUtf8("<br />") );
        for (std::list<std::pair<QString, QString> > ::iterator it = variables.begin(); it != variables.end(); ++it) {
            QString toAppend = QString::fromUtf8("<b>%1</b>: %2<br />").arg(it->first).arg(it->second);
            labelHtml.append(toAppend);
        }
        QKeySequence s(Qt::CTRL);
        labelHtml.append( QString::fromUtf8("<p>") + tr("Note that parameters can be referenced by drag'n'dropping while holding %1 on their widget").arg( s.toString(QKeySequence::NativeText) ) + QString::fromUtf8("</p>") );
    }

    _imp->expressionLabel = new Label(labelHtml, this);
    _imp->mainLayout->addWidget(_imp->expressionLabel);

    _imp->expressionEdit = new InputScriptTextEdit(_imp->gui, this);
    _imp->expressionEdit->setAcceptDrops(true);
    _imp->expressionEdit->setMouseTracking(true);
    _imp->mainLayout->addWidget(_imp->expressionEdit);
    _imp->expressionEdit->setPlainText(initialScript);

    _imp->midButtonsContainer = new QWidget(this);
    _imp->midButtonsLayout = new QHBoxLayout(_imp->midButtonsContainer);


    if (makeUseRetButton) {
        bool retVariable = hasRetVariable();
        _imp->useRetButton = new Button(tr("Multi-line"), _imp->midButtonsContainer);
        _imp->useRetButton->setToolTip( GuiUtils::convertFromPlainText(tr("When checked the Python expression will be interpreted "
                                                                          "as series of statement. The return value should be then assigned to the "
                                                                          "\"ret\" variable. When unchecked the expression must not contain "
                                                                          "any new line character and the result will be interpreted from the "
                                                                          "interpretation of the single line."), Qt::WhiteSpaceNormal) );
        _imp->useRetButton->setCheckable(true);
        bool checked = !initialScript.isEmpty() && retVariable;
        _imp->useRetButton->setChecked(checked);
        _imp->useRetButton->setDown(checked);
        QObject::connect( _imp->useRetButton, SIGNAL(clicked(bool)), this, SLOT(onUseRetButtonClicked(bool)) );
        _imp->midButtonsLayout->addWidget(_imp->useRetButton);
    }


    _imp->helpButton = new Button(tr("Help"), _imp->midButtonsContainer);
    QObject::connect( _imp->helpButton, SIGNAL(clicked(bool)), this, SLOT(onHelpRequested()) );
    _imp->midButtonsLayout->addWidget(_imp->helpButton);
    _imp->midButtonsLayout->addStretch();

    _imp->mainLayout->addWidget(_imp->midButtonsContainer);

    _imp->resultLabel = new Label(tr("Result:"), this);
    _imp->mainLayout->addWidget(_imp->resultLabel);

    _imp->resultEdit = new OutputScriptTextEdit(this);
    _imp->resultEdit->setFixedHeight( TO_DPIY(80) );
    _imp->resultEdit->setReadOnly(true);
    _imp->mainLayout->addWidget(_imp->resultEdit);

    _imp->buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
    _imp->mainLayout->addWidget(_imp->buttons);
    QObject::connect( _imp->buttons, SIGNAL(accepted()), this, SLOT(accept()) );
    QObject::connect( _imp->buttons, SIGNAL(rejected()), this, SLOT(reject()) );

    if ( !initialScript.isEmpty() ) {
        compileAndSetResult(initialScript);
    }
    QObject::connect( _imp->expressionEdit, SIGNAL(textChanged()), this, SLOT(onTextEditChanged()) );
    _imp->expressionEdit->setFocus();

    QString fontFamily = QString::fromUtf8( appPTR->getCurrentSettings()->getSEFontFamily().c_str() );
    int fontSize = appPTR->getCurrentSettings()->getSEFontSize();
    QFont font(fontFamily, fontSize);
    if ( font.exactMatch() ) {
        _imp->expressionEdit->setFont(font);
        _imp->resultEdit->setFont(font);
    }
    QFontMetrics fm = _imp->expressionEdit->fontMetrics();
    _imp->expressionEdit->setTabStopWidth( 4 * fm.width( QLatin1Char(' ') ) );
} // EditScriptDialog::create
示例#8
0
void
ScaleSliderQWidget::paintEvent(QPaintEvent* /*e*/)
{
    if (_imp->mustInitializeSliderPosition) {
        if (_imp->minimum < _imp->maximum) {
            centerOn(_imp->minimum, _imp->maximum);
        }
        _imp->mustInitializeSliderPosition = false;
        seekScalePosition(_imp->value);
        _imp->initialized = true;
    }

    ///fill the background with the appropriate style color
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    p.setOpacity(1);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);

    double txtR, txtG, txtB;
    if (_imp->altered) {
        appPTR->getCurrentSettings()->getAltTextColor(&txtR, &txtG, &txtB);
    } else {
        appPTR->getCurrentSettings()->getTextColor(&txtR, &txtG, &txtB);
    }

    QColor textColor;
    textColor.setRgbF( Image::clamp<qreal>(txtR, 0., 1.),
                       Image::clamp<qreal>(txtG, 0., 1.),
                       Image::clamp<qreal>(txtB, 0., 1.) );

    QColor scaleColor;
    scaleColor.setRgbF(textColor.redF() / 2., textColor.greenF() / 2., textColor.blueF() / 2.);

    QFontMetrics fontM(_imp->font, 0);

    if (!_imp->useLineColor) {
        p.setPen(scaleColor);
    } else {
        p.setPen(_imp->lineColor);
    }

    QPointF btmLeft = _imp->zoomCtx.toZoomCoordinates(0, height() - 1);
    QPointF topRight = _imp->zoomCtx.toZoomCoordinates(width() - 1, 0);

    if ( btmLeft.x() == topRight.x() ) {
        return;
    }

    /*drawing X axis*/
    double lineYpos = height() - 1 - fontM.height()  - TO_DPIY(TICK_HEIGHT) / 2;
    p.drawLine(0, lineYpos, width() - 1, lineYpos);

    double tickBottom = _imp->zoomCtx.toZoomCoordinates( 0, height() - 1 - fontM.height() ).y();
    double tickTop = _imp->zoomCtx.toZoomCoordinates( 0, height() - 1 - fontM.height()  - TO_DPIY(TICK_HEIGHT) ).y();
    const double smallestTickSizePixel = 10.; // tick size (in pixels) for alpha = 0.
    const double largestTickSizePixel = 1000.; // tick size (in pixels) for alpha = 1.
    const double rangePixel =  width();
    const double range_min = btmLeft.x();
    const double range_max =  topRight.x();
    const double range = range_max - range_min;
    double smallTickSize;
    bool half_tick;
    ticks_size(range_min, range_max, rangePixel, smallestTickSizePixel, &smallTickSize, &half_tick);
    if ( (_imp->dataType == eDataTypeInt) && (smallTickSize < 1.) ) {
        smallTickSize = 1.;
        half_tick = false;
    }
    int m1, m2;
    const int ticks_max = 1000;
    double offset;
    ticks_bounds(range_min, range_max, smallTickSize, half_tick, ticks_max, &offset, &m1, &m2);
    std::vector<int> ticks;
    ticks_fill(half_tick, ticks_max, m1, m2, &ticks);
    const double smallestTickSize = range * smallestTickSizePixel / rangePixel;
    const double largestTickSize = range * largestTickSizePixel / rangePixel;
    const double minTickSizeTextPixel = fontM.width( QLatin1String("00") ); // AXIS-SPECIFIC
    const double minTickSizeText = range * minTickSizeTextPixel / rangePixel;
    for (int i = m1; i <= m2; ++i) {
        double value = i * smallTickSize + offset;
        const double tickSize = ticks[i - m1] * smallTickSize;
        const double alpha = ticks_alpha(smallestTickSize, largestTickSize, tickSize);
        QColor color(textColor);
        color.setAlphaF(alpha);
        QPen pen(color);
        pen.setWidthF(1.9);
        p.setPen(pen);

        // for Int slider, because smallTickSize is at least 1, isFloating can never be true
        bool isFloating = std::abs(std::floor(0.5 + value) - value) != 0.;
        assert( !(_imp->dataType == eDataTypeInt && isFloating) );
        bool renderFloating = _imp->dataType == eDataTypeDouble || !isFloating;

        if (renderFloating) {
            QPointF tickBottomPos = _imp->zoomCtx.toWidgetCoordinates(value, tickBottom);
            QPointF tickTopPos = _imp->zoomCtx.toWidgetCoordinates(value, tickTop);

            p.drawLine(tickBottomPos, tickTopPos);
        }

        if ( renderFloating && (tickSize > minTickSizeText) ) {
            const int tickSizePixel = rangePixel * tickSize / range;
            const QString s = QString::number(value);
            const int sSizePixel =  fontM.width(s);
            if (tickSizePixel > sSizePixel) {
                const int sSizeFullPixel = sSizePixel + minTickSizeTextPixel;
                double alphaText = 1.0; //alpha;
                if (tickSizePixel < sSizeFullPixel) {
                    // when the text size is between sSizePixel and sSizeFullPixel,
                    // draw it with a lower alpha
                    alphaText *= (tickSizePixel - sSizePixel) / (double)minTickSizeTextPixel;
                }
                QColor c = _imp->readOnly || !isEnabled() ? Qt::black : textColor;
                c.setAlphaF(alphaText);
                p.setFont(_imp->font);
                p.setPen(c);

                QPointF textPos = _imp->zoomCtx.toWidgetCoordinates( value, btmLeft.y() );

                p.drawText(textPos, s);
            }
        }
    }
    double positionValue = _imp->zoomCtx.toWidgetCoordinates(_imp->value, 0).x();
    QPointF sliderBottomLeft(positionValue - TO_DPIX(SLIDER_WIDTH) / 2, height() - 1 - fontM.height() / 2);
    QPointF sliderTopRight( positionValue + TO_DPIX(SLIDER_WIDTH) / 2, height() - 1 - fontM.height() / 2 - TO_DPIY(SLIDER_HEIGHT) );

    /*draw the slider*/
    p.setPen(_imp->sliderColor);
    p.fillRect(sliderBottomLeft.x(), sliderBottomLeft.y(), sliderTopRight.x() - sliderBottomLeft.x(), sliderTopRight.y() - sliderBottomLeft.y(), _imp->sliderColor);

    /*draw a black rect around the slider for contrast or orange when focused*/
    if ( !hasFocus() ) {
        p.setPen(Qt::black);
    } else {
        QPen pen = p.pen();
        pen.setColor( QColor(243, 137, 0) );
        QVector<qreal> dashStyle;
        qreal space = 2;
        dashStyle << 1 << space;
        pen.setDashPattern(dashStyle);
        p.setOpacity(0.8);
        p.setPen(pen);
    }

    p.drawLine( sliderBottomLeft.x(), sliderBottomLeft.y(), sliderBottomLeft.x(), sliderTopRight.y() );
    p.drawLine( sliderBottomLeft.x(), sliderTopRight.y(), sliderTopRight.x(), sliderTopRight.y() );
    p.drawLine( sliderTopRight.x(), sliderTopRight.y(), sliderTopRight.x(), sliderBottomLeft.y() );
    p.drawLine( sliderTopRight.x(), sliderBottomLeft.y(), sliderBottomLeft.x(), sliderBottomLeft.y() );
} // paintEvent
示例#9
0
QSize
ScaleSliderQWidget::minimumSizeHint() const
{
    return QSize( TO_DPIX(150), TO_DPIY(20) );
}
示例#10
0
void
KnobGuiValue::createWidget(QHBoxLayout* layout)
{
    
    connectKnobSignalSlots();
    
    _imp->container = new QWidget(layout->parentWidget());
    QHBoxLayout *containerLayout = new QHBoxLayout(_imp->container);
    layout->addWidget(_imp->container);
    
    containerLayout->setContentsMargins(0, 0, 0, 0);
    containerLayout->setSpacing(3);
    
    if (getKnobsCountOnSameLine() > 1) {
        disableSlider();
    }
    
    if (!isSliderDisabled()) {
        layout->parentWidget()->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    }
    
    KnobPtr knob = _imp->getKnob();
    const int nDims = knob->getDimension();
    
    std::vector<double> increments, displayMins, displayMaxs, mins, maxs;
    std::vector<int> decimals;
    boost::shared_ptr<Knob<double> > doubleKnob = _imp->getKnobAsDouble();
    boost::shared_ptr<Knob<int> > intKnob = _imp->getKnobAsInt();
    if (doubleKnob) {
        displayMins = doubleKnob->getDisplayMinimums();
        displayMaxs = doubleKnob->getDisplayMaximums();
        mins = doubleKnob->getMinimums();
        maxs = doubleKnob->getMaximums();
    } else {
        const std::vector<int>& intDmins = intKnob->getDisplayMinimums();
        const std::vector<int>& intDMaxs = intKnob->getDisplayMaximums();
        const std::vector<int>& intMins = intKnob->getMinimums();
        const std::vector<int>& intMaxs = intKnob->getMaximums();
        assert(intDMaxs.size() == intDmins.size() && intDmins.size() == intMins.size() && intMins.size() == intMaxs.size());
        displayMins.resize(intDmins.size());
        displayMaxs.resize(intDmins.size());
        mins.resize(intDmins.size());
        maxs.resize(intDmins.size());
        
        for (std::size_t i = 0; i < intMins.size(); ++i) {
            displayMins[i] = intDmins[i];
            displayMaxs[i] = intDMaxs[i];
            mins[i] = intMins[i];
            maxs[i] = intMaxs[i];
        }
    }
    
    getIncrements(&increments);
    getDecimals(&decimals);
    
    std::vector<std::string> dimensionLabels(nDims);
    
    bool isRectangleParam = isRectangleType();
    // This is a rectangle parameter
    if (isRectangleParam) {
        dimensionLabels[0] = "x";
        dimensionLabels[1] = "y";
        dimensionLabels[2] = "w";
        dimensionLabels[3] = "h";
    } else {
        for (int i = 0; i < nDims; ++i) {
            dimensionLabels[i] = knob->getDimensionName(i);
        }
    }
    
    KnobGuiPtr thisShared = shared_from_this();
    
    SpinBox::SpinBoxTypeEnum type;
    if (doubleKnob) {
        type = SpinBox::eSpinBoxTypeDouble;
    } else {
        type = SpinBox::eSpinBoxTypeInt;
    }
    
    
    int nItemsPerRow = nDims;
    if (std::floor(nDims / 3. + 0.5) == nDims / 3.) {
        nItemsPerRow = 3;
    }
    if (std::floor(nDims / 4. + 0.5) == nDims / 4.) {
        nItemsPerRow = 4;
    }
    
    int nbRows = nDims / nItemsPerRow;
    assert(nbRows >= 1);
    QWidget* allSpinBoxesContainer = 0;
    QGridLayout* spinBoxesGrid = 0;
    if (nbRows == 1) {
        allSpinBoxesContainer = _imp->container;
    } else {
        allSpinBoxesContainer = new QWidget(_imp->container);
        spinBoxesGrid = new QGridLayout(allSpinBoxesContainer);
        spinBoxesGrid->setContentsMargins(0, 0, 0, 0);
        spinBoxesGrid->setVerticalSpacing(TO_DPIY(1));
        spinBoxesGrid->setHorizontalSpacing(TO_DPIX(1));
    }
    
    _imp->spinBoxes.resize(nDims);
    
    int rowIndex = 0;
    int columnIndex = 0;
    for (std::size_t i = 0; i < _imp->spinBoxes.size(); ++i) {
        
        QWidget *boxContainer = new QWidget(allSpinBoxesContainer);
        boxContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        
        QHBoxLayout *boxContainerLayout = 0;
        boxContainerLayout = new QHBoxLayout(boxContainer);
        boxContainerLayout->setContentsMargins(0, 0, 0, 0);
        boxContainerLayout->setSpacing(3);
        
        
        Label *subDesc = 0;
        if (nDims != 1 && nbRows == 1) {
            subDesc = new Label(QString::fromUtf8(dimensionLabels[i].c_str()), boxContainer);
            boxContainerLayout->addWidget(subDesc);
        }
        
        SpinBox *box = new KnobSpinBox(layout->parentWidget(), type, thisShared , i);
        NumericKnobValidator* validator = new NumericKnobValidator(box,thisShared);
        box->setValidator(validator);
        QObject::connect( box, SIGNAL(valueChanged(double)), this, SLOT(onSpinBoxValueChanged()) );
        
        // Set the copy/link actions in the right click menu of the SpinBox
        enableRightClickMenu(box,i);
        
#ifdef SPINBOX_TAKE_PLUGIN_RANGE_INTO_ACCOUNT
        double min = mins[i];
        double max = maxs[i];
        valueAccordingToType(false, i, &min);
        valueAccordingToType(false, i, &max);
        box->setMaximum(max);
        box->setMinimum(min);
#endif
        
        
        
        if (type == SpinBox::eSpinBoxTypeDouble) {
            // Set the number of digits after the decimal point
            if (i < decimals.size()) {
                box->decimals(decimals[i]);
            }
        }
        
        if (i < increments.size()) {    
            double incr = 1;
            incr = increments[i];
            valueAccordingToType(false, i, &incr);
            box->setIncrement(incr);
        }
        boxContainerLayout->addWidget(box);
        if (!spinBoxesGrid) {
            containerLayout->addWidget(boxContainer);
        } else {
            spinBoxesGrid->addWidget(boxContainer, rowIndex, columnIndex);
        }
        _imp->spinBoxes[i] = std::make_pair(box, subDesc);
        
        ++columnIndex;
        if (columnIndex >= nItemsPerRow) {
            columnIndex = 0;
            ++rowIndex;
        }
    }
    
    if (spinBoxesGrid) {
        containerLayout->addWidget(allSpinBoxesContainer);
    }
    
    bool sliderVisible = false;
    if (!isSliderDisabled() && !isRectangleParam) {
        double dispmin = displayMins[0];
        double dispmax = displayMaxs[0];
        if (dispmin == -DBL_MAX) {
            dispmin = mins[0];
        }
        if (dispmax == DBL_MAX) {
            dispmax = maxs[0];
        }
        
        // denormalize if necessary
        double dispminGui = dispmin;
        double dispmaxGui = dispmax;
        valueAccordingToType(false, 0, &dispminGui);
        valueAccordingToType(false, 0, &dispmaxGui);
        
        bool spatial = isSpatialType();
        Format f;
        if (spatial) {
            getKnob()->getHolder()->getApp()->getProject()->getProjectDefaultFormat(&f);
        }
        if (dispminGui < -SLIDER_MAX_RANGE) {
            if (spatial) {
                dispminGui = -f.width();
            } else {
                dispminGui = -SLIDER_MAX_RANGE;
            }
        }
        if (dispmaxGui > SLIDER_MAX_RANGE) {
            if (spatial) {
                dispmaxGui = f.width();
            } else {
                dispmaxGui = SLIDER_MAX_RANGE;
            }
        }
        
        double value0 = _imp->getKnobValue(0);

        ScaleSliderQWidget::DataTypeEnum sliderType;
        if (doubleKnob) {
            sliderType = ScaleSliderQWidget::eDataTypeDouble;
        } else {
            sliderType = ScaleSliderQWidget::eDataTypeInt;
        }

        
        _imp->slider = new ScaleSliderQWidget(dispminGui, dispmaxGui, value0,knob->getEvaluateOnChange(),
                                         sliderType,getGui(), eScaleTypeLinear, layout->parentWidget());
        _imp->slider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        if (hasToolTip()) {
            _imp->slider->setToolTip( toolTip() );
        }
        QObject::connect(_imp->slider, SIGNAL(positionChanged(double)), this, SLOT(onSliderValueChanged(double)));
        QObject::connect(_imp->slider, SIGNAL(editingFinished(bool)), this, SLOT(onSliderEditingFinished(bool)));
        containerLayout->addWidget(_imp->slider);
        
        sliderVisible = shouldSliderBeVisible(dispminGui, dispmaxGui);
        
        // onDisplayMinMaxChanged takes original (maybe normalized) values
        onDisplayMinMaxChanged(dispmin, dispmax);
    }
std::pair<MoveTangentCommand::SelectedTangentEnum, AnimItemDimViewKeyFrame >
AnimationModuleViewPrivate::isNearbySelectedTangentText(const QPoint & pt) const
{
    QFontMetrics fm( _publicInterface->font() );
    int yOffset = TO_DPIY(4);
    std::pair<MoveTangentCommand::SelectedTangentEnum, AnimItemDimViewKeyFrame > ret;
    
    AnimationModuleBasePtr model = _model.lock();
    const AnimItemDimViewKeyFramesMap& selectedKeys = model->getSelectionModel()->getCurrentKeyFramesSelection();
    if (selectedKeys.empty() || selectedKeys.size() > 1) {
        return ret;
    }

    AnimItemDimViewKeyFramesMap::const_iterator curveIT = selectedKeys.begin();
    const KeyFrameWithStringSet& keys = curveIT->second;
    if (keys.empty() || keys.size() > 1) {
        return ret;
    }

    const KeyFrameWithString& key = *keys.begin();
    CurvePtr curve = curveIT->first.item->getCurve(curveIT->first.dim, curveIT->first.view);
    if (!curve) {
        return ret;
    }
    KeyFrameSet curveKeys = curve->getKeyFrames_mt_safe();

    KeyFrameSet::iterator foundKey = Curve::findWithTime(curveKeys, curveKeys.begin(), key.key.getTime());
    assert(foundKey != curveKeys.end());
    if (foundKey == curveKeys.end()) {
        return ret;
    }
    for (KeyFrameWithStringSet::const_iterator it = keys.begin(); it != keys.end(); ++it) {


        QPointF leftTanPos, rightTanPos;
        _publicInterface->getKeyTangentPoints(foundKey, curveKeys, &leftTanPos, &rightTanPos);

        double rounding = std::pow(10., CURVEWIDGET_DERIVATIVE_ROUND_PRECISION);
        QPointF topLeft_LeftTanWidget = curveEditorZoomContext.toWidgetCoordinates( leftTanPos.x(), leftTanPos.y() );
        QPointF topLeft_RightTanWidget = curveEditorZoomContext.toWidgetCoordinates( rightTanPos.x(), rightTanPos.y() );
        topLeft_LeftTanWidget.ry() += yOffset;
        topLeft_RightTanWidget.ry() += yOffset;

        QString leftCoordStr =  QString( tr("l: %1") ).arg(std::floor( ( key.key.getLeftDerivative() * rounding ) + 0.5 ) / rounding);
        QString rightCoordStr =  QString( tr("r: %1") ).arg(std::floor( ( key.key.getRightDerivative() * rounding ) + 0.5 ) / rounding);
        QPointF btmRight_LeftTanWidget( topLeft_LeftTanWidget.x() + fm.width(leftCoordStr), topLeft_LeftTanWidget.y() + fm.height() );
        QPointF btmRight_RightTanWidget( topLeft_RightTanWidget.x() + fm.width(rightCoordStr), topLeft_RightTanWidget.y() + fm.height() );

        if ( (pt.x() >= topLeft_LeftTanWidget.x() - TO_DPIX(CLICK_DISTANCE_TOLERANCE)) && (pt.x() <= btmRight_LeftTanWidget.x() + TO_DPIX(CLICK_DISTANCE_TOLERANCE)) &&
            ( pt.y() >= topLeft_LeftTanWidget.y() - TO_DPIX(CLICK_DISTANCE_TOLERANCE)) && ( pt.y() <= btmRight_LeftTanWidget.y() + TO_DPIX(CLICK_DISTANCE_TOLERANCE)) ) {
            ret.second.key.key = key.key;
            StringAnimationManagerPtr stringAnim = curveIT->first.item->getInternalAnimItem()->getStringAnimation();
            if (stringAnim) {
                stringAnim->stringFromInterpolatedIndex(key.key.getValue(), curveIT->first.view, &ret.second.key.string);
            }
            ret.second.id = curveIT->first;
            ret.first = MoveTangentCommand::eSelectedTangentLeft;
        } else if ( (pt.x() >= topLeft_RightTanWidget.x() - TO_DPIX(CLICK_DISTANCE_TOLERANCE)) && (pt.x() <= btmRight_RightTanWidget.x() + TO_DPIX(CLICK_DISTANCE_TOLERANCE)) &&
                   ( pt.y() >= topLeft_RightTanWidget.y() - TO_DPIX(CLICK_DISTANCE_TOLERANCE)) && ( pt.y() <= btmRight_RightTanWidget.y() + TO_DPIX(CLICK_DISTANCE_TOLERANCE)) ) {
            ret.second.key.key = key.key;
            StringAnimationManagerPtr stringAnim = curveIT->first.item->getInternalAnimItem()->getStringAnimation();
            if (stringAnim) {
                stringAnim->stringFromInterpolatedIndex(key.key.getValue(), curveIT->first.view, &ret.second.key.string);
            }
            ret.second.id = curveIT->first;
            ret.first = MoveTangentCommand::eSelectedTangentRight;
        }



    } // for all curves
    return ret;

} // isNearbySelectedTangentText
示例#12
0
NATRON_NAMESPACE_ENTER


ViewerTab::ViewerTab(const std::string& scriptName,
                     const std::list<NodeGuiPtr> & existingNodesContext,
                     const std::list<NodeGuiPtr>& activePluginsContext,
                     Gui* gui,
                     const NodeGuiPtr& node_ui,
                     QWidget* parent)
    : QWidget(parent)
    , PanelWidget(scriptName, this, gui)
    , _imp( new ViewerTabPrivate(this, node_ui) )
{
    ViewerNodePtr node = node_ui->getNode()->isEffectViewerNode();
    installEventFilter(this);
    setMouseTracking(true);
    NodePtr internalNode = node->getNode();
    QObject::connect( internalNode.get(), SIGNAL(scriptNameChanged(QString)), this, SLOT(onInternalNodeScriptNameChanged(QString)) );
    QObject::connect( internalNode.get(), SIGNAL(labelChanged(QString,QString)), this, SLOT(onInternalNodeLabelChanged(QString,QString)) );
    QObject::connect( node.get(), SIGNAL(internalViewerCreated()), this, SLOT(onInternalViewerCreated()));

    _imp->mainLayout = new QVBoxLayout(this);
    setLayout(_imp->mainLayout);
    _imp->mainLayout->setSpacing(0);
    _imp->mainLayout->setContentsMargins(0, 0, 0, 0);

    QFontMetrics fm(font(), 0);


    _imp->viewerContainer = new QWidget(this);
    _imp->viewerLayout = new QHBoxLayout(_imp->viewerContainer);
    _imp->viewerLayout->setContentsMargins(0, 0, 0, 0);
    _imp->viewerLayout->setSpacing(0);

    _imp->viewerSubContainer = new QWidget(_imp->viewerContainer);
    _imp->viewerSubContainerLayout = new QVBoxLayout(_imp->viewerSubContainer);
    _imp->viewerSubContainerLayout->setContentsMargins(0, 0, 0, 0);
    _imp->viewerSubContainerLayout->setSpacing(1);


    // Info bars
    QString inputNames[2] = {
        QString::fromUtf8("A:"), QString::fromUtf8("B:")
    };

    bool infobarvisible = node->isInfoBarVisible();
    for (int i = 0; i < 2; ++i) {
        _imp->infoWidget[i] = new InfoViewerWidget(inputNames[i], this);

    }

    // Viewer
    _imp->viewer = new ViewerGL(this);

    GuiAppInstancePtr app = gui->getApp();

    // Init viewer to project format
    {
        Format projectFormat;
        app->getProject()->getProjectDefaultFormat(&projectFormat);

        RectD canonicalFormat = projectFormat.toCanonicalFormat();
        for (int i = 0; i < 2; ++i) {
            _imp->viewer->setInfoViewer(_imp->infoWidget[i], i);
            _imp->viewer->setRegionOfDefinition(canonicalFormat, projectFormat.getPixelAspectRatio(), i);
            setInfoBarAndViewerResolution(projectFormat, canonicalFormat, projectFormat.getPixelAspectRatio(), i);
        }
        _imp->viewer->resetWipeControls();
    }

    _imp->viewerSubContainerLayout->addWidget(_imp->viewer);
    for (int i = 0; i < 2; ++i) {
        _imp->viewerSubContainerLayout->addWidget(_imp->infoWidget[i]);
        _imp->viewer->setInfoViewer(_imp->infoWidget[i], i);
        if (i == 1 || !infobarvisible) {
            _imp->infoWidget[i]->hide();
        }
    }

    manageSlotsForInfoWidget(0, true);


    _imp->viewerLayout->addWidget(_imp->viewerSubContainer);
    _imp->mainLayout->addWidget(_imp->viewerContainer);

    TimeLinePtr timeline = app->getTimeLine();
    _imp->timeLineGui = new TimeLineGui(node, timeline, getGui(), this);
    QObject::connect( _imp->timeLineGui, SIGNAL(boundariesChanged(SequenceTime,SequenceTime)),
                      this, SLOT(onTimelineBoundariesChanged(SequenceTime,SequenceTime)) );
    QObject::connect( app->getProject().get(), SIGNAL(frameRangeChanged(int,int)), _imp->timeLineGui, SLOT(onProjectFrameRangeChanged(int,int)) );
    _imp->timeLineGui->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);

    if (!node->isTimelineVisible()) {
        _imp->timeLineGui->hide();
    }

    //Add some spacing because the timeline might be black as the info
    _imp->mainLayout->addSpacing( TO_DPIY(5) );
    _imp->mainLayout->addWidget(_imp->timeLineGui);

    double leftBound, rightBound;
    leftBound = node->getPlaybackInPointKnob()->getValue();
    rightBound = node->getPlaybackOutPointKnob()->getValue();

    TimeValue projectLeft, projectRight;
    app->getProject()->getFrameRange(&projectLeft, &projectRight);

    _imp->timeLineGui->setBoundaries(leftBound, rightBound);
    onTimelineBoundariesChanged(leftBound, rightBound);
    _imp->timeLineGui->setFrameRangeEdited(projectLeft != leftBound || projectRight != rightBound);;


    manageTimelineSlot(false, timeline);

    QObject::connect( node.get(), SIGNAL(renderStatsAvailable(int,double,RenderStatsMap)),
                      this, SLOT(onRenderStatsAvailable(int,double,RenderStatsMap)) );
    QObject::connect( _imp->viewer, SIGNAL(zoomChanged(int)), this, SLOT(updateZoomComboBox(int)) );
    QObject::connect( node.get(), SIGNAL(viewerDisconnected()), this, SLOT(disconnectViewer()) );


    createNodeViewerInterface(node_ui);
    setPluginViewerInterface(node_ui);
    
    for (std::list<NodeGuiPtr>::const_iterator it = existingNodesContext.begin(); it != existingNodesContext.end(); ++it) {
        ViewerNodePtr isViewerNode = (*it)->getNode()->isEffectViewerNode();
        // For viewers, create the viewer interface separately
        if (!isViewerNode) {
            createNodeViewerInterface(*it);
        }
    }
    for (std::list<NodeGuiPtr>::const_iterator it = activePluginsContext.begin(); it != activePluginsContext.end(); ++it) {
        ViewerNodePtr isViewerNode = (*it)->getNode()->isEffectViewerNode();
        // For viewers, create the viewer interface separately
        if (!isViewerNode) {
            setPluginViewerInterface(*it);
        }
    }


    setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);

    _imp->viewerNode.lock()->setUiContext( getViewer() );

    QTimer::singleShot( 25, _imp->timeLineGui, SLOT(recenterOnBounds()) );


    //Refresh the viewport lock state
    const std::list<ViewerTab*>& viewers = getGui()->getViewersList();
    if ( !viewers.empty() ) {
        ViewerTab* other = viewers.front();
        if ( other->getInternalNode()->isViewersSynchroEnabled() ) {
            double left, bottom, factor, par;
            other->getViewer()->getProjection(&left, &bottom, &factor, &par);
            _imp->viewer->setProjection(left, bottom, factor, par);
            node->setViewersSynchroEnabled(true);
        }
    }

    _imp->cachedFramesThread.reset(new CachedFramesThread(this));
    _imp->cachedFramesThread->start();
}