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