void KnobGui::onExprChanged(int dimension) { if (_imp->guiRemoved) { return; } KnobPtr knob = getKnob(); std::string exp = knob->getExpression(dimension); reflectExpressionState(dimension,!exp.empty()); if (exp.empty()) { reflectAnimationLevel(dimension, knob->getAnimationLevel(dimension)); } else { NodeSettingsPanel* isNodeSettings = dynamic_cast<NodeSettingsPanel*>(_imp->container); if (isNodeSettings) { NodeGuiPtr node = isNodeSettings->getNode(); if (node) { node->onKnobExpressionChanged(this); } } if (_imp->warningIndicator) { bool invalid = false; QString fullErrTooltip; int dims = knob->getDimension(); for (int i = 0; i < dims; ++i) { std::string err; if (!knob->isExpressionValid(i, &err)) { invalid = true; } if (dims > 1 && invalid) { fullErrTooltip += QString::fromUtf8("<p><b>"); fullErrTooltip += QString::fromUtf8(knob->getDimensionName(i).c_str()); fullErrTooltip += QString::fromUtf8("</b></p>"); } if (!err.empty()) { fullErrTooltip += QString::fromUtf8(err.c_str()); } } if (invalid) { QString toPrepend; toPrepend += QString::fromUtf8("<p>"); toPrepend += QObject::tr("Invalid expression(s), value returned is the underlying curve:"); toPrepend += QString::fromUtf8("</p>"); fullErrTooltip.prepend(toPrepend); setWarningValue(eKnobWarningExpressionInvalid, fullErrTooltip); } else { setWarningValue(eKnobWarningExpressionInvalid, QString()); } } onHelpChanged(); Q_EMIT expressionChanged(); } updateGUI(dimension); }
void Gui::renderViewersAndRefreshKnobsAfterTimelineTimeChange(SequenceTime time, int reason) { TimeLine* timeline = qobject_cast<TimeLine*>( sender() ); if ( timeline != getApp()->getTimeLine().get() ) { return; } assert( QThread::currentThread() == qApp->thread() ); if ( (reason == eTimelineChangeReasonUserSeek) || ( reason == eTimelineChangeReasonDopeSheetEditorSeek) || ( reason == eTimelineChangeReasonCurveEditorSeek) ) { if ( getApp()->checkAllReadersModificationDate(true) ) { return; } } boost::shared_ptr<Project> project = getApp()->getProject(); bool isPlayback = reason == eTimelineChangeReasonPlaybackSeek; ///Refresh all visible knobs at the current time if ( !getApp()->isGuiFrozen() ) { for (std::list<DockablePanel*>::const_iterator it = _imp->openedPanels.begin(); it != _imp->openedPanels.end(); ++it) { NodeSettingsPanel* nodePanel = dynamic_cast<NodeSettingsPanel*>(*it); if (nodePanel) { NodePtr node = nodePanel->getNode()->getNode(); node->getEffectInstance()->refreshAfterTimeChange(isPlayback, time); NodesList children; node->getChildrenMultiInstance(&children); for (NodesList::iterator it2 = children.begin(); it2 != children.end(); ++it2) { (*it2)->getEffectInstance()->refreshAfterTimeChange(isPlayback, time); } } } } ViewerInstance* leadViewer = getApp()->getLastViewerUsingTimeline(); const std::list<ViewerTab*>& viewers = getViewersList(); ///Syncrhronize viewers for (std::list<ViewerTab*>::const_iterator it = viewers.begin(); it != viewers.end(); ++it) { if ( ( (*it)->getInternalNode() == leadViewer ) && isPlayback ) { continue; } if ( (*it)->getInternalNode()->isDoingPartialUpdates() ) { //When tracking, we handle rendering separatly continue; } (*it)->getInternalNode()->renderCurrentFrame(!isPlayback); } } // Gui::renderViewersAndRefreshKnobsAfterTimelineTimeChange
static KnobGuiPtr getKnobGuiForKnob(const NodePtr& selectedNode, const KnobIPtr& knob) { NodeGuiIPtr selectedNodeGuiI = selectedNode->getNodeGui(); assert(selectedNodeGuiI); if (!selectedNodeGuiI) { return KnobGuiPtr(); } NodeGui* selectedNodeGui = dynamic_cast<NodeGui*>( selectedNodeGuiI.get() ); assert(selectedNodeGui); if (!selectedNodeGui) { return KnobGuiPtr(); } NodeSettingsPanel* selectedPanel = selectedNodeGui->getSettingPanel(); bool hadPanelVisible = selectedPanel && !selectedPanel->isClosed(); if (!selectedPanel) { selectedNodeGui->ensurePanelCreated(); selectedPanel = selectedNodeGui->getSettingPanel(); selectedNodeGui->setVisibleSettingsPanel(false); } if (!selectedPanel) { return KnobGuiPtr(); } if (!hadPanelVisible && selectedPanel) { selectedPanel->setClosed(true); } const std::list<std::pair<KnobIWPtr, KnobGuiPtr> >& knobsMap = selectedPanel->getKnobsMapping(); for (std::list<std::pair<KnobIWPtr, KnobGuiPtr> >::const_iterator it = knobsMap.begin(); it != knobsMap.end(); ++it) { if (it->first.lock() == knob) { return it->second; } } return KnobGuiPtr(); }
void Gui::restoreLayout(bool wipePrevious, bool enableOldProjectCompatibility, const GuiLayoutSerialization & layoutSerialization) { ///Wipe the current layout if (wipePrevious) { wipeLayout(); } ///For older projects prior to the layout change, just set default layout. if (enableOldProjectCompatibility) { createDefaultLayout1(); } else { std::list<ApplicationWindowSerialization*> floatingDockablePanels; QDesktopWidget* desktop = QApplication::desktop(); QRect screen = desktop->screenGeometry(); ///now restore the gui layout for (std::list<ApplicationWindowSerialization*>::const_iterator it = layoutSerialization._windows.begin(); it != layoutSerialization._windows.end(); ++it) { QWidget* mainWidget = 0; ///The window contains only a pane (for the main window it also contains the toolbar) if ( (*it)->child_asPane ) { TabWidget* centralWidget = new TabWidget(this); registerPane(centralWidget); restoreTabWidget(centralWidget, *(*it)->child_asPane); mainWidget = centralWidget; } ///The window contains a splitter as central widget else if ( (*it)->child_asSplitter ) { Splitter* centralWidget = new Splitter(this); restoreSplitterRecursive(this, centralWidget, *(*it)->child_asSplitter); mainWidget = centralWidget; } ///The child is a dockable panel, restore it later else if ( !(*it)->child_asDockablePanel.empty() ) { assert(!(*it)->isMainWindow); floatingDockablePanels.push_back(*it); continue; } assert(mainWidget); if (!mainWidget) { continue; } QWidget* window; if ( (*it)->isMainWindow ) { // mainWidget->setParent(_imp->_leftRightSplitter); _imp->_leftRightSplitter->addWidget_mt_safe(mainWidget); window = this; } else { FloatingWidget* floatingWindow = new FloatingWidget(this, this); floatingWindow->setWidget(mainWidget); registerFloatingWindow(floatingWindow); window = floatingWindow; } ///Restore geometry int w = std::min( (*it)->w, screen.width() ); int h = std::min( (*it)->h, screen.height() ); window->resize(w, h); // If the screen size changed, make sure at least 50x50 pixels of the window are visible int x = boost::algorithm::clamp( (*it)->x, screen.left(), screen.right() - 50 ); int y = boost::algorithm::clamp( (*it)->y, screen.top(), screen.bottom() - 50 ); window->move( QPoint(x, y) ); } for (std::list<ApplicationWindowSerialization*>::iterator it = floatingDockablePanels.begin(); it != floatingDockablePanels.end(); ++it) { ///Find the node associated to the floating panel if any and float it assert( !(*it)->child_asDockablePanel.empty() ); if ( (*it)->child_asDockablePanel == kNatronProjectSettingsPanelSerializationName ) { _imp->_projectGui->getPanel()->floatPanel(); } else { ///Find a node with the dockable panel name const NodesGuiList & nodes = getNodeGraph()->getAllActiveNodes(); DockablePanel* panel = 0; for (NodesGuiList::const_iterator it2 = nodes.begin(); it2 != nodes.end(); ++it2) { if ( (*it2)->getNode()->getScriptName() == (*it)->child_asDockablePanel ) { (*it2)->ensurePanelCreated(); NodeSettingsPanel* nodeSettings = (*it2)->getSettingPanel(); if (nodeSettings) { nodeSettings->floatPanel(); panel = nodeSettings; } break; } } if (panel) { FloatingWidget* fWindow = 0; QWidget* w = panel->parentWidget(); while (!fWindow && w) { fWindow = dynamic_cast<FloatingWidget*>(w); w = w->parentWidget(); } assert(fWindow); fWindow->move( QPoint( (*it)->x, (*it)->y ) ); fWindow->resize( std::min( (*it)->w, screen.width() ), std::min( (*it)->h, screen.height() ) ); } } } } } // restoreLayout
PickKnobDialog::PickKnobDialog(DockablePanel* panel, QWidget* parent) : QDialog(parent) , _imp( new PickKnobDialogPrivate(panel) ) { NodeSettingsPanel* nodePanel = dynamic_cast<NodeSettingsPanel*>(panel); assert(nodePanel); if (!nodePanel) { throw std::logic_error("PickKnobDialog::PickKnobDialog()"); } NodeGuiPtr nodeGui = nodePanel->getNodeGui(); NodePtr node = nodeGui->getNode(); NodeGroupPtr isGroup = node->isEffectNodeGroup(); NodeCollectionPtr collec = node->getGroup(); NodeGroupPtr isCollecGroup = toNodeGroup(collec); NodesList collectNodes = collec->getNodes(); for (NodesList::iterator it = collectNodes.begin(); it != collectNodes.end(); ++it) { if ((*it)->isActivated() && (*it)->getNodeGui() && ( (*it)->getKnobs().size() > 0 ) ) { _imp->allNodes.push_back(*it); } } if (isCollecGroup) { _imp->allNodes.push_back( isCollecGroup->getNode() ); } if (isGroup) { NodesList groupnodes = isGroup->getNodes(); for (NodesList::iterator it = groupnodes.begin(); it != groupnodes.end(); ++it) { if ( (*it)->getNodeGui() && (*it)->isActivated() && ( (*it)->getKnobs().size() > 0 ) ) { _imp->allNodes.push_back(*it); } } } QStringList nodeNames; for (NodesList::iterator it = _imp->allNodes.begin(); it != _imp->allNodes.end(); ++it) { QString name = QString::fromUtf8( (*it)->getLabel().c_str() ); nodeNames.push_back(name); } nodeNames.sort(); _imp->mainLayout = new QGridLayout(this); _imp->selectNodeLabel = new Label( tr("Node:") ); _imp->nodeSelectionCombo = new CompleterLineEdit(nodeNames, nodeNames, false, this); _imp->nodeSelectionCombo->setToolTip( NATRON_NAMESPACE::convertFromPlainText(tr("Input the name of a node in the current project."), NATRON_NAMESPACE::WhiteSpaceNormal) ); _imp->nodeSelectionCombo->setFocus(Qt::PopupFocusReason); _imp->knobSelectionCombo = new ComboBox(this); QObject::connect( _imp->knobSelectionCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onKnobComboIndexChanged(int)) ); QString useAliasTt = NATRON_NAMESPACE::convertFromPlainText(tr("If checked, an alias of the selected parameter will be created, coyping entirely its state. " "Only the script-name, label and tooltip will be editable.\n" "For choice parameters this will also " "dynamically refresh the menu entries when the original parameter's menu is changed.\n" "When unchecked, a simple expression will be set linking the two parameters, but things such as dynamic menus " "will be disabled."), NATRON_NAMESPACE::WhiteSpaceNormal); _imp->useAliasLabel = new Label(tr("Make Alias:"), this); _imp->useAliasLabel->setToolTip(useAliasTt); _imp->useAliasCheckBox = new QCheckBox(this); _imp->useAliasCheckBox->setToolTip(useAliasTt); _imp->useAliasCheckBox->setChecked(true); QObject::connect( _imp->nodeSelectionCombo, SIGNAL(itemCompletionChosen()), this, SLOT(onNodeComboEditingFinished()) ); _imp->destPageLabel = new Label(tr("Page:"), this); QString pagett = NATRON_NAMESPACE::convertFromPlainText(tr("Select the page into which the parameter will be created."), NATRON_NAMESPACE::WhiteSpaceNormal); _imp->destPageLabel->setToolTip(pagett); _imp->destPageCombo = new ComboBox(this); _imp->destPageCombo->setToolTip(pagett); QObject::connect( _imp->destPageCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onPageComboIndexChanged(int)) ); const KnobsVec& knobs = node->getKnobs(); for (std::size_t i = 0; i < knobs.size(); ++i) { if ( knobs[i]->isUserKnob() ) { KnobPagePtr isPage = toKnobPage(knobs[i]); if (isPage) { _imp->pages.push_back(isPage); _imp->destPageCombo->addItem( QString::fromUtf8( isPage->getName().c_str() ) ); } else { KnobGroupPtr isGrp = toKnobGroup(knobs[i]); if (isGrp) { _imp->groups.push_back(isGrp); } } } } if (_imp->destPageCombo->count() == 0) { _imp->destPageLabel->hide(); _imp->destPageCombo->hide(); } _imp->groupLabel = new Label(tr("Group:"), this); QString grouptt = NATRON_NAMESPACE::convertFromPlainText(tr("Select the group into which the parameter will be created."), NATRON_NAMESPACE::WhiteSpaceNormal); _imp->groupCombo = new ComboBox(this); _imp->groupLabel->setToolTip(grouptt); _imp->groupCombo->setToolTip(grouptt); onPageComboIndexChanged(0); _imp->buttons = new DialogButtonBox(QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel), Qt::Horizontal, this); QObject::connect( _imp->buttons, SIGNAL(accepted()), this, SLOT(accept()) ); QObject::connect( _imp->buttons, SIGNAL(rejected()), this, SLOT(reject()) ); _imp->mainLayout->addWidget(_imp->selectNodeLabel, 0, 0, 1, 1); _imp->mainLayout->addWidget(_imp->nodeSelectionCombo, 0, 1, 1, 1); _imp->mainLayout->addWidget(_imp->knobSelectionCombo, 0, 2, 1, 1); _imp->mainLayout->addWidget(_imp->useAliasLabel, 1, 0, 1, 1); _imp->mainLayout->addWidget(_imp->useAliasCheckBox, 1, 1, 1, 1); _imp->mainLayout->addWidget(_imp->destPageLabel, 2, 0, 1, 1); _imp->mainLayout->addWidget(_imp->destPageCombo, 2, 1, 1, 1); _imp->mainLayout->addWidget(_imp->groupLabel, 2, 2, 1, 1); _imp->mainLayout->addWidget(_imp->groupCombo, 2, 3, 1, 1); _imp->mainLayout->addWidget(_imp->buttons, 3, 0, 1, 3); QTimer::singleShot( 25, _imp->nodeSelectionCombo, SLOT(showCompleter()) ); }