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()); } }
void BackdropGui::getInitialSize(int *w, int *h) const { *w = TO_DPIX(NATRON_BACKDROP_DEFAULT_WIDTH); *h = TO_DPIY(NATRON_BACKDROP_DEFAULT_HEIGHT); }
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) ); }
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(); } }
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; }
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
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
QSize ScaleSliderQWidget::minimumSizeHint() const { return QSize( TO_DPIX(150), TO_DPIY(20) ); }
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
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(); }