//---------------------------------------------------------------------------- // $Id: QtRpl/RplFunctionPanel.cpp 2017/07/23 16:20:45 philw $ //---------------------------------------------------------------------------- // // Riverware Qt includes // #include "RplFunctionPanel.hpp" // this module #include "RplFunctionMenus.hpp" #include "qt/ui_RplFunctionPanelWidgets.h" #include "RowOToggles.hpp" #include "RplArgEditDlg.hpp" #include "RplDlgMgr.hpp" #include "RplFrame.hpp" #include "RplGUI.hpp" #include "RplIcons.hpp" #include "RplPrinter.hpp" #include "RplUnitInterpreter.hpp" #include "RwQtIcons.hpp" #include "RwQtUtils.hpp" // // Qt includes // #include #include #include #include #include #include // // Riverware non-GUI includes // #include "DocumentInfo.hpp" #include "InternalFunction.hpp" #include "PolicyGroup.hpp" #include "RplArgList.hpp" #include "RplBlock.hpp" #include "RplDebugger.hpp" #include "RplInterpreter.hpp" #include "RplObj.hpp" #include "RplSet.hpp" #include "RwDocUtils.hpp" #include "Selection.hpp" #include "SimWS.hpp" #include "System.hpp" #include "ValueConstraint.hpp" #include "VisualToken.hpp" #include "rwError.hpp" //--- rwAssert #include "rwStr.hpp" //-------------------------------------------------------------------------- //+class // // CLASS: // RplFunctionPanel // // DESCRIPTION: // Editor dialogs for RplSet objects. // //-------------------------------------------------------------------------- RplFunctionPanel::RplFunctionPanel(RplBaseDlg* parent, RplFunction* rplFunction) : QFrame (parent), RplObjPanel(), _dlg (parent), _initialized(false), _rplFunction (rplFunction), _isPredefined (dynamic_cast(rplFunction) != NULL), _ui (new Ui_RplFunctionPanelWidgets()), _mu (new RplFunctionMenus(this, false)), // not RplViewer _bodyRplFrame (NULL), _constraintRplFrame (NULL), _undoStack(), _bodyLayout (NULL), _toggles (NULL), _showDescriptionToggleIndex (-1), _showNotesToggleIndex(-1), _showPostExecChecksToggleIndex (-1), _showDiagSettingsToggleIndex (-1), _showCommentsToggleIndex (-1) { _ui->setupUi(this); // Note: The client should call 'installMenuBar()'. This is not done // automatically because the new RplViewerDlg will want to do this // on its own (when switching to a RplBlock or RplFunction tab). // Note: Because of a sequence problem (the client dialog hasn't yet // recorded the pointer of this new instance), initialization must be // completed by calling the completeInit() method. (See below). } void RplFunctionPanel::completeInit() { if (!_initialized) { _initialized = true; rplDlgMgr->addRplDlg(_rplFunction, _dlg); initWidgets(); initConnections(); } } void RplFunctionPanel::installMenuBar() { if ( rwAssert (_dlg != NULL) && rwAssert (_mu != NULL) ) { QMenuBar* mbar = _dlg->menuBar(); // [QMainWindow] mbar->clear(); QList menus = _mu->topMenuList(); while (!menus.isEmpty()) mbar->addMenu (menus.takeFirst()); } } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- RplFunctionPanel::~RplFunctionPanel() { // We don't want to be updating our edit actions because the stack changes. _undoStack.blockSignals(true); // We don't want the RplDlgMgr to be updating us or our frames. rplDlgMgr->removeRplDlg(getRplObj(), _dlg); rplDlgMgr->removeRplFrame(_bodyRplFrame); rplDlgMgr->removeRplFrame(_constraintRplFrame); delete _ui; _ui = NULL; delete _mu; _mu = NULL; } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- bool RplFunctionPanel::updateLoadStatus() { // Update the load-related widgets _dlg->updateLoadWidgets(_ui->_loadStateFrame, _ui->_loadButton); return true; //--- success } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- bool RplFunctionPanel::update() { updateLoadStatus(); _ui->_nameEdit->setText(_rplFunction->getName()); _ui->_argumentsEdit->setText(_rplFunction->getArgumentString()); updateDescr(); updateNotes(); QString dlgTypeStr = RplDlgMgr::getObjTypeString(_rplFunction); setWindowTitle (dlgTypeStr + " Editor - \"" + _rplFunction->getParent()->getParent()->getName() + QString(" : ") + _rplFunction->getParent()->getName() + QString(" : ") + QString(_rplFunction->getName()) + "\""); _ui->_beforeExecCheckBox->setChecked(_rplFunction->getPreExecDiagState()); _ui->_afterExecCheckBox->setChecked(_rplFunction->getPostExecDiagState()); _ui->_scaleUnitsEdit->setText(_rplFunction->getDiagUnitsText()); _ui->_rplTypeComboBox->setRplType(_rplFunction->getFunctionType()); // Initialize Icon Button: Show External Document _dlg->initExternalDocButton (_ui->_externalDocPushButton); _dlg->updateExternalDocOps (_ui->_externalDocPushButton, _mu->_extDocMenu, _mu->_viewExtDocAction, _mu->_editExtDocAction); updateBodyRplFrameVisibility(); const RplSet* rplSet (_rplFunction->getSet()); if (rplSet) { // Set RplSet Type Icon Pushbutton const QPixmap setIcon (RplIcons::getObjIcon (rplSet)); const QSize setIconSize (setIcon.size()); _ui->_rplSetTypeIconButton->setText (QString::null); _ui->_rplSetTypeIconButton->setIcon (setIcon); _ui->_rplSetTypeIconButton->setIconSize (setIconSize); _ui->_rplSetTypeIconButton->setFixedSize (setIconSize + QSize (4,4)); _ui->_rplSetTypeIconButton->setAutoDefault (false); _ui->_rplSetTypeIconButton->setDefault (false); _ui->_rplSetTypeIconButton->setToolTip (rplSet->getName()); } _ui->_rplSetTypeIconButton->setVisible (rplSet != NULL); const RplUtilityGroup* rplGrp (_rplFunction->getParent()); if (rplGrp) { // Set RplUtilityGroup Type Icon Pushbutton const QPixmap grpIcon (RplIcons::getObjIcon (rplGrp)); const QSize grpIconSize (grpIcon.size()); _ui->_rplGroupTypeIconButton->setText (QString::null); _ui->_rplGroupTypeIconButton->setIcon (grpIcon); _ui->_rplGroupTypeIconButton->setIconSize (grpIconSize); _ui->_rplGroupTypeIconButton->setFixedSize (grpIconSize + QSize (4,4)); _ui->_rplGroupTypeIconButton->setAutoDefault (false); _ui->_rplGroupTypeIconButton->setDefault (false); _ui->_rplGroupTypeIconButton->setToolTip (rplGrp->getName()); } _ui->_rplGroupTypeIconButton->setVisible ( SHOW_RPL_GROUP_TYPE_ICON_BUTTON && (rplGrp != NULL)); // Set RplObj Type Icon Label _ui->_rplObjTypeIconLabel->setText (QString::null); _ui->_rplObjTypeIconLabel->setPixmap ( RplIcons::getObjIcon(_rplFunction, rplSet)); return true; //--- success } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- bool RplFunctionPanel::updateDescr() { const QString objText = _rplFunction->getDescription(); const QString widText = _ui->_descrEdit->toPlainText(); if (!_dlg->_inDescrEdit && (objText != widText)) { //------------------------------------------------- const bool saveIsSetting = _dlg->_settingDescrEdit; _dlg->_settingDescrEdit = true; //------------------------------------------------- const int saveVertPos = _ui->_descrEdit->verticalScrollBar()->value(); _ui->_descrEdit->setText (objText); _ui->_descrEdit->verticalScrollBar()->setValue (saveVertPos); //------------------------------------------------- _dlg->_settingDescrEdit = saveIsSetting; //------------------------------------------------- } if (!_isPredefined) { updateDescriptionToggleRelevance(); } return true; } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- bool RplFunctionPanel::updateNotes() { const QString objText = _rplFunction->getNotes(); const QString widText = _ui->_notesEdit->toPlainText(); if (!_dlg->_inNotesEdit && (objText != widText)) { const bool saveIsSetting = _dlg->_settingNotesEdit; _dlg->_settingNotesEdit = true; const int saveVertPos = _ui->_notesEdit->verticalScrollBar()->value(); _ui->_notesEdit->setText(objText); _ui->_notesEdit->verticalScrollBar()->setValue(saveVertPos); _dlg->_settingNotesEdit = saveIsSetting; } if (!_isPredefined) { updateNotesToggleRelevance(); } return true; } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- bool RplFunctionPanel::rebuild() { update(); return true; //--- success } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::updateEditActions() { // Note: For predefined functions, some fields are never editable. bool editsOkGlobally(rplDlgMgr->objEditsAllowed()); bool appIsOpt(_rplFunction && _rplFunction->appIsOpt()); _ui->_nameEdit -> setReadOnly (_isPredefined || !editsOkGlobally); _ui->_descrEdit -> setReadOnly (_isPredefined || !editsOkGlobally); _ui->_notesEdit -> setReadOnly (_isPredefined || !editsOkGlobally); _ui->_notesEdit -> setVisible (!_isPredefined); _ui->_argumentsEdit -> setReadOnly (_isPredefined || !editsOkGlobally); _ui->_editArgsButton -> setEnabled (!_isPredefined && editsOkGlobally); _ui->_rplTypeComboBox -> setEnabled (!_isPredefined && editsOkGlobally); _ui->_beforeExecCheckBox -> setEnabled (editsOkGlobally); _ui->_afterExecCheckBox -> setEnabled (editsOkGlobally); _ui->_scaleUnitsEdit -> setEnabled (editsOkGlobally && !appIsOpt); _mu->_newSetAction -> setEnabled (editsOkGlobally); _mu->_newGlobFuncSetAction -> setEnabled (editsOkGlobally); _mu->_saveSetAction -> setEnabled (editsOkGlobally); _mu->_saveSetAsAction -> setEnabled (editsOkGlobally); _mu->_undoAction -> setEnabled (!_isPredefined && editsOkGlobally && _undoStack.canUndo()); _mu->_redoAction -> setEnabled (!_isPredefined && editsOkGlobally && _undoStack.canRedo()); _mu->_addMinConstraintAction -> setEnabled (!_isPredefined); _mu->_addMaxConstraintAction -> setEnabled (!_isPredefined); _mu->_addMinErrorAction -> setEnabled (!_isPredefined); _mu->_addMaxErrorAction -> setEnabled (!_isPredefined); _mu->_checkValidityAction -> setEnabled (!_isPredefined); _mu->_showPostExecChecksAction -> setEnabled (!_isPredefined); _mu->_showDescriptionAction -> setEnabled (!_isPredefined); _mu->_showNotesAction -> setEnabled (!_isPredefined); // One can only toggle the time varying status of user-defined // functions with more than one argument. bool timeVarToggleOk(_rplFunction && (_rplFunction->getArguments()->numArgs() == 0) && !_isPredefined && editsOkGlobally); _mu->_setTimeVaryingAction->setEnabled(timeVarToggleOk); // We update our frames before we start asking them questions // (most edit actions apply to the frame with the selection, // which might be neither of our frames). if (_bodyRplFrame) { _bodyRplFrame->updateEditActions(); } if (_constraintRplFrame) { _constraintRplFrame->updateEditActions(); } _mu->_cutAction ->setEnabled(!_isPredefined && editsOkGlobally && (_bodyRplFrame ->deleteEnabled() || _constraintRplFrame->deleteEnabled())); _mu->_copyAction ->setEnabled(!_isPredefined && (_bodyRplFrame ->copyEnabled() || _constraintRplFrame->copyEnabled())); _mu->_pasteAction ->setEnabled(!_isPredefined && editsOkGlobally && (_bodyRplFrame ->pasteEnabled() || _constraintRplFrame->pasteEnabled())); _mu->_deleteAction->setEnabled(!_isPredefined && editsOkGlobally && (_bodyRplFrame ->deleteEnabled() || _constraintRplFrame->deleteEnabled())); _mu->_enableAction->setEnabled(!_isPredefined && editsOkGlobally && (_bodyRplFrame ->enableEnabled() || _constraintRplFrame->enableEnabled())); _mu->_insertAction->setEnabled(!_isPredefined && editsOkGlobally && (_bodyRplFrame ->insertEnabled() || _constraintRplFrame->insertEnabled())); _mu->_appendAction->setEnabled(!_isPredefined && editsOkGlobally && (_bodyRplFrame ->appendEnabled() || _constraintRplFrame->appendEnabled())); // I figure we might as well always provide access to the palette, // even if they might not currently be able to edit with it. _mu->_paletteAction-> setEnabled (true); _ui->_loadButton->setEnabled(!rplDebugger->isExecutionPaused()); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::rplSetTypeIconButton_clicked() { static const char (*mname) ("RplFunctionPanel::rplSetTypeIconButton_clicked"); // std::cout << mname << std::endl; RplSet* rplSet (_rplFunction->getSet()); if (rplSet) { // NOTE: Using the BaseRWDlg parenting on these dialog doesn't work, // because we don't want the deletion behavior. rplDlgMgr->openRplDlgSelectRplObjViewRow (rplSet, _rplFunction, NULL); } } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::rplGroupTypeIconButton_clicked() { static const char (*mname) ("RplFunctionPanel::rplGroupTypeIconButton_clicked"); // std::cout << mname << std::endl; RplUtilityGroup* rplGrp (_rplFunction->getParent()); if (rplGrp) { // NOTE: Using the BaseRWDlg parenting on these dialog doesn't work, // because we don't want the deletion behavior. rplDlgMgr->openRplDlgSelectRplObjViewRow (rplGrp, _rplFunction, NULL); } } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::returnTypeHandler() { _rplFunction->setFunctionType(_ui->_rplTypeComboBox->getRplType()); rplDlgMgr->updateDlgs(_rplFunction, _rplFunction->getSet(), RplDlgMgr::RPL_EDIT_ARGS); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::argsHandler() { static bool alreadyInHandler = false; if (alreadyInHandler) return; // Parse. RplInterpreter *interpreter = RplInterpreter::Instance(); interpreter->clearErrors (); const QString editText = _ui->_argumentsEdit->text().trimmed(); const QString oldText = _rplFunction->getArgumentString(); // Don't bother, if nothing has changed if (editText == oldText) return; const QByteArray editBytes = editText.toLatin1(); RplArgList* argList = interpreter->parseArgList(editBytes); const int errCnt = interpreter->getNumErrors(); // Bringing up a warning dialog may cause us to lose/gain focus again // which is unnecessary. So don't let this handler recurse. alreadyInHandler = true; if ( errCnt != 0 ) { QMessageBox::warning(_dlg, tr ("Parse Error"), tr ("Invalid argument(s): ") + interpreter->getErrorText()); if ( argList != NULL ) { delete argList; } // Restore the original value to the text field _ui->_argumentsEdit->setText(oldText); } else { _rplFunction->setArguments (argList); rplDlgMgr->updateDlgs(_rplFunction, _rplFunction->getSet(), RplDlgMgr::RPL_EDIT_ARGS); } // Disable/enable things that rely on number of arguments. updateEditActions(); // Conditionally enable External Document menu and actions. const bool supportsDoc = DocumentInfo::supportsExternalDoc (_rplFunction); _mu->_extDocMenu->setEnabled (supportsDoc); alreadyInHandler = false; } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::editArgsButtonHandler() { const QPixmap funcIcon (RplIcons::getObjIcon (_rplFunction)); // Present a modal dialog for editing the arguments. RplArgEditDlg rplArgEditDlg(_rplFunction->getName(), funcIcon, _rplFunction->getArguments()); rplArgEditDlg.exec(); _rplFunction->setArguments(new RplArgList(rplArgEditDlg.args())); _ui->_argumentsEdit->setText(_rplFunction->getArgumentString()); rplDlgMgr->updateDlgs(_rplFunction, _rplFunction->getSet(), RplDlgMgr::RPL_EDIT_ARGS); // Disable/enable things that rely on number of arguments. updateEditActions(); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::diagnosticsHandler() { _rplFunction->setPreExecDiagState(_ui->_beforeExecCheckBox->isChecked()); _rplFunction->setPostExecDiagState(_ui->_afterExecCheckBox->isChecked()); updateDiagSettingsToggleRelevance(); // Don't need to update any other dialogs } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::unitsHandler() { // Because the user often incorrectly types in square brackets and // quotes, and the RplUnit intepreter will silently ignore these, // and possibly parse something unintended or defer the problem to // load time, we get rid of problem characters right off the bat. // For more information, see Bug 3948. QString unitStr (_ui->_scaleUnitsEdit->text()); QString correctedUnitsString( RplUnitInterpreter::removeBogusChars(unitStr)); if (correctedUnitsString != unitStr) { _ui->_scaleUnitsEdit->setText(correctedUnitsString); } if (!_rplFunction->setDiagUnits(correctedUnitsString)) { QMessageBox::warning(_dlg, tr ("Error"), tr ("Invalid diagnostic units specified.")); } rplDlgMgr->updateDlgs(_rplFunction, _rplFunction->getSet(), RplDlgMgr::RPL_EDIT_ARGS); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::showOptionalFrames() { _ui->_diagGroupBox->setVisible(_mu->_showDiagnosticsAction->isChecked()); if (!_isPredefined) { _ui->_descrGroupBox->setVisible( _mu->_showDescriptionAction->isChecked()); _ui->_notesGroupBox->setVisible( _mu->_showNotesAction->isChecked()); _ui->_checksGroupBox->setVisible( _mu->_showPostExecChecksAction->isChecked()); if (_mu->_showPostExecChecksAction->isChecked()) _constraintRplFrame->reformat(); _toggles->setToggleOn(_showDescriptionToggleIndex, _mu->_showDescriptionAction->isChecked()); _toggles->setToggleOn(_showNotesToggleIndex, _mu->_showNotesAction->isChecked()); _toggles->setToggleOn(_showPostExecChecksToggleIndex, _mu->_showPostExecChecksAction->isChecked()); } else { _ui->_notesGroupBox->setVisible(false); } _toggles->setToggleOn(_showDiagSettingsToggleIndex, _mu->_showDiagnosticsAction->isChecked()); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::addMinConstraint() { _mu->_showPostExecChecksAction->setChecked(true); _constraintRplFrame->addMinConstraint(); showOptionalFrames(); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::addMaxConstraint() { _mu->_showPostExecChecksAction->setChecked(true); _constraintRplFrame->addMaxConstraint(); showOptionalFrames(); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::addMinError() { _mu->_showPostExecChecksAction->setChecked(true); _constraintRplFrame->addMinError(); showOptionalFrames(); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::addMaxError() { _mu->_showPostExecChecksAction->setChecked(true); _constraintRplFrame->addMaxError(); showOptionalFrames(); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::setTimeVarying(bool on) { _mu->_setTimeVaryingAction->setChecked(on); _rplFunction->setTimeVarying(on); // If the function is time invariant, we show them a warning message // in the status bar (which is otherwise hidden). if (on) { _dlg->statusBar()->hide(); } else { _dlg->statusBar()->show(); } } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::setBreakBeforeEval(bool doBreak) { RplDebugger::Location where(_rplFunction, NULL, RplDebugger::BEFORE_EXEC); RplDebugger::Breakpoint breakpoint(where, true); if (doBreak) { rplDebugger->addBreakpoint(breakpoint); } else { rplDebugger->removeBreakpoint(breakpoint); } if (_bodyRplFrame) { _bodyRplFrame->reformat(); } } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::setBreakAfterEval(bool doBreak) { RplDebugger::Location where(_rplFunction, NULL, RplDebugger::AFTER_EXEC); RplDebugger::Breakpoint breakpoint(where, true); if (doBreak) { rplDebugger->addBreakpoint(breakpoint); } else { rplDebugger->removeBreakpoint(breakpoint); } if (_bodyRplFrame) { _bodyRplFrame->reformat(); } } void RplFunctionPanel::printPredefined() { if (_ui->_descrWebView == NULL) { QApplication::beep(); return; //------>> } _ui->_descrWebView->printWebView(); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::initConnections() { connect(_ui->_rplSetTypeIconButton, SIGNAL (clicked()), SLOT (rplSetTypeIconButton_clicked())); connect(_ui->_rplGroupTypeIconButton, SIGNAL (clicked()), SLOT (rplGroupTypeIconButton_clicked())); // Now redundant with the 'config' methods in RplBaseDlg. // //-- connect(_mu->_newSetAction, SIGNAL(triggered()), //-- SLOT(newRplSetHandler())); //-- connect(_mu->_openSetAction, SIGNAL(triggered()), //-- SLOT(openRplSetHandler())); //-- connect(_mu->_saveSetAction, SIGNAL(triggered()), //-- SLOT(saveRplSetHandler())); //-- connect(_mu->_saveSetAsAction, SIGNAL(triggered()), //-- SLOT(saveRplSetAsHandler())); connect (_mu->_newGlobFuncSetAction, SIGNAL(triggered()), _dlg, SLOT (newGlobFuncSetHandler())); connect (_mu->_openGlobFuncSetAction, SIGNAL(triggered()), _dlg, SLOT (openGlobFuncSetHandler())); if (_isPredefined) { connect(_mu->_printRplSetAction, SIGNAL(triggered()), SLOT(printPredefined())); } else { connect(_mu->_printRplSetAction, SIGNAL(triggered()), _dlg, SLOT(printHandler())); } connect(_mu->_closeAction, SIGNAL(triggered()), _dlg, SLOT(close())); connect(_mu->_refreshAction, SIGNAL(triggered()), _dlg, SLOT(refreshHandler())); connect(_mu->_showDescriptionAction, SIGNAL(triggered(bool)), SLOT(showOptionalFrames())); connect(_mu->_showNotesAction, SIGNAL(triggered(bool)), SLOT(showOptionalFrames())); connect(_mu->_showDiagnosticsAction, SIGNAL(triggered(bool)), SLOT(showOptionalFrames())); connect(_mu->_showCommentsAction, SIGNAL(triggered(bool)), _bodyRplFrame, SLOT(setShowComments(bool))); // Some menus need to be updated before they are shown. connect(_mu->_editMenu, SIGNAL(aboutToShow()), SLOT(aboutToShowEditMenu())); connect(_mu->_viewMenu, SIGNAL(aboutToShow()), SLOT(aboutToShowViewMenu())); connect(_mu->_funcMenu, SIGNAL(aboutToShow()), SLOT(aboutToShowFunctionMenu())); if (!_isPredefined) { connect(_mu->_cutAction, SIGNAL(triggered()), _bodyRplFrame, SLOT(cut())); connect(_mu->_copyAction, SIGNAL(triggered()), _bodyRplFrame, SLOT(copy())); connect(_mu->_pasteAction, SIGNAL(triggered()), _bodyRplFrame, SLOT(paste())); connect(_mu->_deleteAction, SIGNAL(triggered()), _bodyRplFrame, SLOT(deleteHandler())); connect(_mu->_enableAction, SIGNAL(triggered(bool)), _bodyRplFrame, SLOT(enableHandler(bool))); connect(_mu->_cutAction, SIGNAL(triggered()), _constraintRplFrame, SLOT (cut())); connect(_mu->_copyAction, SIGNAL(triggered()), _constraintRplFrame, SLOT (copy())); connect(_mu->_pasteAction, SIGNAL(triggered()), _constraintRplFrame, SLOT (paste())); connect(_mu->_deleteAction, SIGNAL(triggered()), _constraintRplFrame, SLOT (deleteHandler())); connect(_mu->_enableAction, SIGNAL(triggered(bool)), _constraintRplFrame, SLOT (enableHandler(bool))); connect(_mu->_insertAction, SIGNAL(triggered()), _constraintRplFrame, SLOT (insertStmt())); connect(_mu->_appendAction, SIGNAL(triggered()), _constraintRplFrame, SLOT (appendStmt())); connect(_mu->_addMinConstraintAction,SIGNAL(triggered()), SLOT(addMinConstraint())); connect(_mu->_addMaxConstraintAction,SIGNAL(triggered()), SLOT(addMaxConstraint())); connect(_mu->_addMinErrorAction,SIGNAL(triggered()), SLOT(addMinError())); connect(_mu->_addMaxErrorAction,SIGNAL(triggered()), SLOT(addMaxError())); connect(_mu->_setTimeVaryingAction, SIGNAL(toggled(bool)), SLOT(setTimeVarying(bool))); connect(_mu->_showPostExecChecksAction, SIGNAL(triggered(bool)), SLOT(showOptionalFrames())); connect(_mu->_checkValidityAction, SIGNAL(triggered()), _dlg, SLOT(checkValidityHandler())); connect(_ui->_nameEdit, SIGNAL(returnPressed()), _dlg, SLOT(nameHandler())); connect(_ui->_nameEdit, SIGNAL(editingFinished()), _dlg, SLOT(nameHandler())); connect(_ui->_descrEdit, SIGNAL(textChanged()), _dlg, SLOT(descriptionHandler())); connect(_ui->_notesEdit, SIGNAL(textChanged()), _dlg, SLOT(notesHandler())); connect(_ui->_argumentsEdit, SIGNAL(returnPressed()), SLOT(argsHandler())); connect(_ui->_argumentsEdit, SIGNAL(editingFinished()), SLOT(argsHandler())); connect(_mu->_undoAction, SIGNAL(triggered()), &_undoStack, SLOT(undo())); connect(_mu->_redoAction, SIGNAL(triggered()), &_undoStack, SLOT(redo())); connect(&_undoStack, SIGNAL(canUndoChanged(bool)), SLOT(updateEditActions())); connect(&_undoStack, SIGNAL(canRedoChanged(bool)), SLOT(updateEditActions())); connect(_mu->_showCommentsAction, SIGNAL(triggered(bool)), _constraintRplFrame, SLOT(setShowComments(bool))); } connect(_mu->_searchReplaceAction, SIGNAL(triggered()), _dlg, SLOT(openSearchReplaceDlgHandler())); connect(_mu->_displaySettingsAction, SIGNAL(triggered()), _dlg, SLOT(openDisplaySettingsDlgHandler())); connect(_mu->_setAnalysisAction, SIGNAL(triggered()), _dlg, SLOT(openAnalysisDlgHandler())); connect(_mu->_compareSetAction, SIGNAL(triggered()), _dlg, SLOT(compareSetHandler())); connect(_mu->_paletteAction, SIGNAL(triggered()), _dlg, SLOT(openPaletteHandler())); connect(_mu->_closeAllEditorsAction, SIGNAL(triggered()), _dlg, SLOT(closeOtherEditors())); connect(_mu->_setEditorAction, SIGNAL(triggered()), _dlg, SLOT(openRplSetDlg())); _mu->_openDebuggerDlgAction->setIcon(RplIcons::bug()); connect(_mu->_openDebuggerDlgAction, SIGNAL(triggered()), _dlg, SLOT(openDebuggerDlgHandler())); connect(_ui->_externalDocPushButton, SIGNAL(clicked()), _dlg, SLOT(externalDocButtonHandler())); connect(_ui->_loadButton, SIGNAL(clicked()), _dlg, SLOT(loadButtonHandler())); connect(_ui->_scaleUnitsEdit, SIGNAL(returnPressed()), SLOT(unitsHandler())); connect(_ui->_scaleUnitsEdit, SIGNAL(editingFinished()), SLOT(unitsHandler())); connect(_ui->_beforeExecCheckBox, SIGNAL(toggled(bool)), SLOT(diagnosticsHandler())); connect(_ui->_afterExecCheckBox, SIGNAL(toggled(bool)), SLOT(diagnosticsHandler())); connect(_ui->_rplTypeComboBox, SIGNAL(valueChanged(RplValue::Type_ID)), SLOT(returnTypeHandler())); if (!_isPredefined) { connect(_mu->_viewExtDocAction, SIGNAL(triggered()), _dlg, SLOT(viewExternalDocHandler())); connect(_mu->_editExtDocAction, SIGNAL(triggered()), _dlg, SLOT(editExternalDocHandler())); connect(_mu->_configExtDocAction, SIGNAL(triggered()), _dlg, SLOT(configureExternalDocHandler())); connect(_mu->_fileTypeAssocAction, SIGNAL(triggered()), _dlg, SLOT(fileTypeAssocHandler())); connect(_ui->_editArgsButton, SIGNAL(clicked()), SLOT(editArgsButtonHandler())); } connect(_mu->_breakBeforeEvalAction, SIGNAL(triggered(bool)), SLOT(setBreakBeforeEval(bool))); connect(_mu->_breakAfterEvalAction, SIGNAL(triggered(bool)), SLOT(setBreakAfterEval(bool))); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::initWidgets() { // description web view is hidden by default. _ui->_descrWebView->hide(); resize(QSize(485, 300).expandedTo(minimumSizeHint())); const QString funcName = _rplFunction ? _rplFunction->getName() : QString(); InternalFunction *internalFunction = dynamic_cast(_rplFunction); if (internalFunction) { _bodyRplFrame = new RplFrame(_undoStack, _rplFunction, true, _ui->_bodyPlaceholderWidget); // We want the frame to take up all available space. _bodyRplFrame->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding)); _ui->_editArgsButton->setIcon(QIcon(RwQtIcons::edit())); _ui->_editArgsButton->setText(QString::null); } else if (_isPredefined) { rwDebugAssert (dynamic_cast(_rplFunction)); _ui->_descrGroupBox->show(); _ui->_descrEdit->hide(); const QByteArray htmlBytes = RwDocUtils::rplPredefinedFuncHtml (funcName); const QUrl baseUrl = RwDocUtils::rplFuncDocBaseUrl(); const QString baseUrlStr = baseUrl.toString(); baseUrlStr; // (avoid compilation warning) // std::cout << mname << " [#" << callCnt << "]" // << " " << htmlCnt << " bytes." // << "\n ... baseUrl \"" << qPrintable (baseUrlStr) << "\"" // << std::endl; _ui->_descrWebView->setDocName (funcName); if (baseUrl.isEmpty()) _ui->_descrWebView->setHtml (htmlBytes); else _ui->_descrWebView->setHtml (htmlBytes, baseUrl); // Hide RPL Predefined Function Number _ui->_descrWebView->showHideInlineElementsByClass ( "RplFunc_Num", false); // DON'T show _ui->_descrWebView->show(); _ui->_checksGroupBox->hide(); _ui->_editArgsButton->hide(); _mu->_extDocMenu->menuAction()->setVisible(false); _bodyRplFrame = new RplFrame(_undoStack, _rplFunction, true, _ui->_bodyPlaceholderWidget); // The body frame only needs to be as high as the minimal special content const QSizePolicy fixedHgt (QSizePolicy::Preferred, QSizePolicy::Fixed); _bodyRplFrame->setSizePolicy(fixedHgt); _ui->_bodyPlaceholderWidget->setSizePolicy(fixedHgt); QSplitter* split = _ui->_bodyVertSplitter; const int splitCnt = split->count(); const int inx1 = split->indexOf (_ui->_bodyPlaceholderWidget); const int inx2 = split->indexOf (_ui->_checksGroupBox); const int inx3 = split->indexOf (_ui->_descrGroupBox); if ( rwAssert (inx1 >= 0) && rwAssert (inx2 >= 0) && rwAssert (inx3 >= 0) ) { split->setStretchFactor (inx1, 0); // stretch==0 split->setStretchFactor (inx2, 0); // stretch==0 split->setStretchFactor (inx3, 1); // stretch==1 } // Disable splitter handles for (int splitInx = 0; splitInx < splitCnt; ++splitInx) { QSplitterHandle* splitHandle = split->handle(splitInx); splitHandle->setEnabled(false); } } else { rwDebugAssert(false); // Unsupported object type. } _bodyLayout = new QVBoxLayout; _bodyLayout->setContentsMargins(0, 0, 0, 0); // l,t,r,b _bodyLayout->addWidget(_bodyRplFrame); _ui->_bodyPlaceholderWidget->setLayout(_bodyLayout); // // Initialize the value constraints frame // if (!_isPredefined) { _constraintRplFrame = new RplFrame(_undoStack, _rplFunction, false, _ui->_checksGroupBox); _constraintRplFrame->setCanShowDebuggingDecorations(false); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(_constraintRplFrame); layout->setContentsMargins(9, 5, 9, 5); // l,t,r,b _ui->_checksGroupBox->setLayout(layout); // If we have any value constraints, then show this frame _mu->_showPostExecChecksAction->setChecked( _rplFunction->getValueConstraintCount() != 0); } // // Deal with the function's "constant in run" property, // which we present to the user as "time varying" or not. // Indicating that a function is time invariant is a dangerous setting, // so when this is the setting we emphasize it in the status bar. // QLabel* warning = new QLabel(tr(" Warning: this function is time invariant."), this); RwQtUtils::setFgColor (warning, Qt::red); _dlg->statusBar()->addWidget(warning, true /* = permanent */ ); if (!_isPredefined) { setTimeVarying(_rplFunction->isTimeVarying()); } _dlg->configureCloseDlgsButton (_ui->_closeDlgsButton); initForApplication(); if (_isPredefined) { QVBoxLayout* vbox = new QVBoxLayout (_ui->_belowBodyVertSplitterBox); vbox->setContentsMargins (0,0,0,0); // l,t,r,b initVisibilityToggles(vbox); } else { initVisibilityToggles(_bodyLayout); } _ui->_belowBodyVertSplitterBox->setVisible(_isPredefined); showOptionalFrames(); _dlg->updateExternalDocOps (_ui->_externalDocPushButton, _mu->_extDocMenu, _mu->_viewExtDocAction, _mu->_editExtDocAction); update(); updateBodyRplFrameVisibility (true); // force updateEditActions(); // For testing, display the undo command stack. // QUndoView* undoView = new QUndoView(&_undoStack); // undoView->setWindowTitle(tr("Undo/Redo Command List")); // undoView->show(); // undoView->setAttribute(Qt::WA_QuitOnClose, false); } // // Add a horizontal row of visibility toggles (check boxes which // control the display of optionally displayed aspects of this dialog). // void RplFunctionPanel::initVisibilityToggles(QVBoxLayout* containingLayout) { _toggles = new RowOToggles(this, tr("Show: ")); containingLayout->addWidget(_toggles); if (!_isPredefined) { _showPostExecChecksToggleIndex = _toggles->addToggle(tr("Post-Exec. Checks")); _showDescriptionToggleIndex = _toggles->addToggle(tr("Description")); _showNotesToggleIndex = _toggles->addToggle(tr("Notes")); _showCommentsToggleIndex = _toggles->addToggle(tr("Comments")); _toggles->setToggleOn(_showDescriptionToggleIndex, _mu->_showDescriptionAction->isChecked()); _toggles->setToggleOn(_showNotesToggleIndex, _mu->_showNotesAction->isChecked()); _toggles->setToggleOn(_showPostExecChecksToggleIndex, _mu->_showPostExecChecksAction->isChecked()); _toggles->setToggleOn(_showCommentsToggleIndex, _bodyRplFrame->showComments()); } _showDiagSettingsToggleIndex = _toggles->addToggle(tr("Diagnostic Settings")); _toggles->setToggleOn(_showDiagSettingsToggleIndex, _mu->_showDiagnosticsAction->isChecked()); // Notice when the user clicks a toggle. connect(_toggles, SIGNAL(stateChanged(int, bool)), this, SLOT(visibilityToggleChangedHandler(int, bool))); // The state of most toggles are updated in showOptionalFrames(), // but inline comments are different. if (!_isPredefined) { connect(_bodyRplFrame, SIGNAL(showCommentsChanged(bool)), this, SLOT(showCommentsChangedHandler(bool))); } // Each toggle provides a visual indication of whether there is non-trivial // content in the item whose display is controlled by the toggle. if (!_isPredefined) { updateDescriptionToggleRelevance(); updateNotesToggleRelevance(); updatePostExecConstraintsToggleRelevance(); updateCommentsToggleRelevance(); // Note: we maintain the appearance of some toggles using signals // directly, but others are updated in signal handler methods. connect(_bodyRplFrame, SIGNAL(editted()), this, SLOT(updateCommentsToggleRelevance())); connect(_constraintRplFrame, SIGNAL(editted()), this, SLOT(updateCommentsToggleRelevance())); connect(_constraintRplFrame, SIGNAL(editted()), this, SLOT(updatePostExecConstraintsToggleRelevance())); } updateDiagSettingsToggleRelevance(); } void RplFunctionPanel::updateBodyRplFrameVisibility (bool force /*=false*/) { const bool debugEna = rplDebugger && rplDebugger->isDebuggingEnabled(); const bool wantVis = !_isPredefined || debugEna; const bool isVis = _ui->_bodyPlaceholderWidget->isVisible(); if (force || (isVis != wantVis)) { _ui->_bodyPlaceholderWidget->setVisible (wantVis); } } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::initForApplication() { const RplApplication::Type appType = _rplFunction->getLocalAppType(); _ui->_loadButton->setVisible ( appType == RplApplication::RBS || appType == RplApplication::OPT ); _dlg->configNewSetAction (appType, _mu->_newSetAction); _dlg->configOpenSetAction (appType, _mu->_openSetAction); _dlg->configSaveSetAction (appType, _mu->_saveSetAction); _dlg->configSaveSetAsAction (appType, _mu->_saveSetAsAction); _dlg->configReopenSetMenu (appType, _mu->_reopenSetMenu); if (appType == RplApplication::GLOBAL) { // The New/Open/Reopen menu items are redundant with the menu items // already customized to the current RplApplication::Type. _mu->_newGlobFuncSetAction -> setVisible (false); _mu->_openGlobFuncSetAction -> setVisible (false); _mu->_reopenGlobFuncSetMenu -> setVisible (false); QAction* mAction (_mu->_reopenGlobFuncSetMenu->menuAction()); if (mAction) mAction -> setVisible (false); } else { _dlg->configReopenGlobFuncSetMenu (_mu->_reopenGlobFuncSetMenu); } _dlg->updateFileMenuAppText(_mu->_printRplSetAction, _mu->_closeAction); QString setEditorText = RplDlgMgr::getObjTypeString(_rplFunction->getSet()) + " Editor..."; _mu->_setEditorAction->setText(setEditorText); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::loadSettings() { } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- void RplFunctionPanel::saveSettings() const { } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // public, virtual from RplBaseDlg void RplFunctionPanel::updateExternalDocButton() { _dlg->initExternalDocButton (_ui->_externalDocPushButton); } // public, virtual from RplBaseDlg void RplFunctionPanel::debuggerStateChanged() { updateBodyRplFrameVisibility(); } //---------------------------------------------------------------------------- // Update actions in the view menu. //---------------------------------------------------------------------------- void RplFunctionPanel::aboutToShowViewMenu() { _mu->_showCommentsAction->setChecked(_bodyRplFrame->showComments()); _dlg->updateExternalDocOps (_ui->_externalDocPushButton, _mu->_extDocMenu, _mu->_viewExtDocAction, _mu->_editExtDocAction); } //---------------------------------------------------------------------------- // Update actions in the edit menu. //---------------------------------------------------------------------------- void RplFunctionPanel::aboutToShowEditMenu() { // Which edit actions are available is fairly dynamic, depending for // example on the state of the run and the current selection, so we // update the enabled state of the edit actions every time. updateEditActions(); // Also the toggle state of the enabled action depends on the selection. _mu->_enableAction->setChecked(true); _bodyRplFrame ->updateEnableAction(_mu->_enableAction); _constraintRplFrame->updateEnableAction(_mu->_enableAction); } //---------------------------------------------------------------------------- // Update actions in the Function menu. //---------------------------------------------------------------------------- void RplFunctionPanel::aboutToShowFunctionMenu() { // Get the statuses of the breakpoints from the RPL debugger. RplDebugger::Location before(_rplFunction, NULL, RplDebugger::BEFORE_EXEC); RplDebugger::Location after (_rplFunction, NULL, RplDebugger::AFTER_EXEC); bool breakBefore(rplDebugger->hasBreakpoint(before)); bool breakAfter (rplDebugger->hasBreakpoint(after)); _mu->_breakBeforeEvalAction->setChecked(breakBefore); _mu->_breakAfterEvalAction ->setChecked(breakAfter); // Okay to add/remove breakpoints if debugging is enabled. bool debuggingEnabled(rplDebugger->isDebuggingEnabled()); _mu->_breakBeforeEvalAction->setEnabled(debuggingEnabled); _mu->_breakAfterEvalAction ->setEnabled(debuggingEnabled); } // The GUI's idea of the object's name (as opposed to the object's name). QString RplFunctionPanel::nameEditorText() const { return _ui->_nameEdit->text(); } // // If our body frame includes the debug cursor (location at which debugging // is currently paused), scroll that cursor into view. // // Note: it's not possible to pause in our value constraint frame. // void RplFunctionPanel::scrollToDebugCursor() { if (_bodyRplFrame) { _bodyRplFrame->scrollToDebugCursor(); } } void RplFunctionPanel::updateDescriptionToggleRelevance() { bool emptyDescription(_ui->_descrEdit->toPlainText().isEmpty()); _toggles->setToggleRelevant(_showDescriptionToggleIndex, !emptyDescription); if ( !emptyDescription ) { QString desc = _ui->_descrEdit->toPlainText(); _toggles->setToggleToolTip( _showDescriptionToggleIndex, desc ); } else { _toggles->setToggleToolTip( _showDescriptionToggleIndex, QString() ); } } void RplFunctionPanel::updateNotesToggleRelevance() { bool emptyNotes(_ui->_notesEdit->toPlainText().isEmpty()); _toggles->setToggleRelevant(_showNotesToggleIndex, !emptyNotes); if (!emptyNotes) { QString notes = _ui->_notesEdit->toPlainText(); _toggles->setToggleToolTip(_showNotesToggleIndex, notes); } else { _toggles->setToggleToolTip(_showNotesToggleIndex, QString()); } } void RplFunctionPanel::updatePostExecConstraintsToggleRelevance() { bool noConstraints(_rplFunction->getValueConstraintCount() == 0); _toggles->setToggleRelevant(_showPostExecChecksToggleIndex, !noConstraints); } void RplFunctionPanel::updateDiagSettingsToggleRelevance() { bool diagOff(!_rplFunction->getPreExecDiagState() && !_rplFunction->getPostExecDiagState()); _toggles->setToggleRelevant(_showDiagSettingsToggleIndex, !diagOff); } void RplFunctionPanel::updateCommentsToggleRelevance() { bool aCommentExists((_bodyRplFrame && _bodyRplFrame->containsAComment()) || (_constraintRplFrame && _constraintRplFrame->containsAComment())); _toggles->setToggleRelevant(_showCommentsToggleIndex, aCommentExists); } void RplFunctionPanel::visibilityToggleChangedHandler(int toggleIndex, bool on) { if (toggleIndex == _showDescriptionToggleIndex) { _mu->_showDescriptionAction->setChecked(on); showOptionalFrames(); } else if (toggleIndex == _showNotesToggleIndex) { _mu->_showNotesAction->setChecked(on); showOptionalFrames(); } else if (toggleIndex == _showPostExecChecksToggleIndex) { _mu->_showPostExecChecksAction->setChecked(on); showOptionalFrames(); } else if (toggleIndex == _showDiagSettingsToggleIndex) { _mu->_showDiagnosticsAction->setChecked(on); showOptionalFrames(); } else if (toggleIndex == _showCommentsToggleIndex) { _bodyRplFrame->setShowComments(on); if (_constraintRplFrame) { _constraintRplFrame->setShowComments(on); } // Note: we don't really need to update the state of the View menu // action because it is updated before the menu is shown, but what // the heck. _mu->_showCommentsAction->setChecked(on); } else { rwDebugAssert(false); } } void RplFunctionPanel::showCommentsChangedHandler(bool show) { _toggles->setToggleOn(_showCommentsToggleIndex, show); } RplParamLineEdit::RplParamLineEdit(QWidget* parent) : QLineEdit(parent) { } void RplParamLineEdit::contextMenuEvent(QContextMenuEvent* event) { QMenu *menu = createStandardContextMenu(); QList actions = menu->actions(); QString actionText; for (int i = 0; i < actions.size(); ++i) { actionText = actions[i]->text(); static const QString COPY("Copy"); if (actionText.contains(COPY)) { connect(actions[i], SIGNAL(triggered()), SLOT(copyTriggeredCustomHandler())); } } menu->exec(event->globalPos()); delete menu; } // private slot void RplParamLineEdit::copyTriggeredCustomHandler() { if (!hasSelectedText()) { return; } // If the selection could be a valid name, slap it in the // RPL clipboard as a name symbol. We actually don't go // to too much trouble to see if it's a valid name, just // make sure it's not-empty and has no spaces. QString selText(selectedText().trimmed()); if (selText.isEmpty() || selText.contains(' ')) { return; } VisualToken nameToken(selText, NULL, VisualToken::NAME_SYMBOL); RplFrame::setCopyBuffer(&nameToken); } // virtual override of BaseRWDlg method void RplFunctionPanel::showDescription(bool) { if (!_mu->_showDescriptionAction->isChecked()) { _mu->_showDescriptionAction->activate(QAction::Trigger); } } // virtual override of BaseRWDlg method void RplFunctionPanel::showNotes(bool) { if (!_mu->_showNotesAction->isChecked()) { _mu->_showNotesAction->activate(QAction::Trigger); } } // virtual override void RplFunctionPanel::selectStringInDescription( const Rpl::SearchSpec& searchSpec) { RplGUI::selectSearchSpecInQTextEdit(searchSpec, _ui->_descrEdit); } // virtual override void RplFunctionPanel::selectStringInNotes( const Rpl::SearchSpec& searchSpec) { RplGUI::selectSearchSpecInQTextEdit(searchSpec, _ui->_notesEdit); } int RplFunctionPanel::renameSymbolInFrames(QString origName, QString newName) { int numSymbolsRenamed = 0; numSymbolsRenamed += _bodyRplFrame->renameSymbol(origName, newName); numSymbolsRenamed += _constraintRplFrame->renameSymbol(origName, newName); return numSymbolsRenamed; } // vim:sw=3 ts=3 //--- (end RplFunctionPanel.cpp) ---