Salome HOME
c7d04b5ca4ec0fcb888feee5e442f2c73241ed36
[modules/med.git] / src / MEDCalc / gui / TestController.cxx
1 // Copyright (C) 2016-2021  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 "TestController.hxx"
21 #include "MEDModule.hxx"
22
23 #include <Basics_Utils.hxx>  // STDLOG() macro
24
25 #include <SUIT_Session.h>
26 #include <SUIT_Desktop.h>
27
28 #include <SALOMEconfig.h>
29 #include CORBA_CLIENT_HEADER(MEDEventListener)
30
31 #include <pqTestUtility.h>
32 #include <pqXMLEventObserver.h>
33 #include <pqXMLEventSource.h>
34
35 #include <pqQVTKWidgetEventPlayer.h>
36 #include <pqQVTKWidgetEventTranslator.h>
37
38 #include <pqTabbedMultiViewWidget.h>
39 #include <pqApplicationCore.h>
40 #include <pqTestingReaction.h>
41 #include <pqSaveScreenshotReaction.h>
42
43 #include <QFileDialog>
44 #include <QString>
45 #include <QDir>
46 #include <QIcon>
47 #include <QTimer>
48 #include <QEvent>
49
50 class PlayTestEvent: public QEvent {
51 public:
52   PlayTestEvent(QEvent::Type type, const std::string & filename): QEvent(type), _filename(filename) {}
53   virtual ~PlayTestEvent() {}
54   const std::string _filename;
55 };
56
57 TestController::TestController(MEDModule* mod):
58   _salomeModule(mod),
59   _desk(SUIT_Session::session()->activeApplication()->desktop()),
60   _tester(0), _lock_action(0),
61   _quitEventType(QEvent::registerEventType()),
62   _playEventType(QEvent::registerEventType()),
63   _aboutToPlayTest(false),
64   _myEventLoopStarted(false)
65 {
66   STDLOG("Creating a TestController");
67   _tester = new pqTestUtility(_desk);
68   _tester->addEventObserver("xml", new pqXMLEventObserver(_desk));
69   _tester->addEventSource("xml", new pqXMLEventSource(_desk));
70
71   QApplication::instance()->installEventFilter(this);
72   //QTimer::singleShot(0, this, SLOT(onMainEventLoopStarting()));
73 }
74
75 TestController::~TestController()
76 {
77   if (_tester)
78     delete _tester;
79   _tester = 0;
80 }
81
82 void
83 TestController::createActions() {
84   //
85   // Main actions
86   //
87   QString label   = tr("LAB_RECORD_TEST");
88   QString tooltip = tr("TIP_RECORD_TEST");
89   int actionId;
90   actionId = _salomeModule->createStandardAction(label,this, SLOT(onRecordTest()),QString(),tooltip);
91
92   // This action has to be placed in the general file menu
93   int menuId = _salomeModule->createMenu( tr( "MEN_FILE" ), -1,  1 );
94   _salomeModule->action(actionId)->setIconVisibleInMenu(false);
95   _salomeModule->createMenu(actionId, menuId, 60);
96
97   label   = tr("LAB_PLAY_TEST");
98   tooltip = tr("TIP_PLAY_TEST");
99   actionId = _salomeModule->createStandardAction(label,this, SLOT(onPlayTest()),QString(),tooltip);
100   _salomeModule->action(actionId)->setIconVisibleInMenu(false);
101   _salomeModule->createMenu(actionId, menuId, 70);
102
103   label   = tr("LAB_LOCK_TEST");
104   tooltip = tr("TIP_LOCK_TEST");
105   actionId = _salomeModule->createStandardAction(label,this, SLOT(onLockViewSize()),QString(),tooltip);
106   _salomeModule->action(actionId)->setIconVisibleInMenu(false);
107   _salomeModule->action(actionId)->setCheckable(true);
108   _lock_action = _salomeModule->action(actionId);
109   _salomeModule->createMenu(actionId, menuId, 70);
110
111   label   = tr("LAB_SNAP_TEST");
112   tooltip = tr("TIP_SNAP_TEST");
113   actionId = _salomeModule->createStandardAction(label,this, SLOT(onTakeSnapshot()),QString(),tooltip);
114   _salomeModule->action(actionId)->setIconVisibleInMenu(false);
115   _salomeModule->createMenu(actionId, menuId, 70);
116 }
117
118 void TestController::onRecordTest()
119 {
120   QString fileName =
121       QFileDialog::getSaveFileName(_desk, "Save test", QString(), QString("XML file (*.xml)"));
122   if (!fileName.isEmpty())
123     {
124       QApplication::setActiveWindow(_desk); //mandatory otherwise record pop up doesn't show up
125       _tester->recordTests(fileName);
126     }
127 }
128
129
130 void TestController::onPlayTest()
131 {
132   QString fileName =
133       QFileDialog::getOpenFileName(_desk, "Open test", QString(), QString("XML file (*.xml)"));
134   if (!fileName.isEmpty())
135     _tester->playTests(fileName);
136 }
137
138 void TestController::onLockViewSize() const
139 {
140   pqTestingReaction::lockViewSize(_lock_action->isChecked());
141 }
142
143 void TestController::onTakeSnapshot() const
144 {
145   pqSaveScreenshotReaction::saveScreenshot();
146 }
147
148 void TestController::onRequestTermination()
149 {
150   // Check if test playing
151   if (_tester->playingTest() || _aboutToPlayTest)
152     {
153       QEvent * e = new QEvent((QEvent::Type)_quitEventType);
154       QApplication::postEvent(this, e);
155     }
156   else
157     {
158       _salomeModule->requestSALOMETermination();
159     }
160 }
161
162 void
163 TestController::customEvent(QEvent * event)
164 {
165   if (event->type() == _quitEventType)
166     {
167       if(!isMainEventLoopStarted())
168           // Repost (=delay)
169           QApplication::postEvent(this, new QEvent((QEvent::Type)_quitEventType));
170       else
171           onRequestTermination();
172     }
173   else if (event->type() == _playEventType)
174     {
175       PlayTestEvent * e = dynamic_cast<PlayTestEvent *>(event);
176       if (e)
177         {
178 //          // Wait for main event loop to start:
179           if(!isMainEventLoopStarted())
180               // Repost (=delay)
181               QApplication::postEvent(this, new PlayTestEvent((QEvent::Type)_playEventType, e->_filename));
182           else
183             {
184               STDLOG("About to play test " << e->_filename);
185               _tester->playTests(e->_filename.c_str());
186               _aboutToPlayTest = false;
187               STDLOG("Done playing test " << e->_filename);
188             }
189         }
190     }
191   else
192     { QObject::customEvent(event);  }
193 }
194
195 void
196 TestController::processWorkspaceEvent(const MEDCALC::MedEvent* event)
197 {
198   if ( event->type == MEDCALC::EVENT_PLAY_TEST ) {
199       /* [ABN] Post an event. Indeed, calling the function directly would prevent the proper refresh of the
200        * GUI which also needs to go through the MED event loop (WorkspaceController::processWorkspaceEvent)
201        */
202       _aboutToPlayTest = true; // to prevent an early quit!
203       PlayTestEvent * e  = new PlayTestEvent((QEvent::Type)_playEventType, std::string(event->filename));
204       QApplication::postEvent(this, e);
205   }
206   else if ( event->type == MEDCALC::EVENT_QUIT_SALOME ) {
207       // [ABN] again: post as an event to give a chance to other events (piled up by test
208       // scenarios for example) to execute:
209       QEvent * e = new QEvent((QEvent::Type)_quitEventType);
210       QApplication::postEvent(this, e);
211   }
212 }
213
214 void TestController::onMainEventLoopStarting()
215 {
216   _myEventLoopStarted = true;
217   QApplication::instance()->removeEventFilter(this);
218 }
219
220 bool TestController::eventFilter(QObject *obj, QEvent *event)
221 {
222   if ( obj == QApplication::instance() && event->type() == 9999 )
223     onMainEventLoopStarting();
224   return QObject::eventFilter(obj, event);
225 }