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