#endif
return true;
}
+
+bool ModuleBase_MetaWidget::focusTo(const std::string& theAttributeName)
+{
+ #ifdef _DEBUG
+ std::cout << "ModuleBase_MetaWidget::focusTo"
+ << myWrappedWidget->metaObject()->className() << std::endl;
+ #endif
+ return true;
+}
+
+QList<QWidget*> ModuleBase_MetaWidget::getControls() const
+{
+ return QList<QWidget*>();
+}
//! Interface for loading widget's data from the data model
MODULEBASE_EXPORT virtual bool restoreValue(boost::shared_ptr<ModelAPI_Feature> theFeature);
+ /// Set focus to the current widget if it corresponds to the given attribute
+ /// \param theAttribute name
+ MODULEBASE_EXPORT virtual bool focusTo(const std::string& theAttributeName);
+
+ /// Returns list of widget controls
+ /// \return a control list
+ virtual QList<QWidget*> getControls() const;
+
private:
QWidget* myWrappedWidget;
};
#include <boost/shared_ptr.hpp>
class ModelAPI_Feature;
+class QKeyEvent;
/**\class ModuleBase_ModelWidget
* \brief An abstract custom widget class. This class realization is assumed to create some controls.
virtual bool restoreValue(boost::shared_ptr<ModelAPI_Feature> theFeature) = 0;
+ /// Set focus to the current widget if it corresponds to the given attribute
+ /// \param theAttribute name
+ virtual bool focusTo(const std::string& theAttributeName) = 0;
+
+ /// Returns list of widget controls
+ /// \return a control list
+ virtual QList<QWidget*> getControls() const = 0;
signals:
/// The signal about widget values changed
void valuesChanged();
+ /// The signal about key release on the control, that corresponds to the attribute
+ /// \param theAttributeName a name of the attribute
+ /// \param theEvent key release event
+ void keyReleased(const std::string& theAttributeName, QKeyEvent* theEvent);
};
#endif
class ModelAPI_Feature;
class ModelAPI_Document;
+class QKeyEvent;
+
/*!
\class ModuleBase_Operation
* \brief Base class for all operations
/// Stores a custom value in model.
void storeCustomValue();
+ virtual void keyReleased(std::string theName, QKeyEvent* theEvent) {};
+
protected:
/// Virtual method called when operation started (see start() method for more description)
/// Default impl calls corresponding slot and commits immediately.
#include <QGridLayout>
#include <QDoubleSpinBox>
#include <QLabel>
+#include <QEvent>
+#include <QKeyEvent>
#include <cfloat>
#include <climits>
connect(myYSpin, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged()));
}
+ myXSpin->installEventFilter(this);
+ myYSpin->installEventFilter(this);
}
ModuleBase_WidgetPoint2D::~ModuleBase_WidgetPoint2D()
return true;
}
+bool ModuleBase_WidgetPoint2D::focusTo(const std::string& theAttributeName)
+{
+ if (theAttributeName != myFeatureAttributeID)
+ return false;
+
+ if (!myXSpin->hasFocus() && !myYSpin->hasFocus()) {
+ myXSpin->setFocus();
+ }
+
+ return true;
+}
+
QWidget* ModuleBase_WidgetPoint2D::getControl() const
{
return myGroupBox;
}
+
+QList<QWidget*> ModuleBase_WidgetPoint2D::getControls() const
+{
+ QList<QWidget*> aControls;
+ aControls.push_back(myXSpin);
+ aControls.push_back(myYSpin);
+
+ return aControls;
+}
+
+bool ModuleBase_WidgetPoint2D::eventFilter(QObject *theObject, QEvent *theEvent)
+{
+ if (theObject == myXSpin || theObject == myYSpin) {
+ if (theEvent->type() == QEvent::KeyRelease) {
+ emit keyReleased(myFeatureAttributeID, (QKeyEvent*) theEvent);
+ return true;
+ }
+ }
+ return ModuleBase_ModelWidget::eventFilter(theObject, theEvent);
+}
virtual bool restoreValue(boost::shared_ptr<ModelAPI_Feature> theFeature);
+ /// Set focus to the current widget if it corresponds to the given attribute
+ /// \param theAttribute name
+ virtual bool focusTo(const std::string& theAttributeName);
+
/// Returns the internal parent wiget control, that can be shown anywhere
/// \returns the widget
QWidget* getControl() const;
+ /// Returns list of widget controls
+ /// \return a control list
+ virtual QList<QWidget*> getControls() const;
+
+ virtual bool eventFilter(QObject *theObject, QEvent *theEvent);
+
private:
std::string myFeatureAttributeID; ///< the identifier of the feature attribute
QGroupBox* myGroupBox; ///< the parent group box for all intenal widgets
#include <XGUI_ActionsMgr.h>
#include <XGUI_ViewerProxy.h>
#include <XGUI_ContextMenuMgr.h>
+#include <XGUI_PropertyPanel.h>
#include <Config_PointerMessage.h>
#include <Config_ModuleReader.h>
XGUI_OperationMgr* anOperationMgr = myWorkshop->operationMgr();
+ connect(anOperationMgr, SIGNAL(operationStarted()),
+ this, SLOT(onOperationStarted()));
+
connect(anOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
this, SLOT(onOperationStopped(ModuleBase_Operation*)));
sendOperation(anOperation);
}
+void PartSet_Module::onOperationStarted()
+{
+ PartSet_OperationSketchBase* aPreviewOp = dynamic_cast<PartSet_OperationSketchBase*>(
+ myWorkshop->operationMgr()->currentOperation());
+ if (aPreviewOp) {
+ XGUI_PropertyPanel* aPropPanel = myWorkshop->propertyPanel();
+ connect(aPreviewOp, SIGNAL(focusActivated(const std::string&)),
+ aPropPanel, SLOT(onFocusActivated(const std::string&)));
+ }
+}
+
void PartSet_Module::onOperationStopped(ModuleBase_Operation* theOperation)
{
if (!theOperation)
return;
PartSet_OperationSketchBase* aPreviewOp = dynamic_cast<PartSet_OperationSketchBase*>(theOperation);
if (aPreviewOp) {
+ XGUI_PropertyPanel* aPropPanel = myWorkshop->propertyPanel();
+ disconnect(aPreviewOp, SIGNAL(focusActivated(const std::string&)),
+ aPropPanel, SLOT(onFocusActivated(const std::string&)));
}
}
public slots:
void onFeatureTriggered();
+ /// SLOT, that is called after the operation is started. Connect on the focus activated signal
+ void onOperationStarted();
/// SLOT, that is called after the operation is stopped. Switched off the modfications performed
/// by the operation start
void onOperationStopped(ModuleBase_Operation* theOperation);
/// SLOT, that is called by the key in the viewer is clicked.
/// \param theEvent the mouse event
- void onKeyRelease(QKeyEvent*);
+ void onKeyRelease(QKeyEvent* theEvent);
/// SLOT, to apply to the current viewer the operation
/// \param theX the X projection value
#include <V3d_View.hxx>
+#include <QKeyEvent>
+
#ifdef _DEBUG
#include <QDebug>
#endif
break;
}
}
+
+void PartSet_OperationSketchBase::keyReleased(std::string theName, QKeyEvent* theEvent)
+{
+ keyReleased(theEvent->key());
+}
/// \param theKey a key value
virtual void keyReleased(const int theKey);
+ virtual void keyReleased(std::string theName, QKeyEvent* theEvent);
+
signals:
+ /// signal about the request to launch operation
+ /// theName the operation name
+ /// theFeature the operation argument
+ void launchOperation(std::string theName, boost::shared_ptr<ModelAPI_Feature> theFeature);
+ /// signal about the focus activated
+ /// theName the attribute name
+ void focusActivated(const std::string& theAttibuteName);
+
/// Signal about the feature construing is finished
/// \param theFeature the result feature
/// \param theMode the mode of the feature modification
/// Signal about the features should be selected
/// \param theSelected the list of selected presentations
void featureSelected(const std::list<XGUI_ViewerPrs>& theSelected);
- /// signal about the request to launch operation
- /// theName the operation name
- /// theFeature the operation argument
- void launchOperation(std::string theName, boost::shared_ptr<ModelAPI_Feature> theFeature);
/// signal to enable/disable multi selection in the viewer
/// \param theEnabled the boolean state
void multiSelectionEnabled(bool theEnabled);
#include <gp_Lin.hxx>
#include <XGUI_ViewerPrs.h>
+#include <XGUI_Constants.h>
#include <SketchPlugin_Line.h>
setLinePoint(feature(), aX, anY, LINE_ATTR_END);
flushUpdated();
- myPointSelectionMode = SM_SecondPoint;
+ setPointSelectionMode(SM_SecondPoint);
}
break;
case SM_SecondPoint: {
setLinePoint(feature(), aX, anY, LINE_ATTR_END);
flushUpdated();
- myPointSelectionMode = SM_DonePoint;
- }
+ setPointSelectionMode(SM_DonePoint);
+ }
break;
default:
break;
setLinePoint(feature(), aX, anY, LINE_ATTR_START);
setLinePoint(feature(), aX, anY, LINE_ATTR_END);
flushUpdated();
+ emit focusActivated(LINE_ATTR_START);
}
break;
case SM_SecondPoint:
gp_Pnt aPoint = PartSet_Tools::ConvertClickToPoint(theEvent->pos(), theView);
setLinePoint(aPoint, theView, LINE_ATTR_END);
flushUpdated();
+ emit focusActivated(LINE_ATTR_END);
}
break;
case SM_DonePoint:
}
}
+void PartSet_OperationSketchLine::keyReleased(std::string theName, QKeyEvent* theEvent)
+{
+ int aKeyType = theEvent->key();
+ if (!theName.empty() && aKeyType == Qt::Key_Return) {
+ if (theName == LINE_ATTR_START) {
+ setPointSelectionMode(SM_SecondPoint, false);
+ }
+ else if (theName == LINE_ATTR_END) {
+ setPointSelectionMode(SM_DonePoint, false);
+ }
+ }
+ keyReleased(theEvent->key());
+}
+
void PartSet_OperationSketchLine::keyReleased(const int theKey)
{
switch (theKey) {
{
commit();
emit featureConstructed(feature(), FM_Deactivation);
+ emit launchOperation(PartSet_OperationSketchLine::Type(), boost::shared_ptr<ModelAPI_Feature>());
}
- else
- abort();
- emit launchOperation(PartSet_OperationSketchLine::Type(), boost::shared_ptr<ModelAPI_Feature>());
+ //else
+ // abort();
+ //emit launchOperation(PartSet_OperationSketchLine::Type(), boost::shared_ptr<ModelAPI_Feature>());
}
break;
case Qt::Key_Escape: {
void PartSet_OperationSketchLine::startOperation()
{
PartSet_OperationSketchBase::startOperation();
- myPointSelectionMode = !myInitPoint ? SM_FirstPoint : SM_SecondPoint;
+ setPointSelectionMode(!myInitPoint ? SM_FirstPoint : SM_SecondPoint);
+
emit multiSelectionEnabled(false);
}
boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
aPoint->setValue(aX, anY);
}
+
+void PartSet_OperationSketchLine::setPointSelectionMode(const PointSelectionMode& theMode,
+ const bool isToEmitSignal)
+{
+ myPointSelectionMode = theMode;
+ if (isToEmitSignal) {
+ std::string aName;
+ switch (theMode) {
+ case SM_FirstPoint:
+ aName = LINE_ATTR_START;
+ break;
+ case SM_SecondPoint:
+ aName = LINE_ATTR_END;
+ break;
+ case SM_DonePoint:
+ aName = XGUI::PROP_PANEL_OK;
+ break;
+ default:
+ break;
+ }
+ emit focusActivated(aName);
+ }
+}
class GeomDataAPI_Point2D;
class QMouseEvent;
+class QKeyEvent;
/*!
\class PartSet_OperationSketchLine
/// \param theKey a key value
virtual void keyReleased(const int theKey);
+ virtual void keyReleased(std::string theName, QKeyEvent* theEvent);
+
protected:
/// \brief Virtual method called when operation is started
/// Virtual method called when operation started (see start() method for more description)
///< Structure to lists the possible types of point selection modes
enum PointSelectionMode {SM_FirstPoint, SM_SecondPoint, SM_DonePoint};
+ ///< Set the point selection mode. Emit signal about focus change if necessary.
+ /// \param theMode a new selection mode
+ /// \param isToEmitSignal the neccessity to emit signal
+ void setPointSelectionMode(const PointSelectionMode& theMode, const bool isToEmitSignal = true);
+
private:
boost::shared_ptr<ModelAPI_Feature> mySketch; ///< the sketch feature
boost::shared_ptr<GeomDataAPI_Point2D> myInitPoint; ///< the first line point
#include "ModuleBase_Operation.h"
#include <QMessageBox>
+#include <QApplication>
+#include <QKeyEvent>
XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent)
: QObject(theParent)
{
+ // listen to Escape signal to stop the current operation
+ qApp->installEventFilter(this);
}
XGUI_OperationMgr::~XGUI_OperationMgr()
return result;
}
+bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent)
+{
+ if (theEvent->type() == QEvent::KeyRelease) {
+ QKeyEvent* aKeyEvent = (QKeyEvent*)theEvent;
+ if (aKeyEvent && aKeyEvent->key() == Qt::Key_Escape) {
+ // TODO: this is Escape button processing when the property panel has empty content,
+ // but the operation should be stopped by the Enter has been clicked
+ onKeyReleased("", aKeyEvent);
+ return true;
+ }
+ }
+ return QObject::eventFilter(theObject, theEvent);
+}
+
void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
{
theOperation->resume();
if (aResultOp)
resumeOperation(aResultOp);
}
+
+void XGUI_OperationMgr::onKeyReleased(const std::string& theName, QKeyEvent* theEvent)
+{
+ ModuleBase_Operation* anOperation = currentOperation();
+ if (anOperation)
+ anOperation->keyReleased(theName, theEvent);
+}
#include <QObject>
#include <QStringList>
+class QKeyEvent;
+
/**\class XGUI_OperationMgr
* \ingroup GUI
* \brief Operation manager. Servers to manupulate to the workshop operations. Contains a stack
///Returns list of all operations IDs
QStringList operationList();
+ virtual bool eventFilter(QObject *theObject, QEvent *theEvent);
+
signals:
/// Signal about an operation is started. It is emitted after the start() of operation is done.
void operationStarted();
/// If there is a suspended operation, restart it.
void onOperationStopped();
+ /// SLOT, that is called by the key in the property panel is clicked.
+ /// \param theName the attribute name
+ /// \param theEvent the mouse event
+ void onKeyReleased(const std::string& theName, QKeyEvent* theEvent);
+
private:
typedef QList<ModuleBase_Operation*> Operations; ///< definition for a list of operations
Operations myOperations; ///< a stack of started operations. The active operation is on top,
#include <QPushButton>
#include <QIcon>
#include <QVBoxLayout>
+#include <QEvent>
+#include <QKeyEvent>
#ifdef _DEBUG
#include <iostream>
aBtnLay->addStretch(1);
aBtn = new QPushButton(QIcon(":pictures/button_ok.png"), "", aFrm);
aBtn->setObjectName(XGUI::PROP_PANEL_OK);
+ aBtn->setToolTip(tr("Ok"));
aBtn->setFlat(true);
aBtnLay->addWidget(aBtn);
+ aBtn->installEventFilter(this);
+
aBtn = new QPushButton(QIcon(":pictures/button_cancel.png"), "", aFrm);
+ aBtn->setToolTip(tr("Cancel"));
aBtn->setObjectName(XGUI::PROP_PANEL_CANCEL);
aBtn->setFlat(true);
aBtnLay->addWidget(aBtn);
myCustomWidget = new QWidget(aContent);
aMainLay->addWidget(myCustomWidget);
aMainLay->addStretch(1);
+
+ aBtn->installEventFilter(this);
}
XGUI_PropertyPanel::~XGUI_PropertyPanel()
void XGUI_PropertyPanel::setModelWidgets(const QList<ModuleBase_ModelWidget*>& theWidgets)
{
myWidgets = theWidgets;
+
+ if (!theWidgets.empty()) {
+
+ QList<ModuleBase_ModelWidget*>::const_iterator anIt = theWidgets.begin(), aLast = theWidgets.end();
+ for (; anIt != aLast; anIt++) {
+ connect(*anIt, SIGNAL(keyReleased(const std::string&, QKeyEvent*)),
+ this, SIGNAL(keyReleased(const std::string&, QKeyEvent*)));
+ }
+ ModuleBase_ModelWidget* aLastWidget = theWidgets.last();
+ if (aLastWidget) {
+ QList<QWidget*> aControls = aLastWidget->getControls();
+ if (!aControls.empty()) {
+ QWidget* aLastControl = aControls.last();
+
+ QPushButton* anOkBtn = findChild<QPushButton*>(XGUI::PROP_PANEL_OK);
+ QPushButton* aCancelBtn = findChild<QPushButton*>(XGUI::PROP_PANEL_CANCEL);
+
+ setTabOrder(aLastControl, anOkBtn);
+ setTabOrder(anOkBtn, aCancelBtn);
+ }
+ }
+ }
+}
+
+bool XGUI_PropertyPanel::eventFilter(QObject *theObject, QEvent *theEvent)
+{
+ QPushButton* anOkBtn = findChild<QPushButton*>(XGUI::PROP_PANEL_OK);
+ QPushButton* aCancelBtn = findChild<QPushButton*>(XGUI::PROP_PANEL_CANCEL);
+ if (theObject == anOkBtn || theObject == aCancelBtn) {
+ if (theEvent->type() == QEvent::KeyRelease) {
+ QKeyEvent* aKeyEvent = (QKeyEvent*)theEvent;
+ if (aKeyEvent && aKeyEvent->key() == Qt::Key_Return) {
+ // TODO: this is enter button processing when the focus is on "Apply" or "Cancel" buttons
+ emit keyReleased("", (QKeyEvent*) theEvent);
+ return true;
+ }
+ }
+ }
+ return QDockWidget::eventFilter(theObject, theEvent);
}
QWidget* XGUI_PropertyPanel::contentWidget()
// the repaint is used here to immediatelly react in GUI to the values change.
repaint();
}
+
+void XGUI_PropertyPanel::onFocusActivated(const std::string& theAttributeName)
+{
+ if (theAttributeName == XGUI::PROP_PANEL_OK) {
+ QPushButton* aBtn = findChild<QPushButton*>(XGUI::PROP_PANEL_OK);
+ aBtn->setFocus();
+ }
+ if (theAttributeName == XGUI::PROP_PANEL_CANCEL) {
+ QPushButton* aBtn = findChild<QPushButton*>(XGUI::PROP_PANEL_CANCEL);
+ aBtn->setFocus();
+ }
+ else {
+ foreach(ModuleBase_ModelWidget* eachWidget, myWidgets) {
+ if (eachWidget->focusTo(theAttributeName))
+ break;
+ }
+ }
+}
#include <QDockWidget>
#include <QList>
+class QKeyEvent;
+
class XGUI_EXPORT XGUI_PropertyPanel: public QDockWidget
{
Q_OBJECT
QWidget* contentWidget();
void setModelWidgets(const QList<ModuleBase_ModelWidget*>& theWidgets);
+ virtual bool eventFilter(QObject *theObject, QEvent *theEvent);
+
public slots:
void updateContentWidget(boost::shared_ptr<ModelAPI_Feature> theFeature);
+ /// slot to set the focus to the widget visualized an attribute with the given name
+ /// \param theAttributteName
+ void onFocusActivated(const std::string& theAttributeName);
+
+signals:
+ /// The signal about key release on the control, that corresponds to the attribute
+ /// \param theAttributeName a name of the attribute
+ /// \param theEvent key release event
+ void keyReleased(const std::string& theAttributeName, QKeyEvent* theEvent);
private:
QWidget* myCustomWidget;
connect(aOkBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onCommitOperation()));
QPushButton* aCancelBtn = myPropertyPanel->findChild<QPushButton*>(XGUI::PROP_PANEL_CANCEL);
connect(aCancelBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onAbortOperation()));
+
+ connect(myPropertyPanel, SIGNAL(keyReleased(const std::string&, QKeyEvent*)),
+ myOperationMgr, SLOT(onKeyReleased(const std::string&, QKeyEvent*)));
}
//******************************************************