Salome HOME
improve test h003 h008 h016
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_Operation.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROGUI_Operation.h"
20
21 #include "HYDROGUI_InputPanel.h"
22 #include "HYDROGUI_Module.h"
23 #include "HYDROGUI_Tool.h"
24 #include "HYDROGUI_OCCDisplayer.h"
25 #include "HYDROGUI_Shape.h"
26
27 #include <HYDROData_Document.h>
28 #include <HYDROData_Iterator.h>
29
30 #include <LightApp_Application.h>
31 #include <LightApp_SelectionMgr.h>
32
33 #include <SUIT_Desktop.h>
34 #include <SUIT_MessageBox.h>
35 #include <SUIT_Study.h>
36
37 #include <OCCViewer_ViewManager.h>
38 #include <OCCViewer_ViewWindow.h>
39 #include <OCCViewer_ViewPort3d.h>
40
41 #include <QApplication>
42
43 //#define _DEVDEBUG_
44 #include "HYDRO_trace.hxx"
45
46 bool HYDROGUI_Operation::myIsClear = false;
47
48 HYDROGUI_Operation::HYDROGUI_Operation( HYDROGUI_Module* theModule )
49 : LightApp_Operation(),
50   myModule( theModule ),
51   myPanel( 0 ),
52   myIsPrintErrorMessage( true ),
53   myIsTransactionOpened( false ),
54   myPreviewManager( 0 ),
55   myPreviewZLayer( -1 ),
56   myIsApplyAndClose( true )
57 {
58   DEBTRACE("HYDROGUI_Operation");
59   connect( this, SIGNAL( helpContextModule( const QString&, const QString&,
60                                             const QString& ) ),
61            theModule->application(), SLOT( onHelpContextModule( const QString&,
62                                             const QString&, const QString& ) ) );
63 }
64
65 HYDROGUI_Operation::~HYDROGUI_Operation()
66 {
67   DEBTRACE("~HYDROGUI_Operation");
68 }
69
70 void HYDROGUI_Operation::setName( const QString& theName )
71 {
72   myName = theName;
73 }
74
75 const QString& HYDROGUI_Operation::getName() const
76 {
77   return myName;
78 }
79
80 HYDROGUI_InputPanel* HYDROGUI_Operation::inputPanel() const
81 {
82   DEBTRACE("inputPanel");
83   if( !myPanel )
84   {
85     ( ( HYDROGUI_Operation* )this )->myPanel = createInputPanel();
86     if (myPanel)
87     {
88                 connect( myPanel, SIGNAL( panelApplyAndClose() ), this, SLOT( onApplyAndClose() ) );
89                 connect( myPanel, SIGNAL( panelApply() ),  this, SLOT( onApply() ) );
90                 connect( myPanel, SIGNAL( panelCancel() ), this, SLOT( onCancel() ) );
91                 connect( myPanel, SIGNAL( panelHelp() ), this, SLOT( onHelp() ) );
92     }
93   }
94   return myPanel;
95 }
96
97 SUIT_SelectionMgr* HYDROGUI_Operation::selectionMgr() const
98 {
99   return myModule->getApp()->selectionMgr();
100 }
101
102 HYDROGUI_Module* HYDROGUI_Operation::module() const
103 {
104   return myModule;
105 }
106
107 /**
108   * Returns Z layer of the operation preview.
109    \ returns a layer position
110  */
111 int HYDROGUI_Operation::getPreviewZLayer() const
112 {
113   return myPreviewZLayer;
114 }
115
116 /**
117  * Update Z layer for the operation preview.
118    \param theLayer a layer position
119  */
120 void HYDROGUI_Operation::updatePreviewZLayer( int theLayer )
121 {
122   setPreviewZLayer( theLayer );
123
124   HYDROGUI_Shape* aPreview = getPreviewShape();
125   if ( aPreview )
126     aPreview->setZLayer( getPreviewZLayer() );
127 }
128
129 /**
130  * Set Z layer for the operation preview.
131  \param theLayer a layer position
132  */
133 void HYDROGUI_Operation::setPreviewZLayer( int theLayer )
134 {
135   if ( theLayer != myPreviewZLayer )
136     myPreviewZLayer = theLayer;
137 }
138
139 /**
140  * Returns a shape preview of the operation
141  */
142 HYDROGUI_Shape* HYDROGUI_Operation::getPreviewShape() const
143 {
144   return 0;
145 }
146
147 /**
148  * Return the operation preview manager
149  */
150 OCCViewer_ViewManager* HYDROGUI_Operation::getPreviewManager()
151 {
152   return myPreviewManager;
153 }
154
155 /**
156  * Set the preview manager
157  */
158 void HYDROGUI_Operation::setPreviewManager( OCCViewer_ViewManager* theManager )
159 {
160   //No good: preview Z layer could be used by usual presentations
161   //if ( !theManager && myPreviewManager )
162   //  module()->getOCCDisplayer()->RemoveZLayer( myPreviewManager, getPreviewZLayer() );
163
164   myPreviewManager = theManager;
165   // the manager can be null on abort Operation and we need to clear ZLayers on first call, when on new document (second study without SALOME restart)
166   OCCViewer_ViewManager* aViewManager = myPreviewManager;
167   if ( !aViewManager )
168     aViewManager = dynamic_cast<OCCViewer_ViewManager*>( module()->getApp()->getViewManager( OCCViewer_Viewer::Type(), true ) );
169   DEBTRACE("aViewManager, myPreviewManager " << aViewManager << " " << myPreviewManager);
170
171   if (!myIsClear)
172     {
173       module()->getOCCDisplayer()->RemoveZLayer(aViewManager, 0, true);
174       myIsClear = true;
175     }
176   if ( myPreviewManager )
177     setPreviewZLayer( module()->getOCCDisplayer()->AddPreviewZLayer( myPreviewManager ) );
178 }
179
180 void HYDROGUI_Operation::setCursor()
181 {
182   if ( myPreviewManager )
183   {
184     QVector<SUIT_ViewWindow*> winList = myPreviewManager->getViews();
185     for ( QVector<SUIT_ViewWindow*>::iterator it = winList.begin(); it != winList.end(); ++it )
186     {
187       OCCViewer_ViewWindow* occWin = ::qobject_cast<OCCViewer_ViewWindow*>( *it );
188       if ( occWin )
189       {
190         OCCViewer_ViewPort3d* vp = occWin->getViewPort();
191         if ( vp )
192         {
193           // Save old cursor
194           myCursor = vp->cursor();
195           // Set specific cursor chosen in preferences
196           QCursor aCursor = module()->getPrefEditCursor();
197           vp->setDefaultCursor( aCursor.shape() );
198           vp->setCursor( *vp->getDefaultCursor() );
199         }
200       }
201     }
202   }
203 }
204
205 void HYDROGUI_Operation::restoreCursor()
206 {
207   if ( myPreviewManager )
208   {
209     QVector<SUIT_ViewWindow*> winList = myPreviewManager->getViews();
210     for ( QVector<SUIT_ViewWindow*>::iterator it = winList.begin(); it != winList.end(); ++it )
211     {
212       OCCViewer_ViewWindow* occWin = ::qobject_cast<OCCViewer_ViewWindow*>( *it );
213       if ( occWin )
214       {
215         OCCViewer_ViewPort3d* vp = occWin->getViewPort();
216         if ( vp )
217         {
218           // Restore old cursor
219           vp->setDefaultCursor( myCursor.shape() );
220           vp->setCursor( myCursor );
221         }
222       }
223     }
224   }
225 }
226
227 void HYDROGUI_Operation::setIsApplyAndClose( const bool theFlag )
228 {
229   myIsApplyAndClose = theFlag;
230 }
231
232 bool HYDROGUI_Operation::isApplyAndClose() const
233 {
234   return myIsApplyAndClose;
235 }
236
237 void HYDROGUI_Operation::apply()
238 {
239   QApplication::setOverrideCursor( Qt::WaitCursor );
240
241   startDocOperation();
242
243   int anUpdateFlags = 0;
244   QString anErrorMsg;
245
246   bool aResult = false;
247   QStringList aBrowseObjectsEntries;
248
249   try
250   {
251     aResult = processApply( anUpdateFlags, anErrorMsg, aBrowseObjectsEntries );
252   }
253   catch ( Standard_Failure& e )
254   {
255     if (&e)
256       anErrorMsg = e.GetMessageString();
257     else
258       anErrorMsg = "failure unknown: catch ( Standard_Failure ) does not give access to failure!";
259     aResult = false;
260   }
261   catch ( ... )
262   {
263     aResult = false;
264   }
265   
266   QApplication::restoreOverrideCursor();
267
268   if ( aResult )
269   {
270     module()->update( anUpdateFlags );
271     commitDocOperation();
272     commit();
273     browseObjects( aBrowseObjectsEntries, myIsApplyAndClose );
274
275     if ( !myIsApplyAndClose && inputPanel() )
276       start();
277   }
278   else if( !anErrorMsg.isEmpty() )
279   {
280     // Abort document opeartion only if requested
281     if ( isToAbortOnApply() )
282       abortDocOperation();
283
284     printErrorMessage( anErrorMsg );
285  
286     // If the operation has no input panel - do abort
287     if ( !inputPanel() ) {
288       abort();
289     }
290   } 
291 }
292
293 void HYDROGUI_Operation::startOperation()
294 {
295   LightApp_Operation::startOperation();
296   myModule->getActiveOperations().push( this );
297
298   if( myIsApplyAndClose && inputPanel() )
299   {
300     myModule->getApp()->desktop()->addDockWidget( Qt::RightDockWidgetArea, inputPanel() );
301     inputPanel()->show();
302   }
303 }
304
305 void HYDROGUI_Operation::abortOperation()
306 {
307   LightApp_Operation::abortOperation();
308   closeInputPanel();
309 }
310
311 void HYDROGUI_Operation::commitOperation()
312 {
313   LightApp_Operation::commitOperation();
314   if ( myIsApplyAndClose )
315     closeInputPanel();
316 }
317
318 void HYDROGUI_Operation::stopOperation()
319 {
320   LightApp_Operation::stopOperation();
321
322   // pop the operation from the cached map of active operations
323   QStack<HYDROGUI_Operation*>& anOperations = myModule->getActiveOperations();
324   if ( !anOperations.empty() ) {
325     if ( anOperations.top() == this )
326       anOperations.pop();
327     else
328     {
329       // find in the stack the current operation and remove it from the stack
330       QVectorIterator<HYDROGUI_Operation*> aVIt( anOperations );
331       aVIt.toBack();
332       aVIt.previous(); // skip the top show/hide operation
333       while ( aVIt.hasPrevious() )
334       {
335         HYDROGUI_Operation* anOp = aVIt.previous();
336         if ( anOp == this )
337           anOperations.remove( anOperations.lastIndexOf( anOp ) );
338       }
339     }
340   }
341   // release the preview manager with removing the added preview Z layer
342   setPreviewManager( 0 );
343 }
344
345 void HYDROGUI_Operation::setDialogActive( const bool active )
346 {
347   LightApp_Operation::setDialogActive( active );
348   if( myPanel )
349   {
350     if( active )
351     {
352       myPanel->show();
353     }
354   }
355 }
356
357 HYDROGUI_InputPanel* HYDROGUI_Operation::createInputPanel() const
358 {
359   return NULL;
360 }
361
362 void HYDROGUI_Operation::closeInputPanel()
363 {
364   if( myPanel )
365   {
366     myModule->getApp()->desktop()->removeDockWidget( myPanel );
367     delete myPanel;
368     myPanel = 0;
369   }
370 }
371
372 bool HYDROGUI_Operation::processApply( int& theUpdateFlags,
373                                        QString& theErrorMsg,
374                                        QStringList& theBrowseObjectsEntries )
375 {
376   return false;
377 }
378
379 void HYDROGUI_Operation::processCancel()
380 {
381 }
382
383 void HYDROGUI_Operation::startDocOperation()
384 {
385   // Open transaction in the model document only if it not
386   // already opened by other operation (intended for nested operations)
387   if ( !doc()->IsOperation() )
388   {
389     doc()->StartOperation();
390     myIsTransactionOpened = true;
391   }
392 }
393
394 void HYDROGUI_Operation::abortDocOperation()
395 {
396   // Abort transaction in the model document only if it was 
397   // opened by this operation (intended for nested operations)
398   if ( myIsTransactionOpened && doc()->IsOperation() )
399   {
400     doc()->AbortOperation();
401     myIsTransactionOpened = false;
402   }
403 }
404
405 void HYDROGUI_Operation::commitDocOperation()
406 {
407   // Commit transaction in the model document only if it was 
408   // opened by this operation (intended for nested operations)
409   if ( myIsTransactionOpened && doc()->IsOperation() )
410   {
411     doc()->CommitOperation( HYDROGUI_Tool::ToExtString( getName() ) );
412     myIsTransactionOpened = false;
413   }
414 }
415
416 Handle(HYDROData_Document) HYDROGUI_Operation::doc() const
417 {
418   return HYDROData_Document::Document();
419 }
420
421 void HYDROGUI_Operation::onApplyAndClose()
422 {
423   myIsApplyAndClose = true;
424   apply();
425   restoreOCCViewerSelection();
426 }
427
428 void HYDROGUI_Operation::onApply()
429 {
430   myIsApplyAndClose = false;
431   apply();
432   restoreOCCViewerSelection();
433 }
434
435 void HYDROGUI_Operation::setPrintErrorMessage( const bool theIsPrint )
436 {
437   myIsPrintErrorMessage = theIsPrint;
438 }
439
440 void HYDROGUI_Operation::printErrorMessage( const QString& theErrorMsg )
441 {
442   if ( myIsPrintErrorMessage )
443   {
444     QString aMsg = tr( "INPUT_VALID_DATA" );
445     if( !theErrorMsg.isEmpty() )
446       aMsg.prepend( theErrorMsg + "\n" );
447     SUIT_MessageBox::critical( module()->getApp()->desktop(),
448                                tr( "INSUFFICIENT_INPUT_DATA" ),
449                                aMsg );
450
451   }
452   
453   myIsPrintErrorMessage = true;
454 }
455
456 void HYDROGUI_Operation::onCancel()
457 {
458   processCancel();
459   abort();
460   if ( myPanel )
461     abortOperation();
462   myIsApplyAndClose = true;
463   restoreOCCViewerSelection();
464 }
465
466 void HYDROGUI_Operation::restoreOCCViewerSelection(OCCViewer_ViewManager* theViewManager)
467 {
468   DEBTRACE("restoreOCCViewerSelection " << theViewManager);
469   LightApp_Application* anApp = module()->getApp();
470   LightApp_SelectionMgr* sm = anApp->selectionMgr();
471   if(sm)
472   {
473           sm->clearFilters(); // see GEOM_Displayer::GlobalSelection
474   }
475   OCCViewer_ViewManager* aViewManager = theViewManager;
476   if (!aViewManager)
477     aViewManager = dynamic_cast<OCCViewer_ViewManager*>( anApp->getViewManager( OCCViewer_Viewer::Type(), true ) );
478   if( aViewManager )
479   {
480         if( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() )
481         {
482           Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
483           if( !aCtx.IsNull() )
484           {
485                   DEBTRACE("aViewManager " << aViewManager << " AIScontext " << aCtx.get());
486                   aCtx->Deactivate();
487                   aCtx->Activate(0);
488                   aCtx->SetAutomaticHilight( Standard_True );
489                   aCtx->RemoveFilters();
490           }
491         }
492   }
493 }
494 void HYDROGUI_Operation::onHelp()
495 {
496    emit helpContextModule( getHelpComponent(), getHelpFile(), getHelpContext() );
497 }
498
499 QString HYDROGUI_Operation::getHelpComponent() const
500 {
501    return module()->moduleName();
502 }
503
504 QString HYDROGUI_Operation::getHelpFile() const
505 {
506   QString aFileName = ((myName.isEmpty())? operationName() : myName);
507   aFileName = aFileName.toLower();
508   aFileName = aFileName.replace(QRegExp("\\s"), "_").append(".html");
509   aFileName.remove( "create_" );
510   aFileName.remove( "edit_" );
511   return aFileName;
512 }
513
514 QString HYDROGUI_Operation::getHelpContext() const
515 {
516    return QString();
517 }
518
519 void HYDROGUI_Operation::browseObjects( const QStringList& theBrowseObjectsEntries,
520                                         const bool theIsApplyAndClose/* = true*/ )
521 {
522   bool isOptimizedBrowse = true;
523   module()->getApp()->browseObjects( theBrowseObjectsEntries, theIsApplyAndClose, isOptimizedBrowse );
524 }