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