Salome HOME
Update viewer after selection clear for OCCT 7.4.0.
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetEditor.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <ModuleBase_WidgetEditor.h>
21 #include <ModuleBase_ParamSpinBox.h>
22 #include <ModuleBase_Tools.h>
23
24 #include <Config_Keywords.h>
25 #include <Config_WidgetAPI.h>
26
27 #include <Events_Loop.h>
28 #include <ModelAPI_Events.h>
29
30 #include <ModelAPI_Feature.h>
31 #include <ModelAPI_Data.h>
32 #include <ModelAPI_Object.h>
33 #include <ModelAPI_AttributeDouble.h>
34
35 #include <GeomDataAPI_Point2D.h>
36
37 #include <QApplication>
38 #include <QKeyEvent>
39 #include <QLineEdit>
40 #include <QMenu>
41 #include <QWidget>
42 #include <QWidgetAction>
43 #include <QRegExp>
44 #include <QRegExpValidator>
45 #include <QDesktopWidget>
46 #include <QDialog>
47 #include <QLayout>
48
49 // Dialog is redefined to avoid Escape key processing
50 class ModuleBase_EditorDialog : public QDialog
51 {
52 public:
53   ModuleBase_EditorDialog(QWidget* theParent, Qt::WindowFlags theFlags)
54     : QDialog(theParent, theFlags)
55   {
56     setMinimumWidth(100);
57   }
58   ~ModuleBase_EditorDialog() {}
59
60 protected:
61   // Do nothing if key pressed because it is processing on operation manager level
62   virtual void keyPressEvent(QKeyEvent* theEvent) {
63     if (theEvent->key() == Qt::Key_Escape)
64         return;
65     QDialog::keyPressEvent(theEvent);
66   }
67 };
68
69 ModuleBase_WidgetEditor::ModuleBase_WidgetEditor(QWidget* theParent,
70                                                  const Config_WidgetAPI* theData)
71 : ModuleBase_WidgetDoubleValue(theParent, theData),
72   myXPosition(-1), myYPosition(-1), myEditorDialog(0)
73 {
74 }
75
76 ModuleBase_WidgetEditor::~ModuleBase_WidgetEditor()
77 {
78 }
79
80 bool ModuleBase_WidgetEditor::editedValue(double theSpinMinValue, double theSpinMaxValue,
81                                           double& outValue, QString& outText)
82 {
83   bool isValueAccepted = false;
84
85   myEditorDialog = new ModuleBase_EditorDialog(QApplication::desktop(), Qt::FramelessWindowHint);
86
87   QHBoxLayout* aLay = new QHBoxLayout(myEditorDialog);
88   aLay->setContentsMargins(2, 2, 2, 2);
89
90   ModuleBase_ParamSpinBox* anEditor = new ModuleBase_ParamSpinBox(myEditorDialog);
91   anEditor->setMinimum(theSpinMinValue);
92   anEditor->setMaximum(theSpinMaxValue);
93
94   QStringList aParameters;
95   ModuleBase_Tools::getParameters(aParameters);
96   anEditor->setCompletionList(aParameters);
97
98   if (outText.isEmpty())
99     anEditor->setValue(outValue);
100   else
101     anEditor->setText(outText);
102
103   aLay->addWidget(anEditor);
104
105   ModuleBase_Tools::setFocus(anEditor, "ModuleBase_WidgetEditor::editedValue");
106   anEditor->selectAll();
107
108   QPoint aPoint = QCursor::pos();
109   if (myXPosition >= 0 && myYPosition >= 0)
110     aPoint = QPoint(myXPosition, myYPosition);
111
112   myEditorDialog->move(aPoint);
113   isValueAccepted = myEditorDialog->exec() == QDialog::Accepted;
114   if (isValueAccepted) {
115     outText = anEditor->text();
116     bool isDouble;
117     double aValue = outText.toDouble(&isDouble);
118     if (isDouble) {
119       outValue = aValue;
120       outText = ""; // return empty string, if it's can be converted to a double
121     }
122   }
123   delete myEditorDialog;
124   myEditorDialog = 0;
125   return isValueAccepted;
126 }
127
128 bool ModuleBase_WidgetEditor::focusTo()
129 {
130   showPopupEditor();
131   return false;
132 }
133
134 bool ModuleBase_WidgetEditor::showPopupEditor(const bool theSendSignals)
135 {
136   bool isValueAccepted = false;
137   // we need to emit the focus in event manually in order to save the widget as an active
138   // in the property panel before the mouse leave event happens in the viewer. The module
139   // ask an active widget and change the feature visualization if the widget is not the current
140   // one.  Also we need this widget as active to provide call of processEnter() applyed
141   // by operation manager to the current widget. If not, the myEditorDialog will stay opened
142   emitFocusInWidget();
143
144   // nds: it seems, that the envents processing is not necessary anymore
145   // White while all events will be processed
146   //QApplication::processEvents();
147   double aValue = mySpinBox->value();
148   QString aText;
149   if (mySpinBox->hasVariable())
150     aText = mySpinBox->text();
151
152   isValueAccepted = editedValue(mySpinBox->minimum(), mySpinBox->maximum(), aValue, aText);
153   if (isValueAccepted) {
154     if (aText.isEmpty()) {
155       if (mySpinBox->hasVariable()) {
156         // variable text should be cleared before setting value as the value
157         // will not be set if there is a varable in control
158         ModuleBase_Tools::setSpinText(mySpinBox, "");
159       }
160       ModuleBase_Tools::setSpinValue(mySpinBox, aValue);
161     } else {
162       ModuleBase_Tools::setSpinText(mySpinBox, aText);
163     }
164     if (theSendSignals) {
165       emit valuesChanged();
166       // the focus leaves the control automatically by the Enter/Esc event
167       // it is processed in operation manager
168       //emit focusOutWidget(this);
169     }
170     else
171       storeValue();
172   }
173   ModuleBase_Tools::setFocus(mySpinBox, "ModuleBase_WidgetEditor::editedValue");
174   mySpinBox->selectAll();
175   // enter is processed, so we need not anymore emit clicked signal
176   //if (theSendSignals && !myIsEditing && isValueAccepted)
177   //  emit enterClicked(this);
178
179   return isValueAccepted;
180 }
181
182 void ModuleBase_WidgetEditor::setCursorPosition(const int theX, const int theY)
183 {
184   myXPosition = theX;
185   myYPosition = theY;
186 }
187
188 bool ModuleBase_WidgetEditor::processEnter()
189 {
190   if (myEditorDialog) {
191     myEditorDialog->accept();
192     return true;
193   }
194
195   return ModuleBase_WidgetDoubleValue::processEnter();
196 }
197
198 bool ModuleBase_WidgetEditor::processEscape()
199 {
200   if (myEditorDialog) {
201     myEditorDialog->reject();
202     return true;
203   }
204
205   return ModuleBase_WidgetDoubleValue::processEscape();
206 }