From a423a1d70f1030ddbdd7169db23f1248d4893698 Mon Sep 17 00:00:00 2001 From: nds Date: Mon, 19 Oct 2015 18:40:27 +0300 Subject: [PATCH] Enter processing from object browser. --- src/ModuleBase/ModuleBase_DoubleSpinBox.cpp | 39 ++++---- src/ModuleBase/ModuleBase_DoubleSpinBox.h | 18 +++- src/ModuleBase/ModuleBase_ModelWidget.cpp | 24 ++++- src/ModuleBase/ModuleBase_ModelWidget.h | 10 +- .../ModuleBase_WidgetDoubleValue.cpp | 14 ++- src/ModuleBase/ModuleBase_WidgetDoubleValue.h | 2 +- .../ModuleBase_WidgetExprEditor.cpp | 65 ++++++++++++- src/ModuleBase/ModuleBase_WidgetExprEditor.h | 31 +++++- src/PartSet/PartSet_WidgetPoint2d.cpp | 24 ++++- src/PartSet/PartSet_WidgetPoint2d.h | 2 +- src/PartSet/PartSet_WidgetPoint2dDistance.cpp | 13 ++- src/PartSet/PartSet_WidgetPoint2dDistance.h | 2 +- src/XGUI/XGUI_OperationMgr.cpp | 9 +- src/XGUI/XGUI_PropertyPanel.cpp | 97 +++++++++++++++---- src/XGUI/XGUI_PropertyPanel.h | 12 +++ 15 files changed, 298 insertions(+), 64 deletions(-) diff --git a/src/ModuleBase/ModuleBase_DoubleSpinBox.cpp b/src/ModuleBase/ModuleBase_DoubleSpinBox.cpp index e436875bf..46f208ee2 100644 --- a/src/ModuleBase/ModuleBase_DoubleSpinBox.cpp +++ b/src/ModuleBase/ModuleBase_DoubleSpinBox.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -78,7 +79,7 @@ ModuleBase_DoubleSpinBox::ModuleBase_DoubleSpinBox(QWidget* theParent, int thePr SLOT(onTextChanged( const QString& ))); connect(this, SIGNAL(valueChanged(const QString&)), this, SLOT(onValueChanged(const QString&))); - connect(this, SIGNAL(editingFinished()), this, SLOT(onEditingFinished())); + //connect(this, SIGNAL(editingFinished()), this, SLOT(onEditingFinished())); } /*! @@ -200,29 +201,28 @@ QString ModuleBase_DoubleSpinBox::removeTrailingZeroes(const QString& src) const return res; } -#include void ModuleBase_DoubleSpinBox::keyPressEvent(QKeyEvent *theEvent) { - myProcessedEvent = 0; - - bool anIsModified = myIsModified; - QDoubleSpinBox::keyPressEvent(theEvent); - switch (theEvent->key()) { case Qt::Key_Enter: case Qt::Key_Return: { - if (anIsModified) - myProcessedEvent = theEvent; - /*qDebug("ModuleBase_DoubleSpinBox::keyPressEvent"); - if (anIsModified) // we should not perform this event outside - theEvent->setAccepted(true); - else - theEvent->setAccepted(false);*/ + // do not react to the Enter key, the property panel processes it + return; } break; default: break; } + QDoubleSpinBox::keyPressEvent(theEvent); +} + +bool ModuleBase_DoubleSpinBox::focusNextPrevChild(bool theIsNext) +{ + myIsModified = false; + + emit valueStored(); + emit focusNextPrev(); + return QDoubleSpinBox::focusNextPrevChild(theIsNext); } /*! @@ -345,10 +345,15 @@ void ModuleBase_DoubleSpinBox::onValueChanged(const QString& theValue) void ModuleBase_DoubleSpinBox::onEditingFinished() { - myIsModified = false; + //myIsModified = false; } -bool ModuleBase_DoubleSpinBox::isEventProcessed(QKeyEvent* theEvent) +bool ModuleBase_DoubleSpinBox::isModified() const { - return myProcessedEvent && myProcessedEvent == theEvent; + return myIsModified; +} + +void ModuleBase_DoubleSpinBox::clearModified() +{ + myIsModified = false; } diff --git a/src/ModuleBase/ModuleBase_DoubleSpinBox.h b/src/ModuleBase/ModuleBase_DoubleSpinBox.h index 52eb6e3f9..f725c59bc 100644 --- a/src/ModuleBase/ModuleBase_DoubleSpinBox.h +++ b/src/ModuleBase/ModuleBase_DoubleSpinBox.h @@ -49,7 +49,16 @@ Q_OBJECT /// Validate current value virtual QValidator::State validate(QString&, int&) const; - virtual bool isEventProcessed(QKeyEvent* theEvent); + // Returns true if the current value is modified by has not been applyed yet + virtual bool isModified() const; + + // Clears modified state + void clearModified(); + +signals: + /// A signal that is emitted by the "Tab" key event. It is emitted before the key is processed. + void focusNextPrev(); + void valueStored(); protected slots: /// Called on text changed @@ -62,6 +71,11 @@ Q_OBJECT QString removeTrailingZeroes(const QString&) const; virtual void keyPressEvent(QKeyEvent* theEvent); + /// The parent method that processes the "Tab"/"SHIF + Tab" keyboard events + /// Emits a signal about focus change + /// If theIsNext is true, this function searches forward, if next is false, it searches backward. + virtual bool focusNextPrevChild(bool theIsNext); + private: /// Is clear flag bool myCleared; @@ -70,8 +84,6 @@ Q_OBJECT int myPrecision; /// Boolean value whether the spin box content is modified bool myIsModified; - - QKeyEvent* myProcessedEvent; }; #endif diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index 66fe88f12..721c6c7b0 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.cpp +++ b/src/ModuleBase/ModuleBase_ModelWidget.cpp @@ -136,6 +136,28 @@ void ModuleBase_ModelWidget::activate() activateCustom(); } +QWidget* ModuleBase_ModelWidget::getControlAcceptingFocus(const bool isFirst) +{ + QWidget* aControl = 0; + + QList aControls = getControls(); + int aSize = aControls.size(); + + if (isFirst) { + for (int i = 0; i < aSize && !aControl; i++) { + if (aControls[i]->focusPolicy() != Qt::NoFocus) + aControl = aControls[i]; + } + } + else { + for (int i = aSize - 1; i >= 0 && !aControl; i--) { + if (aControls[i]->focusPolicy() != Qt::NoFocus) + aControl = aControls[i]; + } + } + return aControl; +} + void ModuleBase_ModelWidget::setDefaultValue(const std::string& theValue) { myDefaultValue = theValue; @@ -198,7 +220,7 @@ void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj) //blockUpdateViewer(false); } -bool ModuleBase_ModelWidget::isEventProcessed(QKeyEvent* theEvent) +bool ModuleBase_ModelWidget::processEnter() { return false; } diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index 8804fdbeb..c805502d1 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -120,6 +120,11 @@ Q_OBJECT /// \return a control list virtual QList getControls() const = 0; + /// Returns the first or the last control that can accept the focus + /// \param isFirst if true, the first controls is returned or the last one + /// \return a control from a list of controls + QWidget* getControlAcceptingFocus(const bool isFirst); + /// FocusIn events processing virtual bool eventFilter(QObject* theObject, QEvent *theEvent); @@ -162,7 +167,7 @@ Q_OBJECT bool isEditingMode() const { return myIsEditing; } /// Returns true if the event is processed. - virtual bool isEventProcessed(QKeyEvent* theEvent); + virtual bool processEnter(); /// Sends Update and Redisplay for the given object /// \param theObj is updating object @@ -202,6 +207,9 @@ signals: /// The signal about value state modification void valueStateChanged(); + void focusNextPrev(); + void valueStored(); + protected: /// Sets default value of widget. Normally, widget should fetch this value /// from the xml. However, some widgets derived widgets could define it diff --git a/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp b/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp index 49f2588d1..2159c8125 100644 --- a/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp +++ b/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp @@ -89,8 +89,10 @@ ModuleBase_WidgetDoubleValue::ModuleBase_WidgetDoubleValue(QWidget* theParent, aControlLay->addRow(myLabel, mySpinBox); #ifdef APPLY_BY_ENTER_OR_TAB // Apply widget value change by enter/tab event. - connect(mySpinBox, SIGNAL(editingFinished()), this, SIGNAL(valuesChanged())); + //connect(mySpinBox, SIGNAL(editingFinished()), this, SIGNAL(valuesChanged())); + connect(mySpinBox, SIGNAL(valueStored()), this, SIGNAL(valuesChanged())); connect(mySpinBox, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesModified())); + connect(mySpinBox, SIGNAL(focusNextPrev()), this, SIGNAL(focusNextPrev())); #else connect(mySpinBox, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesChanged())); @@ -159,7 +161,13 @@ QList ModuleBase_WidgetDoubleValue::getControls() const return aList; } -bool ModuleBase_WidgetDoubleValue::isEventProcessed(QKeyEvent* theEvent) +bool ModuleBase_WidgetDoubleValue::processEnter() { - return mySpinBox->isEventProcessed(theEvent); + bool isModified = mySpinBox->isModified(); + if (isModified) { + emit valuesChanged(); + mySpinBox->clearModified(); + mySpinBox->selectAll(); + } + return isModified; } diff --git a/src/ModuleBase/ModuleBase_WidgetDoubleValue.h b/src/ModuleBase/ModuleBase_WidgetDoubleValue.h index ec3daae2c..8c1e0a1d8 100644 --- a/src/ModuleBase/ModuleBase_WidgetDoubleValue.h +++ b/src/ModuleBase/ModuleBase_WidgetDoubleValue.h @@ -42,7 +42,7 @@ Q_OBJECT virtual QList getControls() const; /// Returns true if the event is processed. - virtual bool isEventProcessed(QKeyEvent* theEvent); + virtual bool processEnter(); public slots: // Delayed value chnged: when user starts typing something, diff --git a/src/ModuleBase/ModuleBase_WidgetExprEditor.cpp b/src/ModuleBase/ModuleBase_WidgetExprEditor.cpp index 3b3d25c08..2d0e841a4 100644 --- a/src/ModuleBase/ModuleBase_WidgetExprEditor.cpp +++ b/src/ModuleBase/ModuleBase_WidgetExprEditor.cpp @@ -36,7 +36,7 @@ #include ExpressionEditor::ExpressionEditor(QWidget* theParent) -: QPlainTextEdit(theParent), myCompletedAndSelected(false) +: QPlainTextEdit(theParent), myCompletedAndSelected(false), myIsModified(false) { myCompleter = new QCompleter(this); myCompleter->setWidget(this); @@ -52,6 +52,10 @@ ExpressionEditor::ExpressionEditor(QWidget* theParent) this, SLOT(insertCompletion(const QString&))); (void) new QShortcut(QKeySequence(tr("Ctrl+Space", "Complete")), this, SLOT(performCompletion())); + + connect(this, SIGNAL(textChanged()), this, SLOT(onTextChanged())); + + setTabChangesFocus(true); } ExpressionEditor::~ExpressionEditor() @@ -110,6 +114,8 @@ void ExpressionEditor::performCompletion(const QString& theCompletionPrefix) void ExpressionEditor::keyPressEvent(QKeyEvent* theEvent) { + bool anIsModified = myIsModified; + if (myCompletedAndSelected && handledCompletedAndSelected(theEvent)) return; myCompletedAndSelected = false; @@ -117,16 +123,27 @@ void ExpressionEditor::keyPressEvent(QKeyEvent* theEvent) switch (theEvent->key()) { case Qt::Key_Up: case Qt::Key_Down: + case Qt::Key_Escape: case Qt::Key_Enter: case Qt::Key_Return: - case Qt::Key_Escape: theEvent->ignore(); - return; + return; default: myCompleter->popup()->hide(); break; } } + else { + switch (theEvent->key()) { + case Qt::Key_Enter: + case Qt::Key_Return: + // do not react to the Enter key, the property panel processes it + return; + break; + default: + break; + } + } QPlainTextEdit::keyPressEvent(theEvent); } @@ -155,6 +172,16 @@ QString ExpressionEditor::placeHolderText() const return myPlaceHolderText; } +bool ExpressionEditor::isModified() const +{ + return myIsModified; +} + +void ExpressionEditor::clearModified() +{ + myIsModified = false; +} + void ExpressionEditor::paintEvent( QPaintEvent* theEvent ) { QPlainTextEdit::paintEvent( theEvent ); @@ -184,6 +211,20 @@ void ExpressionEditor::paintEvent( QPaintEvent* theEvent ) } } +bool ExpressionEditor::focusNextPrevChild(bool theIsNext) +{ + if (myIsModified) + emit editingFinished(); + emit valueStored(); + emit focusNextPrev(); + return QPlainTextEdit::focusNextPrevChild(theIsNext); +} + +void ExpressionEditor::onTextChanged() +{ + myIsModified = true; + emit valueModified(); +} ModuleBase_WidgetExprEditor::ModuleBase_WidgetExprEditor( QWidget* theParent, @@ -207,7 +248,10 @@ ModuleBase_WidgetExprEditor::ModuleBase_WidgetExprEditor( QWidget* theParent, aMainLay->addWidget(myEditor); this->setLayout(aMainLay); - connect(myEditor, SIGNAL(textChanged()), this, SLOT(onTextChanged())); + connect(myEditor, SIGNAL(valueModified()), this, SIGNAL(valuesModified())); + //connect(myEditor, SIGNAL(editingFinished()), this, SLOT(onTextChanged())); + connect(myEditor, SIGNAL(valueStored()), this, SLOT(onTextChanged())); + connect(myEditor, SIGNAL(focusNextPrev()), this, SIGNAL(focusNextPrev())); } ModuleBase_WidgetExprEditor::~ModuleBase_WidgetExprEditor() @@ -273,7 +317,18 @@ QList ModuleBase_WidgetExprEditor::getControls() const return result; } +bool ModuleBase_WidgetExprEditor::processEnter() +{ + bool isModified = myEditor->isModified(); + if (isModified) { + emit valuesChanged(); + myEditor->clearModified(); + myEditor->selectAll(); + } + return isModified; +} + void ModuleBase_WidgetExprEditor::onTextChanged() { - storeValue(); + emit valuesChanged(); } diff --git a/src/ModuleBase/ModuleBase_WidgetExprEditor.h b/src/ModuleBase/ModuleBase_WidgetExprEditor.h index 39ae98235..56d91029f 100644 --- a/src/ModuleBase/ModuleBase_WidgetExprEditor.h +++ b/src/ModuleBase/ModuleBase_WidgetExprEditor.h @@ -45,6 +45,12 @@ class ExpressionEditor: public QPlainTextEdit /// Returns placeholder list QString placeHolderText() const; + // Returns true if the current value is modified by has not been applyed yet + bool isModified() const; + + // Clears modified state + void clearModified(); + public slots: /// Insert additional string for completion /// \param theCompletion a string to insert @@ -54,6 +60,16 @@ class ExpressionEditor: public QPlainTextEdit /// Perform completion void performCompletion(); + /// A slot for processing text changed event + void onTextChanged(); + +signals: + void editingFinished(); + void valueModified(); + /// A signal that is emitted by the "Tab" key event. It is emitted before the key is processed. + void valueStored(); + void focusNextPrev(); + protected: /// Perform completion by prefix /// \param theCompletionPrefix a prefix for looking for completion @@ -70,11 +86,19 @@ class ExpressionEditor: public QPlainTextEdit /// Redefinition of virtual method virtual void paintEvent( QPaintEvent* ); + /// The parent method that processes the "Tab"/"SHIF + Tab" keyboard events + /// Emits a signal about focus change + /// If theIsNext is true, this function searches forward, if next is false, it searches backward. + virtual bool focusNextPrevChild(bool theIsNext); + private: QStringListModel* myCompleterModel; QCompleter* myCompleter; bool myCompletedAndSelected; QString myPlaceHolderText; + + /// Boolean value whether the spin box content is modified + bool myIsModified; }; /** @@ -99,8 +123,11 @@ class MODULEBASE_EXPORT ModuleBase_WidgetExprEditor : public ModuleBase_ModelWid /// Redefinition of virtual method virtual QList getControls() const; - public slots: - /// A slot for processing text changed event + /// Returns true if the event is processed. + virtual bool processEnter(); + +protected slots: + /// A slot for processing text changed event void onTextChanged(); protected: diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index e69c62cc3..7cdf8cc92 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -92,8 +92,11 @@ PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, #ifdef APPLY_BY_ENTER_OR_TAB // Apply widget value change by enter/tab event. - connect(myXSpin, SIGNAL(editingFinished()), this, SLOT(onValuesChanged())); + //connect(myXSpin, SIGNAL(editingFinished()), this, SLOT(onValuesChanged())); + //connect(myXSpin, SIGNAL(focusNextPrev()), this, SLOT(onValuesChanged())); + connect(myXSpin, SIGNAL(valueStored()), this, SLOT(onValuesChanged())); connect(myXSpin, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesModified())); + connect(myXSpin, SIGNAL(focusNextPrev()), this, SIGNAL(focusNextPrev())); #else connect(myXSpin, SIGNAL(valueChanged(const QString&)), this, SLOT(onValuesChanged())); #endif @@ -111,8 +114,10 @@ PartSet_WidgetPoint2D::PartSet_WidgetPoint2D(QWidget* theParent, #ifdef APPLY_BY_ENTER_OR_TAB // Apply widget value change by enter/tab event. - connect(myYSpin, SIGNAL(editingFinished()), this, SLOT(onValuesChanged())); + //connect(myYSpin, SIGNAL(editingFinished()), this, SLOT(onValuesChanged())); + connect(myYSpin, SIGNAL(valueStored()), this, SLOT(onValuesChanged())); connect(myYSpin, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesModified())); + connect(myYSpin, SIGNAL(focusNextPrev()), this, SIGNAL(focusNextPrev())); #else connect(myYSpin, SIGNAL(valueChanged(const QString&)), this, SLOT(onValuesChanged())); #endif @@ -476,7 +481,18 @@ void PartSet_WidgetPoint2D::onValuesChanged() emit valuesChanged(); } -bool PartSet_WidgetPoint2D::isEventProcessed(QKeyEvent* theEvent) +bool PartSet_WidgetPoint2D::processEnter() { - return myXSpin->isEventProcessed(theEvent) || myXSpin->isEventProcessed(theEvent); + bool isModified = myXSpin->isModified() || myYSpin->isModified(); + if (isModified) { + bool isXModified = myXSpin->isModified(); + emit valuesChanged(); + myXSpin->clearModified(); + myYSpin->clearModified(); + if (isXModified) + myXSpin->selectAll(); + else + myYSpin->selectAll(); + } + return isModified; } diff --git a/src/PartSet/PartSet_WidgetPoint2d.h b/src/PartSet/PartSet_WidgetPoint2d.h index 6662ab7eb..d2e5741cd 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.h +++ b/src/PartSet/PartSet_WidgetPoint2d.h @@ -85,7 +85,7 @@ Q_OBJECT double y() const; /// Returns true if the event is processed. - virtual bool isEventProcessed(QKeyEvent* theEvent); + virtual bool processEnter(); signals: /// Signal about selection of an existing vertex from an object diff --git a/src/PartSet/PartSet_WidgetPoint2dDistance.cpp b/src/PartSet/PartSet_WidgetPoint2dDistance.cpp index 15061b90c..2e665cf97 100644 --- a/src/PartSet/PartSet_WidgetPoint2dDistance.cpp +++ b/src/PartSet/PartSet_WidgetPoint2dDistance.cpp @@ -38,7 +38,8 @@ PartSet_WidgetPoint2dDistance::PartSet_WidgetPoint2dDistance(QWidget* theParent, // Reconnect to local slot #ifdef APPLY_BY_ENTER_OR_TAB // Apply widget value change by enter/tab event. - disconnect(mySpinBox, SIGNAL(editingFinished()), this, SIGNAL(valuesChanged())); + //disconnect(mySpinBox, SIGNAL(editingFinished()), this, SIGNAL(valuesChanged())); + disconnect(mySpinBox, SIGNAL(valueStored()), this, SIGNAL(valuesChanged())); connect(mySpinBox, SIGNAL(editingFinished()), this, SLOT(onValuesChanged())); connect(mySpinBox, SIGNAL(valueChanged(double)), this, SIGNAL(valuesModified())); #else @@ -140,7 +141,13 @@ void PartSet_WidgetPoint2dDistance::onValuesChanged() emit valuesChanged(); } -bool PartSet_WidgetPoint2dDistance::isEventProcessed(QKeyEvent* theEvent) +bool PartSet_WidgetPoint2dDistance::processEnter() { - return mySpinBox->isEventProcessed(theEvent); + bool isModified = mySpinBox->isModified(); + if (isModified) { + emit valuesChanged(); + mySpinBox->clearModified(); + mySpinBox->selectAll(); + } + return isModified; } diff --git a/src/PartSet/PartSet_WidgetPoint2dDistance.h b/src/PartSet/PartSet_WidgetPoint2dDistance.h index 7dc45bcca..857212aca 100644 --- a/src/PartSet/PartSet_WidgetPoint2dDistance.h +++ b/src/PartSet/PartSet_WidgetPoint2dDistance.h @@ -60,7 +60,7 @@ Q_OBJECT void setSketch(CompositeFeaturePtr theSketch) { mySketch = theSketch; } /// Returns true if the event is processed. - virtual bool isEventProcessed(QKeyEvent* theEvent); + virtual bool processEnter(); public slots: /// Process of mouse move diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index 215f5f214..cc3fe0521 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -9,6 +9,8 @@ #include "XGUI_Workshop.h" #include "XGUI_ErrorMgr.h" +#include +#include #include "ModuleBase_Operation.h" #include "ModuleBase_IWorkshop.h" #include "ModuleBase_IModule.h" @@ -417,10 +419,10 @@ void XGUI_OperationMgr::onOperationStopped() } } -#include -#include bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent) { + qDebug("XGUI_OperationMgr::onKeyReleased"); + QObject* aSender = sender(); // Let the manager decide what to do with the given key combination. @@ -429,10 +431,11 @@ bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent) switch (theEvent->key()) { case Qt::Key_Return: case Qt::Key_Enter: { + qDebug("XGUI_OperationMgr::onKeyReleased: Key_Return"); ModuleBase_Operation* aOperation = currentOperation(); ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); ModuleBase_ModelWidget* aActiveWgt = aPanel->activeWidget(); - if (!aActiveWgt || !aActiveWgt->isEventProcessed(theEvent)) { + if (!aActiveWgt || !aActiveWgt->processEnter()) { ModuleBase_OperationFeature* aFOperation = dynamic_cast(currentOperation()); if (!aFOperation || myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty()) { emit keyEnterReleased(); diff --git a/src/XGUI/XGUI_PropertyPanel.cpp b/src/XGUI/XGUI_PropertyPanel.cpp index 89b9461f5..4154cfb68 100644 --- a/src/XGUI/XGUI_PropertyPanel.cpp +++ b/src/XGUI/XGUI_PropertyPanel.cpp @@ -116,19 +116,8 @@ void XGUI_PropertyPanel::setModelWidgets(const QList& t this, SLOT(activateNextWidget(ModuleBase_ModelWidget*))); connect(aWidget, SIGNAL(keyReleased(QKeyEvent*)), this, SIGNAL(keyReleased(QKeyEvent*))); - } - ModuleBase_ModelWidget* aLastWidget = theWidgets.last(); - if (aLastWidget) { - QList aControls = aLastWidget->getControls(); - if (!aControls.empty()) { - QWidget* aLastControl = aControls.last(); - - QToolButton* anOkBtn = findChild(PROP_PANEL_OK); - QToolButton* aCancelBtn = findChild(PROP_PANEL_CANCEL); - - setTabOrder(aLastControl, anOkBtn); - setTabOrder(anOkBtn, aCancelBtn); - } + connect(aWidget, SIGNAL(focusNextPrev()), + this, SLOT(onFocusNextPrev())); } } @@ -139,7 +128,6 @@ const QList& XGUI_PropertyPanel::modelWidgets() const ModuleBase_PageBase* XGUI_PropertyPanel::contentWidget() { - return static_cast(myPanelPage); } @@ -185,12 +173,88 @@ void XGUI_PropertyPanel::activateNextWidget(ModuleBase_ModelWidget* theWidget) } } +void XGUI_PropertyPanel::onFocusNextPrev() +{ + setActiveWidget(NULL); +} + +bool XGUI_PropertyPanel::focusNextPrevChild(bool theIsNext) +{ + // it wraps the Tabs clicking to follow in the chain: + // controls, last control, Apply, Cancel, first control, controls + + bool isChangedFocus = false; + if (theIsNext) { // forward by Tab + QToolButton* aCancelBtn = findChild(PROP_PANEL_CANCEL); + if (aCancelBtn->hasFocus()) { + // after cancel, the first control should be focused + QWidget* aFirstControl = 0; + for (int i = 0, aSize = myWidgets.size(); i < aSize && !aFirstControl; i++) + aFirstControl = myWidgets[i]->getControlAcceptingFocus(true); + if (aFirstControl) + aFirstControl->setFocus(); + isChangedFocus = true; + } + else { + // after the last control, the Apply button should be focused + QWidget* aLastControl = 0; + for (int i = myWidgets.size()-1; i >= 0 && !aLastControl; i--) + aLastControl = myWidgets[i]->getControlAcceptingFocus(false); + if (aLastControl && aLastControl->hasFocus()) { + setFocusOnOkButton(); + isChangedFocus = true; + } + } + } + else { // backward by SHIFT + Tab + QToolButton* anOkBtn = findChild(PROP_PANEL_OK); + if (anOkBtn->hasFocus()) { + // after Apply, the last control should be focused + QWidget* aLastControl = 0; + for (int i = myWidgets.size()-1; i >= 0 && !aLastControl; i--) + aLastControl = myWidgets[i]->getControlAcceptingFocus(false); + if (aLastControl) + aLastControl->setFocus(); + isChangedFocus = true; + } + else { + // after the first control, the Cancel button should be focused + QWidget* aFirstControl = 0; + for (int i = 0, aSize = myWidgets.size(); i < aSize && !aFirstControl; i++) + aFirstControl = myWidgets[i]->getControlAcceptingFocus(true); + if (aFirstControl && aFirstControl->hasFocus()) { + QToolButton* aCancelBtn = findChild(PROP_PANEL_CANCEL); + aCancelBtn->setFocus(); + isChangedFocus = true; + } + } + } + + if (!isChangedFocus) + isChangedFocus = ModuleBase_IPropertyPanel::focusNextPrevChild(theIsNext); + + return isChangedFocus; +} + void XGUI_PropertyPanel::activateNextWidget() { activateNextWidget(myActiveWidget); } void XGUI_PropertyPanel::activateWidget(ModuleBase_ModelWidget* theWidget) +{ + // Avoid activation of already actve widget. It could happen on focusIn event many times + setActiveWidget(theWidget); + + if (myActiveWidget) { + emit widgetActivated(myActiveWidget); + } else if (!isEditingMode()) { + emit noMoreWidgets(); + setFocusOnOkButton(); + } +} + +void XGUI_PropertyPanel::setActiveWidget(ModuleBase_ModelWidget* theWidget) { // Avoid activation of already actve widget. It could happen on focusIn event many times if (theWidget == myActiveWidget) { @@ -206,11 +270,6 @@ void XGUI_PropertyPanel::activateWidget(ModuleBase_ModelWidget* theWidget) theWidget->activate(); } myActiveWidget = theWidget; - if (myActiveWidget) { - emit widgetActivated(theWidget); - } else if (!isEditingMode()) { - emit noMoreWidgets(); - } } void XGUI_PropertyPanel::setFocusOnOkButton() diff --git a/src/XGUI/XGUI_PropertyPanel.h b/src/XGUI/XGUI_PropertyPanel.h index 083242fd1..d916f4f64 100644 --- a/src/XGUI/XGUI_PropertyPanel.h +++ b/src/XGUI/XGUI_PropertyPanel.h @@ -114,6 +114,18 @@ Q_OBJECT */ virtual void activateWidget(ModuleBase_ModelWidget* theWidget); + void onFocusNextPrev(); + +protected: + /// Makes the widget active, deactivate the previous, activate and hightlight the given one + /// \param theWidget a widget + void setActiveWidget(ModuleBase_ModelWidget* theWidget); + + /// The parent method that processes the "Tab"/"SHIF + Tab" keyboard events + /// Emits a signal about focus change + /// If theIsNext is true, this function searches forward, if next is false, it searches backward. + virtual bool focusNextPrevChild(bool theIsNext); + protected: /// A header widget QWidget* myHeaderWidget; -- 2.39.2