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