Salome HOME
Migration to OCCT 7.0
[modules/gui.git] / src / CAF / CAF_Study.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "CAF_Study.h"
24
25 #include "CAF_Tools.h"
26 #include "CAF_Application.h"
27
28 #include <SUIT_Desktop.h>
29 #include <SUIT_MessageBox.h>
30 #include <SUIT_Application.h>
31
32 #include <QDir>
33
34 #include <TDF_Delta.hxx>
35 #include <TDF_ListIteratorOfDeltaList.hxx>
36
37 #include <Standard_Failure.hxx>
38 #include <Standard_ErrorHandler.hxx>
39
40 /*!
41   \class CAF_Study
42   \brief Represents study for using in CAF module.
43
44   A study contains reference to OCAF std document and allows using OCAF services.
45   Provides necessary functionality for OCC transactions management.
46 */
47
48 /*!
49   \brief Constructor.
50   \param theApp application
51 */
52 CAF_Study::CAF_Study(SUIT_Application* theApp)
53 : SUIT_Study( theApp ),
54   myModifiedCnt( 0 )
55 {
56 }
57
58 /*!
59   \brief Constructor.
60   \param theApp application
61   \param aStdDoc OCAF document
62 */
63 CAF_Study::CAF_Study(SUIT_Application* theApp, Handle (TDocStd_Document)& aStdDoc)
64 : SUIT_Study( theApp ),
65   myStdDoc( aStdDoc ),
66   myModifiedCnt( 0 )
67 {
68 }
69
70 /*!
71   \brief Destructor.
72 */
73 CAF_Study::~CAF_Study()
74 {
75 }
76
77 /*!
78   \brief Get OCAF document.
79   \return handle to the OCAF document object
80 */
81 Handle(TDocStd_Document) CAF_Study::stdDoc() const
82 {
83   return myStdDoc;
84 }
85
86 /*!
87   \brief Set OCAF document.
88   \param aStdDoc new OCAF document
89 */
90 void CAF_Study::setStdDoc( Handle(TDocStd_Document)& aStdDoc )
91 {
92   myStdDoc = aStdDoc;
93 }
94
95 /*!
96   \brief Customize document initialization.
97   \param doc study name
98   \return \c true on success and \c false on error
99 */
100 bool CAF_Study::createDocument( const QString& doc )
101 {
102   bool res = SUIT_Study::createDocument( doc );
103
104   CAF_Application* app = cafApplication();
105   if ( res && app && !app->stdApp().IsNull() )
106   {
107     try {
108       OCC_CATCH_SIGNALS;
109       TColStd_SequenceOfExtendedString formats;
110       app->stdApp()->Formats( formats );
111       if ( !formats.IsEmpty() )
112         app->stdApp()->NewDocument( formats.First(), myStdDoc );
113     }
114     catch ( Standard_Failure ) {
115       res = false;
116     }
117   }
118   return res;
119 }
120
121 /*!
122   \brief Close document.
123   \param permanently if \c true, a document is closed permanently
124 */
125 void CAF_Study::closeDocument( bool permanently )
126 {
127   Handle(TDocStd_Application) app = stdApp();
128   if ( !app.IsNull() && !stdDoc().IsNull() )
129     app->Close( stdDoc() );
130
131   SUIT_Study::closeDocument( permanently );
132 }
133
134 /*!
135   \brief Open document.
136   \param fname study file name
137   \return \c true on success and \c false if document cannot be opened
138 */
139 bool CAF_Study::openDocument( const QString& fname )
140 {
141   Handle(TDocStd_Application) app = stdApp();
142   if ( app.IsNull() )
143     return false;
144
145   bool status = false;
146   try {
147     OCC_CATCH_SIGNALS;
148     status = app->Open( CAF_Tools::toExtString( fname ), myStdDoc ) == PCDM_RS_OK;
149   }
150   catch ( Standard_Failure ) {
151     status = false;
152   }
153
154   return status && SUIT_Study::openDocument( fname );
155 }
156
157 /*!
158   \brief Save document with other name.
159   \param fname study file name
160 */
161 bool CAF_Study::saveDocumentAs( const QString& fname )
162 {
163   Handle(TDocStd_Application) app = stdApp();
164   if ( app.IsNull() )
165     return false;
166
167   bool save = false;
168   if ( !stdDoc().IsNull() && stdDoc()->IsSaved() )
169   {
170     QString path = QDir::toNativeSeparators( CAF_Tools::toQString( stdDoc()->GetPath() ) );
171     save = path == QDir::toNativeSeparators( fname );
172   }
173
174   bool status = false;
175   try {
176     OCC_CATCH_SIGNALS;
177     if ( save )
178       status = app->Save( stdDoc() ) == PCDM_SS_OK;
179     else
180     {
181       TCollection_ExtendedString format, path( CAF_Tools::toExtString( fname ) );
182       app->Format( path, format );
183
184       if ( format.Length() )
185         stdDoc()->ChangeStorageFormat( format );
186
187       status = app->SaveAs( stdDoc(), path ) == PCDM_SS_OK;
188     }
189   }
190   catch ( Standard_Failure ) {
191     status = false;
192   }
193
194   if ( status )
195     status = SUIT_Study::saveDocumentAs( fname );
196
197   if ( status )
198     myModifiedCnt = 0;
199
200   return status;
201 }
202
203 /*!
204   \brief Open OCAF transaction.
205   \return \c true if transaction is opened successfully
206 */
207 bool CAF_Study::openTransaction()
208 {
209   if ( myStdDoc.IsNull() )
210     return false;
211
212   bool res = true;
213   try {
214     OCC_CATCH_SIGNALS;
215     if ( myStdDoc->HasOpenCommand() )
216       myStdDoc->AbortCommand();
217
218     myStdDoc->OpenCommand();
219   }
220   catch ( Standard_Failure ) {
221     res = false;
222   }
223
224   return res;
225 }
226
227 /*!
228   \brief Abort OCAF transaction.
229   \return \c true if transaction is aborted successfully
230 */
231 bool CAF_Study::abortTransaction()
232 {
233   if ( myStdDoc.IsNull() )
234     return false;
235
236   bool res = true;
237   try {
238     OCC_CATCH_SIGNALS;
239     myStdDoc->AbortCommand();
240     update();
241   }
242   catch ( Standard_Failure ) {
243     res = false;
244   }
245   return res;
246 }
247
248 /*!
249   \brief Commit OCAF transaction
250   \return \c true if transaction is committed successfully
251 */
252 bool CAF_Study::commitTransaction( const QString& name )
253 {
254   if ( myStdDoc.IsNull() )
255     return false;
256
257   bool res = true;
258   try {
259     OCC_CATCH_SIGNALS;
260     myStdDoc->CommitCommand();
261
262     if ( canUndo() )
263     {
264       Handle(TDF_Delta) d = myStdDoc->GetUndos().Last();
265       if ( !d.IsNull() )
266         d->SetName( CAF_Tools::toExtString( name ) );
267     }
268   }
269   catch ( Standard_Failure ) {
270     res = false;
271   }
272   return res;
273 }
274
275 /*!
276   \brief Check if there is any transaction opened.
277   \return \c true if there is opened OCAF transaction
278 */
279 bool CAF_Study::hasTransaction() const
280 {
281   if ( myStdDoc.IsNull() )
282     return false;
283
284   return myStdDoc->HasOpenCommand();
285 }
286
287 /*!
288   \brief Check if the study is saved.
289   \return \c true if the document has been saved to file
290 */
291 bool CAF_Study::isSaved() const
292 {
293   if ( myStdDoc.IsNull() )
294     return false;
295
296   return myStdDoc->IsSaved();
297 }
298
299 /*!
300   \brief Check if the study is modified.
301   \return \c true if the document has been modified
302 */
303 bool CAF_Study::isModified() const
304 {
305   if ( myStdDoc.IsNull() )
306     return false;
307
308 //  return myStdDoc->IsModified();
309   return myModifiedCnt;
310 }
311
312 /*!
313   \brief Increment modifications count.
314
315   If \a undoable is \c true, this modification can be rolled back by
316   undoModified(), otherwise the document will be marked as \c modified
317   until it is saved.
318
319   \param undoable if \c true the operation is undoable
320   \sa undoModified(), clearModified()
321 */
322 void CAF_Study::doModified( bool undoable )
323 {
324   if ( myStdDoc.IsNull() )
325     return;
326
327   myModifiedCnt++;
328
329   /*  Assumed that number of available undos / redos is NOT changed dynamically */
330   if ( !undoable )
331     myModifiedCnt += myStdDoc->GetAvailableUndos();
332 }
333
334 /*!
335   \brief Decrement modifications count.
336   \sa doModified(), clearModified()
337 */
338 void CAF_Study::undoModified()
339 {
340   myModifiedCnt--;
341 }
342
343 /*!
344   \brief Clear modifications count.
345   \sa doModified(), undoModified()
346 */
347 void CAF_Study::clearModified()
348 {
349   myModifiedCnt = 0;
350 }
351
352 /*!
353   \brief Undo the last command.
354   \return \c true on success and \c false on error
355 */
356 bool CAF_Study::undo()
357 {
358   if ( myStdDoc.IsNull() )
359     return false;
360
361   try {
362     OCC_CATCH_SIGNALS;
363     myStdDoc->Undo();
364     undoModified();     /* decrement modification counter */
365   }
366   catch ( Standard_Failure ) {
367     SUIT_MessageBox::critical(application()->desktop(), tr( "ERR_ERROR" ),
368                               tr( "ERR_DOC_UNDO" ));
369     return false;
370   }
371   return true;
372 }
373
374 /*!
375   \brief Redo the last undo.
376   \return \c true on success and \c false on error
377 */
378 bool CAF_Study::redo()
379 {
380   if ( myStdDoc.IsNull() )
381     return false;
382
383   try {
384     OCC_CATCH_SIGNALS;
385     myStdDoc->Redo();
386     doModified();      /* increment modification counter */
387   }
388   catch ( Standard_Failure ) {
389     SUIT_MessageBox::critical( application()->desktop(), tr( "ERR_ERROR" ),
390                                tr( "ERR_DOC_REDO" ) );
391     return false;
392   }
393   return true;
394 }
395
396 /*!
397   \brief Check if it is possible to undo last command.
398   \return \c true if undo is avaiable
399 */
400 bool CAF_Study::canUndo() const
401 {
402   if ( myStdDoc.IsNull() )
403     return false;
404
405   return myStdDoc->GetAvailableUndos() > 0;
406 }
407
408 /*!
409   \brief Check if it is possible to redo last undo.
410   \return \c true if redo is avaiable
411 */
412 bool CAF_Study::canRedo() const
413 {
414   if ( myStdDoc.IsNull() )
415     return false;
416
417   return myStdDoc->GetAvailableRedos() > 0;
418 }
419
420 /*!
421   \brief Get names of available undo commands.
422   \return list of commands names
423 */
424 QStringList CAF_Study::undoNames() const
425 {
426   QStringList names;
427   if ( !myStdDoc.IsNull() )
428   {
429     for ( TDF_ListIteratorOfDeltaList it( myStdDoc->GetUndos() ); it.More(); it.Next() )
430       names.prepend( CAF_Tools::toQString( it.Value()->Name() ) );
431   }
432   return names;
433 }
434
435 /*!
436   \brief Get names of available redo commands.
437   \return list of commands names
438 */
439 QStringList CAF_Study::redoNames() const
440 {
441   QStringList names;
442   if ( !myStdDoc.IsNull() )
443   {
444     for ( TDF_ListIteratorOfDeltaList it( myStdDoc->GetRedos() ); it.More(); it.Next() )
445       names.append( CAF_Tools::toQString( it.Value()->Name() ) );
446   }
447   return names;
448 }
449
450 /*!
451   \brief Get OCAF application.
452   \return handle to the OCAF application object
453 */
454 Handle(TDocStd_Application) CAF_Study::stdApp() const
455 {
456   Handle(TDocStd_Application) stdApp;
457   CAF_Application* app = cafApplication();
458   if ( app )
459     stdApp = app->stdApp();
460   return stdApp;
461 }
462
463 /*!
464   \brief Get application.
465   \return application object (CAF_Application)
466 */
467 CAF_Application* CAF_Study::cafApplication() const
468 {
469   return qobject_cast<CAF_Application*>( application() );
470 }