Salome HOME
Test scenario playback made cleaner and less path dependent.
[modules/med.git] / src / MEDCalc / gui / TestController.cxx
1 // Copyright (C) 2016  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 {
65   STDLOG("Creating a TestController");
66   _tester = new pqTestUtility(_desk);
67   _tester->addEventObserver("xml", new pqXMLEventObserver(_desk));
68   _tester->addEventSource("xml", new pqXMLEventSource(_desk));
69 }
70
71 TestController::~TestController()
72 {
73   if (_tester)
74     delete _tester;
75   _tester = 0;
76 }
77
78 void
79 TestController::createActions() {
80   //
81   // Main actions
82   //
83   QString label   = tr("LAB_RECORD_TEST");
84   QString tooltip = tr("TIP_RECORD_TEST");
85   int actionId;
86   actionId = _salomeModule->createStandardAction(label,this, SLOT(onRecordTest()),QString(),tooltip);
87
88   // This action has to be placed in the general file menu
89   int menuId = _salomeModule->createMenu( tr( "MEN_FILE" ), -1,  1 );
90   _salomeModule->action(actionId)->setIconVisibleInMenu(false);
91   _salomeModule->createMenu(actionId, menuId, 60);
92
93   label   = tr("LAB_PLAY_TEST");
94   tooltip = tr("TIP_PLAY_TEST");
95   actionId = _salomeModule->createStandardAction(label,this, SLOT(onPlayTest()),QString(),tooltip);
96   _salomeModule->action(actionId)->setIconVisibleInMenu(false);
97   _salomeModule->createMenu(actionId, menuId, 70);
98
99   label   = tr("LAB_LOCK_TEST");
100   tooltip = tr("TIP_LOCK_TEST");
101   actionId = _salomeModule->createStandardAction(label,this, SLOT(onLockViewSize()),QString(),tooltip);
102   _salomeModule->action(actionId)->setIconVisibleInMenu(false);
103   _salomeModule->action(actionId)->setCheckable(true);
104   _lock_action = _salomeModule->action(actionId);
105   _salomeModule->createMenu(actionId, menuId, 70);
106
107   label   = tr("LAB_SNAP_TEST");
108   tooltip = tr("TIP_SNAP_TEST");
109   actionId = _salomeModule->createStandardAction(label,this, SLOT(onTakeSnapshot()),QString(),tooltip);
110   _salomeModule->action(actionId)->setIconVisibleInMenu(false);
111   _salomeModule->createMenu(actionId, menuId, 70);
112 }
113
114 void TestController::onRecordTest()
115 {
116   QString fileName =
117       QFileDialog::getSaveFileName(_desk, "Save test", QString(), QString("XML file (*.xml)"));
118   if (!fileName.isEmpty())
119     {
120       QApplication::setActiveWindow(_desk); //mandatory otherwise record pop up doesn't show up
121       _tester->recordTests(fileName);
122     }
123 }
124
125
126 void TestController::onPlayTest()
127 {
128   QString fileName =
129       QFileDialog::getOpenFileName(_desk, "Open test", QString(), QString("XML file (*.xml)"));
130   if (!fileName.isEmpty())
131     _tester->playTests(fileName);
132 }
133
134 void TestController::onLockViewSize() const
135 {
136   pqTestingReaction::lockViewSize(_lock_action->isChecked());
137 }
138
139 void TestController::onTakeSnapshot() const
140 {
141   pqSaveScreenshotReaction::saveScreenshot();
142 }
143
144 void TestController::onRequestTermination()
145 {
146   // Check if test playing
147   if (_tester->playingTest() || _aboutToPlayTest)
148     {
149       QEvent * e = new QEvent((QEvent::Type)_quitEventType);
150       QApplication::postEvent(this, e);
151     }
152   else
153     {
154       _salomeModule->requestSALOMETermination();
155     }
156 }
157
158 void
159 TestController::customEvent(QEvent * event)
160 {
161   if (event->type() == _quitEventType)
162     {
163       if(!_salomeModule->getApp()->isMainEventLoopStarted())
164           // Repost (=delay)
165           QApplication::postEvent(this, new QEvent((QEvent::Type)_quitEventType));
166       else
167           onRequestTermination();
168     }
169   else if (event->type() == _playEventType)
170     {
171       PlayTestEvent * e = dynamic_cast<PlayTestEvent *>(event);
172       if (e)
173         {
174 //          // Wait for main event loop to start:
175           if(!_salomeModule->getApp()->isMainEventLoopStarted())
176               // Repost (=delay)
177               QApplication::postEvent(this, new PlayTestEvent((QEvent::Type)_playEventType, e->_filename));
178           else
179             {
180               STDLOG("About to play test " << e->_filename);
181               _tester->playTests(e->_filename.c_str());
182               _aboutToPlayTest = false;
183               STDLOG("Done playing test " << e->_filename);
184             }
185         }
186     }
187   else
188     { QObject::customEvent(event);  }
189 }
190
191 void
192 TestController::processWorkspaceEvent(const MEDCALC::MedEvent* event)
193 {
194   if ( event->type == MEDCALC::EVENT_PLAY_TEST ) {
195       /* [ABN] Post an event. Indeed, calling the function directly would prevent the proper refresh of the
196        * GUI which also needs to go through the MED event loop (WorkspaceController::processWorkspaceEvent)
197        */
198       _aboutToPlayTest = true; // to prevent an early quit!
199       PlayTestEvent * e  = new PlayTestEvent((QEvent::Type)_playEventType, std::string(event->filename));
200       QApplication::postEvent(this, e);
201   }
202   else if ( event->type == MEDCALC::EVENT_QUIT_SALOME ) {
203       // [ABN] again: post as an event to give a chance to other events (piled up by test
204       // scenarios for example) to execute:
205       QEvent * e = new QEvent((QEvent::Type)_quitEventType);
206       QApplication::postEvent(this, e);
207   }
208 }
209