00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <qapplication.h>
00028 # include <qdir.h>
00029 # include <qfileinfo.h>
00030 # include <qmessagebox.h>
00031 # include <qstatusbar.h>
00032 # include <boost/signals.hpp>
00033 # include <boost/bind.hpp>
00034 #endif
00035
00036 #include <Base/Console.h>
00037 #include <Base/Exception.h>
00038 #include <Base/Matrix.h>
00039 #include <Base/Reader.h>
00040 #include <Base/Writer.h>
00041
00042 #include <App/Document.h>
00043 #include <App/DocumentObject.h>
00044
00045 #include "Application.h"
00046 #include "MainWindow.h"
00047 #include "Tree.h"
00048 #include "Document.h"
00049 #include "DocumentPy.h"
00050 #include "Command.h"
00051 #include "Control.h"
00052 #include "FileDialog.h"
00053 #include "View3DInventor.h"
00054 #include "View3DInventorViewer.h"
00055 #include "BitmapFactory.h"
00056 #include "ViewProviderDocumentObject.h"
00057 #include "Selection.h"
00058 #include "SoFCSelection.h"
00059 #include "WaitCursor.h"
00060 #include "Thumbnail.h"
00061
00062 using namespace Gui;
00063
00064 namespace Gui {
00065
00066
00067 struct DocumentP
00068 {
00069 Thumbnail thumb;
00070 int _iWinCount;
00071 int _iDocId;
00072 bool _isClosing;
00073 bool _isModified;
00074 ViewProvider* _pcInEdit;
00075 Application* _pcAppWnd;
00076
00077 App::Document* _pcDocument;
00079 std::list<Gui::BaseView*> baseViews;
00081 std::list<Gui::BaseView*> passiveViews;
00082 std::map<const App::DocumentObject*,ViewProviderDocumentObject*> _ViewProviderMap;
00083 std::map<std::string,ViewProvider*> _ViewProviderMapAnnotation;
00084
00085 typedef boost::signals::connection Connection;
00086 Connection connectNewObject;
00087 Connection connectDelObject;
00088 Connection connectCngObject;
00089 Connection connectRenObject;
00090 Connection connectActObject;
00091 Connection connectSaveDocument;
00092 Connection connectRestDocument;
00093 Connection connectLoadDocument;
00094 };
00095
00096 }
00097
00098
00099
00101
00102 int Document::_iDocCount = 0;
00103
00104 Document::Document(App::Document* pcDocument,Application * app)
00105 {
00106 d = new DocumentP;
00107 d->_iWinCount = 1;
00108
00109 d->_iDocId = (++_iDocCount);
00110 d->_isClosing = false;
00111 d->_isModified = false;
00112 d->_pcAppWnd = app;
00113 d->_pcDocument = pcDocument;
00114 d->_pcInEdit = 0;
00115
00116
00117 d->connectNewObject = pcDocument->signalNewObject.connect
00118 (boost::bind(&Gui::Document::slotNewObject, this, _1));
00119 d->connectDelObject = pcDocument->signalDeletedObject.connect
00120 (boost::bind(&Gui::Document::slotDeletedObject, this, _1));
00121 d->connectCngObject = pcDocument->signalChangedObject.connect
00122 (boost::bind(&Gui::Document::slotChangedObject, this, _1, _2));
00123 d->connectRenObject = pcDocument->signalRenamedObject.connect
00124 (boost::bind(&Gui::Document::slotRenamedObject, this, _1));
00125 d->connectActObject = pcDocument->signalActivatedObject.connect
00126 (boost::bind(&Gui::Document::slotActivatedObject, this, _1));
00127 d->connectSaveDocument = pcDocument->signalSaveDocument.connect
00128 (boost::bind(&Gui::Document::Save, this, _1));
00129 d->connectRestDocument = pcDocument->signalRestoreDocument.connect
00130 (boost::bind(&Gui::Document::Restore, this, _1));
00131 d->connectLoadDocument = App::GetApplication().signalRestoreDocument.connect
00132 (boost::bind(&Gui::Document::slotRestoredDocument, this, _1));
00133
00134
00135
00136
00137 _pcDocPy = new Gui::DocumentPy(this);
00138
00139 if (App::GetApplication().GetParameterGroupByPath
00140 ("User parameter:BaseApp/Preferences/Document")->GetBool("UsingUndo",true)){
00141 d->_pcDocument->setUndoMode(1);
00142
00143 d->_pcDocument->setMaxUndoStackSize(App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document")->GetInt("MaxUndoSize",20));
00144 }
00145 }
00146
00147 Document::~Document()
00148 {
00149
00150
00151 d->connectNewObject.disconnect();
00152 d->connectDelObject.disconnect();
00153 d->connectCngObject.disconnect();
00154 d->connectRenObject.disconnect();
00155 d->connectActObject.disconnect();
00156 d->connectSaveDocument.disconnect();
00157 d->connectRestDocument.disconnect();
00158 d->connectLoadDocument.disconnect();
00159
00160
00161 d->_isClosing = true;
00162
00163 std::list<Gui::BaseView*> temp = d->baseViews;
00164 for(std::list<Gui::BaseView*>::iterator it=temp.begin();it!=temp.end();++it)
00165 (*it)->deleteSelf();
00166
00167 std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::iterator jt;
00168 for (jt = d->_ViewProviderMap.begin();jt != d->_ViewProviderMap.end(); ++jt)
00169 delete jt->second;
00170 std::map<std::string,ViewProvider*>::iterator it2;
00171 for (it2 = d->_ViewProviderMapAnnotation.begin();it2 != d->_ViewProviderMapAnnotation.end(); ++it2)
00172 delete it2->second;
00173
00174
00175 _pcDocPy->setInvalid();
00176 _pcDocPy->DecRef();
00177 delete d;
00178 }
00179
00180
00181
00182
00183
00184 bool Document::setEdit(Gui::ViewProvider* p, int ModNum)
00185 {
00186 if (d->_pcInEdit)
00187 resetEdit();
00188 View3DInventor *activeView = dynamic_cast<View3DInventor *>(getActiveView());
00189 if (activeView && activeView->getViewer()->setEditingViewProvider(p,ModNum)) {
00190 d->_pcInEdit = p;
00191 if (d->_pcInEdit->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
00192 signalInEdit(*(static_cast<ViewProviderDocumentObject*>(d->_pcInEdit)));
00193 }
00194 else
00195 return false;
00196 return true;
00197 }
00198
00199 void Document::resetEdit(void)
00200 {
00201 std::list<Gui::BaseView*>::iterator it;
00202 if (d->_pcInEdit) {
00203 for (it = d->baseViews.begin();it != d->baseViews.end();++it) {
00204 View3DInventor *activeView = dynamic_cast<View3DInventor *>(*it);
00205 if (activeView)
00206 activeView->getViewer()->resetEditingViewProvider();
00207 }
00208
00209 if (d->_pcInEdit->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
00210 signalResetEdit(*(static_cast<ViewProviderDocumentObject*>(d->_pcInEdit)));
00211 d->_pcInEdit = 0;
00212 }
00213 }
00214
00215 ViewProvider *Document::getInEdit(void) const
00216 {
00217 if (d->_pcInEdit) {
00218
00219 View3DInventor *activeView = dynamic_cast<View3DInventor *>(getActiveView());
00220 if (activeView && activeView->getViewer()->isEditingViewProvider())
00221 return d->_pcInEdit;
00222 }
00223
00224 return 0;
00225 }
00226
00227 void Document::setAnnotationViewProvider(const char* name, ViewProvider *pcProvider)
00228 {
00229 std::list<Gui::BaseView*>::iterator vIt;
00230
00231
00232 std::map<std::string,ViewProvider*>::iterator it = d->_ViewProviderMapAnnotation.find(name);
00233 if (it != d->_ViewProviderMapAnnotation.end())
00234 removeAnnotationViewProvider(name);
00235
00236
00237 d->_ViewProviderMapAnnotation[name] = pcProvider;
00238
00239
00240 for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) {
00241 View3DInventor *activeView = dynamic_cast<View3DInventor *>(*vIt);
00242 if (activeView)
00243 activeView->getViewer()->addViewProvider(pcProvider);
00244 }
00245 }
00246
00247 ViewProvider * Document::getAnnotationViewProvider(const char* name) const
00248 {
00249 std::map<std::string,ViewProvider*>::const_iterator it = d->_ViewProviderMapAnnotation.find(name);
00250 return ( (it != d->_ViewProviderMapAnnotation.end()) ? it->second : 0 );
00251 }
00252
00253 void Document::removeAnnotationViewProvider(const char* name)
00254 {
00255 std::map<std::string,ViewProvider*>::iterator it = d->_ViewProviderMapAnnotation.find(name);
00256 std::list<Gui::BaseView*>::iterator vIt;
00257
00258
00259 for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) {
00260 View3DInventor *activeView = dynamic_cast<View3DInventor *>(*vIt);
00261 if (activeView)
00262 activeView->getViewer()->removeViewProvider(it->second);
00263 }
00264
00265 delete it->second;
00266 d->_ViewProviderMapAnnotation.erase(it);
00267 }
00268
00269
00270 ViewProvider* Document::getViewProvider(const App::DocumentObject* Feat) const
00271 {
00272 std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator
00273 it = d->_ViewProviderMap.find( Feat );
00274 return ( (it != d->_ViewProviderMap.end()) ? it->second : 0 );
00275 }
00276
00277 std::vector<ViewProvider*> Document::getViewProvidersOfType(const Base::Type& typeId) const
00278 {
00279 std::vector<ViewProvider*> Objects;
00280 for (std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator it =
00281 d->_ViewProviderMap.begin(); it != d->_ViewProviderMap.end(); ++it ) {
00282 if (it->second->getTypeId().isDerivedFrom(typeId))
00283 Objects.push_back(it->second);
00284 }
00285 return Objects;
00286 }
00287
00288 ViewProvider *Document::getViewProviderByName(const char* name) const
00289 {
00290
00291 App::DocumentObject *pcFeat = getDocument()->getObject(name);
00292
00293 if (pcFeat)
00294 {
00295 std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator
00296 it = d->_ViewProviderMap.find( pcFeat );
00297
00298 if (it != d->_ViewProviderMap.end())
00299 return it->second;
00300 } else {
00301
00302 std::map<std::string,ViewProvider*>::const_iterator it2 = d->_ViewProviderMapAnnotation.find( name );
00303
00304 if (it2 != d->_ViewProviderMapAnnotation.end())
00305 return it2->second;
00306 }
00307
00308 return 0;
00309 }
00310
00311 bool Document::isShow(const char* name)
00312 {
00313 ViewProvider* pcProv = getViewProviderByName(name);
00314 return pcProv ? pcProv->isShow() : false;
00315 }
00316
00318 void Document::setShow(const char* name)
00319 {
00320 ViewProvider* pcProv = getViewProviderByName(name);
00321
00322 if (pcProv && pcProv->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) {
00323 ((ViewProviderDocumentObject*)pcProv)->Visibility.setValue(true);
00324 }
00325 }
00326
00328 void Document::setHide(const char* name)
00329 {
00330 ViewProvider* pcProv = getViewProviderByName(name);
00331
00332 if (pcProv && pcProv->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) {
00333 ((ViewProviderDocumentObject*)pcProv)->Visibility.setValue(false);
00334 }
00335 }
00336
00338 void Document::setPos(const char* name, const Base::Matrix4D& rclMtrx)
00339 {
00340 ViewProvider* pcProv = getViewProviderByName(name);
00341 if (pcProv)
00342 pcProv->setTransformation(rclMtrx);
00343
00344 }
00345
00346
00347
00348
00349 void Document::slotNewObject(const App::DocumentObject& Obj)
00350 {
00351
00352 std::string cName = Obj.getViewProviderName();
00353 if (cName.empty()) {
00354
00355 Base::Console().Log("%s has no view provider specified\n", Obj.getTypeId().getName());
00356 return;
00357 }
00358
00359 setModified(true);
00360 Base::BaseClass* base = static_cast<Base::BaseClass*>(Base::Type::createInstanceByName(cName.c_str(),true));
00361 if (base) {
00362
00363 assert(base->getTypeId().isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId()));
00364 ViewProviderDocumentObject *pcProvider = static_cast<ViewProviderDocumentObject*>(base);
00365 d->_ViewProviderMap[&Obj] = pcProvider;
00366
00367 try {
00368
00369
00370 pcProvider->attach(const_cast<App::DocumentObject*>(&Obj));
00371 pcProvider->updateView();
00372 pcProvider->setActiveMode();
00373 }
00374 catch(const Base::MemoryException& e){
00375 Base::Console().Error("Memory exception in '%s' thrown: %s\n",Obj.getNameInDocument(),e.what());
00376 }
00377 catch(Base::Exception &e){
00378 e.ReportException();
00379 }
00380 #ifndef FC_DEBUG
00381 catch(...){
00382 Base::Console().Error("App::Document::_RecomputeFeature(): Unknown exception in Feature \"%s\" thrown\n",Obj.getNameInDocument());
00383 }
00384 #endif
00385 std::list<Gui::BaseView*>::iterator vIt;
00386
00387 for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) {
00388 View3DInventor *activeView = dynamic_cast<View3DInventor *>(*vIt);
00389 if (activeView)
00390 activeView->getViewer()->addViewProvider(pcProvider);
00391 }
00392
00393
00394 signalNewObject(*pcProvider);
00395 }
00396 else {
00397 Base::Console().Warning("Gui::Document::slotNewObject() no view provider for the object %s found\n",cName.c_str());
00398 }
00399 }
00400
00401 void Document::slotDeletedObject(const App::DocumentObject& Obj)
00402 {
00403 std::list<Gui::BaseView*>::iterator vIt;
00404 setModified(true);
00405
00406
00407
00408 ViewProvider* viewProvider = getViewProvider(&Obj);
00409 for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) {
00410 View3DInventor *activeView = dynamic_cast<View3DInventor *>(*vIt);
00411 if (activeView && viewProvider) {
00412 if (d->_pcInEdit == viewProvider)
00413 resetEdit();
00414 activeView->getViewer()->removeViewProvider(viewProvider);
00415 }
00416 }
00417
00418 if (viewProvider && viewProvider->getTypeId().isDerivedFrom(
00419 ViewProviderDocumentObject::getClassTypeId())) {
00420
00421 signalDeletedObject(*(static_cast<ViewProviderDocumentObject*>(viewProvider)));
00422
00423 delete viewProvider;
00424 d->_ViewProviderMap.erase(&Obj);
00425 }
00426 }
00427
00428 void Document::slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop)
00429 {
00430
00431 ViewProvider* viewProvider = getViewProvider(&Obj);
00432 if (viewProvider) {
00433 try {
00434 viewProvider->update(&Prop);
00435 } catch(const Base::MemoryException& e) {
00436 Base::Console().Error("Memory exception in '%s' thrown: %s\n",Obj.getNameInDocument(),e.what());
00437 } catch(Base::Exception &e){
00438 e.ReportException();
00439 } catch (...) {
00440 Base::Console().Error("Cannot update representation for '%s'.\n", Obj.getNameInDocument());
00441 }
00442
00443 if (viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
00444 signalChangedObject(static_cast<ViewProviderDocumentObject&>(*viewProvider), Prop);
00445 }
00446
00447
00448 setModified(true);
00449 }
00450
00451 void Document::slotRenamedObject(const App::DocumentObject& Obj)
00452 {
00453 ViewProvider* viewProvider = getViewProvider(&Obj);
00454 if (viewProvider && viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) {
00455 signalRenamedObject(*(static_cast<ViewProviderDocumentObject*>(viewProvider)));
00456 }
00457 }
00458
00459 void Document::slotActivatedObject(const App::DocumentObject& Obj)
00460 {
00461 ViewProvider* viewProvider = getViewProvider(&Obj);
00462 if (viewProvider && viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) {
00463 signalActivatedObject(*(static_cast<ViewProviderDocumentObject*>(viewProvider)));
00464 }
00465 }
00466
00467 void Document::setModified(bool b)
00468 {
00469 d->_isModified = b;
00470
00471 std::list<MDIView*> mdis = getMDIViews();
00472 for (std::list<MDIView*>::iterator it = mdis.begin(); it != mdis.end(); ++it) {
00473 (*it)->setWindowModified(b);
00474 }
00475 }
00476
00477 bool Document::isModified() const
00478 {
00479 return d->_isModified;
00480 }
00481
00482 App::Document* Document::getDocument(void) const
00483 {
00484 return d->_pcDocument;
00485 }
00486
00488 bool Document::save(void)
00489 {
00490 if (d->_pcDocument->isSaved()) {
00491 Gui::WaitCursor wc;
00492 Command::doCommand(Command::Doc,"App.getDocument(\"%s\").save()"
00493 ,d->_pcDocument->getName());
00494 setModified(false);
00495 return true;
00496 }
00497 else {
00498 return saveAs();
00499 }
00500 }
00501
00503 bool Document::saveAs(void)
00504 {
00505 getMainWindow()->statusBar()->showMessage(QObject::tr("Save document under new filename..."));
00506
00507 QString exe = QString::fromUtf8(App::GetApplication().getExecutableName());
00508 QString fn = QFileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save %1 Document").arg(exe),
00509 FileDialog::getWorkingDirectory(), QObject::tr("%1 document (*.FCStd)").arg(exe));
00510 if (!fn.isEmpty()) {
00511 FileDialog::setWorkingDirectory(fn);
00512 QString file = fn.toLower();
00513 if (!file.endsWith(QLatin1String(".fcstd"))) {
00514 fn += QLatin1String(".fcstd");
00515 QFileInfo fi;
00516 fi.setFile(fn);
00517 if (fi.exists()) {
00518
00519 int ret = QMessageBox::question(getMainWindow(), QObject::tr("Save As"),
00520 QObject::tr("%1 already exists.\n"
00521 "Do you want to replace it?").arg(fn),
00522 QMessageBox::Yes|QMessageBox::Default,
00523 QMessageBox::No|QMessageBox::Escape);
00524 if (ret != QMessageBox::Yes)
00525 fn = QString();
00526 }
00527 }
00528 }
00529
00530 if (!fn.isEmpty()) {
00531 QFileInfo fi;
00532 fi.setFile(fn);
00533 QString bn = fi.baseName();
00534
00535 const char * DocName = App::GetApplication().getDocumentName(getDocument());
00536
00537
00538 Gui::WaitCursor wc;
00539 Command::doCommand(Command::Doc,"App.getDocument(\"%s\").FileName = \"%s\""
00540 , DocName, (const char*)fn.toUtf8());
00541 Command::doCommand(Command::Doc,"App.getDocument(\"%s\").Label = \"%s\""
00542 , DocName, (const char*)bn.toUtf8());
00543 Command::doCommand(Command::Doc,"App.getDocument(\"%s\").save()"
00544 , DocName);
00545 setModified(false);
00546
00547 getMainWindow()->appendRecentFile(fi.filePath());
00548 return true;
00549 }
00550 else {
00551 getMainWindow()->statusBar()->showMessage(QObject::tr("Saving aborted"), 2000);
00552 return false;
00553 }
00554 }
00555
00556 unsigned int Document::getMemSize (void) const
00557 {
00558 unsigned int size = 0;
00559
00560
00561 std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator it;
00562 for (it = d->_ViewProviderMap.begin(); it != d->_ViewProviderMap.end(); ++it)
00563 size += it->second->getMemSize();
00564 return size;
00565 }
00566
00570 void Document::Save (Base::Writer &writer) const
00571 {
00572
00573 if (writer.isForceXML() == false) {
00574 writer.addFile("GuiDocument.xml", this);
00575
00576 if (App::GetApplication().GetParameterGroupByPath
00577 ("User parameter:BaseApp/Preferences/Document")->GetBool("SaveThumbnail",false)) {
00578 std::list<MDIView*> mdi = getMDIViews();
00579 for (std::list<MDIView*>::iterator it = mdi.begin(); it != mdi.end(); ++it) {
00580 if ((*it)->getTypeId().isDerivedFrom(View3DInventor::getClassTypeId())) {
00581 View3DInventorViewer* view = static_cast<View3DInventor*>(*it)->getViewer();
00582 d->thumb.setFileName(d->_pcDocument->FileName.getValue());
00583 d->thumb.setSize(128);
00584 d->thumb.setViewer(view);
00585 d->thumb.Save(writer);
00586 break;
00587 }
00588 }
00589 }
00590 }
00591 }
00592
00596 void Document::Restore(Base::XMLReader &reader)
00597 {
00598 reader.addFile("GuiDocument.xml",this);
00599
00600
00601 std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::iterator it;
00602 for (it = d->_ViewProviderMap.begin(); it != d->_ViewProviderMap.end(); ++it) {
00603 it->second->hide();
00604 it->second->startRestoring();
00605 }
00606 }
00607
00611 void Document::RestoreDocFile(Base::Reader &reader)
00612 {
00613
00614 Base::XMLReader xmlReader("GuiDocument.xml", reader);
00615
00616 int i,Cnt;
00617
00618 xmlReader.readElement("Document");
00619 long scheme = xmlReader.getAttributeAsInteger("SchemaVersion");
00620
00621
00622
00623
00624
00625 if (scheme == 1) {
00626
00627 xmlReader.readElement("ViewProviderData");
00628 Cnt = xmlReader.getAttributeAsInteger("Count");
00629 for (i=0 ;i<Cnt ;i++) {
00630 xmlReader.readElement("ViewProvider");
00631 std::string name = xmlReader.getAttribute("name");
00632 ViewProvider* pObj = getViewProviderByName(name.c_str());
00633 if (pObj)
00634 pObj->Restore(xmlReader);
00635 xmlReader.readEndElement("ViewProvider");
00636 }
00637 xmlReader.readEndElement("ViewProviderData");
00638
00639
00640 xmlReader.readElement("Camera");
00641 const char* ppReturn = xmlReader.getAttribute("settings");
00642 std::string sMsg = "SetCamera ";
00643 sMsg += ppReturn;
00644 if (strcmp(ppReturn, "") != 0) {
00645 if (d->_pcAppWnd->sendHasMsgToActiveView("SetCamera"))
00646 d->_pcAppWnd->sendMsgToActiveView(sMsg.c_str());
00647 }
00648 }
00649
00650 xmlReader.readEndElement("Document");
00651
00652
00653 if (!xmlReader.getFilenames().empty())
00654 xmlReader.readFiles(static_cast<zipios::ZipInputStream&>(reader));
00655
00656
00657 setModified(false);
00658 }
00659
00660 void Document::slotRestoredDocument(const App::Document&)
00661 {
00662
00663 std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::iterator it;
00664 for (it = d->_ViewProviderMap.begin(); it != d->_ViewProviderMap.end(); ++it) {
00665 it->second->finishRestoring();
00666 }
00667 }
00668
00672 void Document::SaveDocFile (Base::Writer &writer) const
00673 {
00674 writer.Stream() << "<?xml version='1.0' encoding='utf-8'?>" << std::endl
00675 << "<!--" << std::endl
00676 << " FreeCAD Document, see http://free-cad.sourceforge.net for more information..."
00677 << std::endl << "-->" << std::endl;
00678
00679 writer.Stream() << "<Document SchemaVersion=\"1\">" << std::endl;
00680
00681 std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator it;
00682
00683
00684 writer.incInd();
00685 writer.Stream() << writer.ind() << "<ViewProviderData Count=\""
00686 << d->_ViewProviderMap.size() <<"\">" << std::endl;
00687
00688 bool xml = writer.isForceXML();
00689
00690 writer.incInd();
00691 for(it = d->_ViewProviderMap.begin(); it != d->_ViewProviderMap.end(); ++it) {
00692 const App::DocumentObject* doc = it->first;
00693 ViewProvider* obj = it->second;
00694 writer.Stream() << writer.ind() << "<ViewProvider name=\""
00695 << doc->getNameInDocument() << "\">" << std::endl;
00696 obj->Save(writer);
00697 writer.Stream() << writer.ind() << "</ViewProvider>" << std::endl;
00698 }
00699 writer.setForceXML(xml);
00700
00701 writer.decInd();
00702 writer.Stream() << writer.ind() << "</ViewProviderData>" << std::endl;
00703 writer.decInd();
00704
00705
00706 QString viewPos;
00707 if (d->_pcAppWnd->sendHasMsgToActiveView("GetCamera")) {
00708 const char* ppReturn=0;
00709 d->_pcAppWnd->sendMsgToActiveView("GetCamera",&ppReturn);
00710
00711
00712 QStringList lines = QString(QString::fromAscii(ppReturn)).split(QLatin1String("\n"));
00713 if (lines.size() > 1) {
00714 lines.pop_front();
00715 viewPos = lines.join(QLatin1String(" "));
00716 }
00717 }
00718
00719 writer.incInd();
00720 writer.Stream() << writer.ind() << "<Camera settings=\""
00721 << (const char*)viewPos.toAscii() <<"\"/>" << std::endl;
00722 writer.decInd();
00723 writer.Stream() << "</Document>" << std::endl;
00724 }
00725
00726 void Document::exportObjects(const std::vector<App::DocumentObject*>& obj, Base::Writer& writer)
00727 {
00728 writer.Stream() << "<?xml version='1.0' encoding='utf-8'?>" << std::endl;
00729 writer.Stream() << "<Document SchemaVersion=\"1\">" << std::endl;
00730
00731 std::map<const App::DocumentObject*,ViewProvider*> views;
00732 for (std::vector<App::DocumentObject*>::const_iterator it = obj.begin(); it != obj.end(); ++it) {
00733 Document* doc = Application::Instance->getDocument((*it)->getDocument());
00734 if (doc) {
00735 ViewProvider* vp = doc->getViewProvider(*it);
00736 if (vp) views[*it] = vp;
00737 }
00738 }
00739
00740
00741 writer.incInd();
00742 writer.Stream() << writer.ind() << "<ViewProviderData Count=\""
00743 << views.size() <<"\">" << std::endl;
00744
00745 bool xml = writer.isForceXML();
00746 writer.setForceXML(true);
00747 writer.incInd();
00748 std::map<const App::DocumentObject*,ViewProvider*>::const_iterator jt;
00749 for (jt = views.begin(); jt != views.end(); ++jt) {
00750 const App::DocumentObject* doc = jt->first;
00751 ViewProvider* obj = jt->second;
00752 writer.Stream() << writer.ind() << "<ViewProvider name=\""
00753 << doc->getNameInDocument() << "\" type=\""
00754 << obj->getTypeId().getName()
00755 << "\">" << std::endl;
00756 obj->Save(writer);
00757 writer.Stream() << writer.ind() << "</ViewProvider>" << std::endl;
00758 }
00759 writer.setForceXML(xml);
00760
00761 writer.decInd();
00762 writer.Stream() << writer.ind() << "</ViewProviderData>" << std::endl;
00763 writer.decInd();
00764 writer.incInd();
00765 writer.Stream() << writer.ind() << "<Camera settings=\"\"/>" << std::endl;
00766 writer.decInd();
00767 writer.Stream() << "</Document>" << std::endl;
00768 }
00769
00770 void Document::importObjects(const std::vector<App::DocumentObject*>& obj, Base::Reader& reader)
00771 {
00772
00773 Base::XMLReader xmlReader("GuiDocument.xml", reader);
00774 xmlReader.readElement("Document");
00775 long scheme = xmlReader.getAttributeAsInteger("SchemaVersion");
00776
00777
00778
00779
00780
00781 if (scheme == 1) {
00782
00783 xmlReader.readElement("ViewProviderData");
00784 int Cnt = xmlReader.getAttributeAsInteger("Count");
00785 std::vector<App::DocumentObject*>::const_iterator it = obj.begin();
00786 for (int i=0;i<Cnt&&it!=obj.end();++i,++it) {
00787
00788
00789
00790 xmlReader.readElement("ViewProvider");
00791 std::string type = xmlReader.getAttribute("type");
00792 ViewProvider* pObj = getViewProvider(*it);
00793 while (pObj && type != pObj->getTypeId().getName()) {
00794 if (it != obj.end()) {
00795 ++it;
00796 pObj = getViewProvider(*it);
00797 }
00798 }
00799 if (pObj && type == pObj->getTypeId().getName())
00800 pObj->Restore(xmlReader);
00801 xmlReader.readEndElement("ViewProvider");
00802 if (it == obj.end())
00803 break;
00804 }
00805 xmlReader.readEndElement("ViewProviderData");
00806 }
00807
00808 xmlReader.readEndElement("Document");
00809 }
00810
00811 void Document::createView(const char* sType)
00812 {
00813 View3DInventor* view3D = new View3DInventor(this, getMainWindow());
00814
00815
00816 std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator It1;
00817 for (It1=d->_ViewProviderMap.begin();It1!=d->_ViewProviderMap.end();++It1)
00818 view3D->getViewer()->addViewProvider(It1->second);
00819 std::map<std::string,ViewProvider*>::const_iterator It2;
00820 for (It2=d->_ViewProviderMapAnnotation.begin();It2!=d->_ViewProviderMapAnnotation.end();++It2)
00821 view3D->getViewer()->addViewProvider(It2->second);
00822
00823 const char* name = getDocument()->Label.getValue();
00824
00825 QString title = QString::fromAscii("%1 : %2[*]")
00826 .arg(QString::fromUtf8(name)).arg(d->_iWinCount++);
00827
00828 view3D->setWindowTitle(title);
00829 view3D->setWindowIcon(QApplication::windowIcon());
00830 view3D->resize(400, 300);
00831 getMainWindow()->addWindow(view3D);
00832 }
00833
00834 void Document::attachView(Gui::BaseView* pcView, bool bPassiv)
00835 {
00836 if (!bPassiv)
00837 d->baseViews.push_back(pcView);
00838 else
00839 d->passiveViews.push_back(pcView);
00840 }
00841
00842 void Document::detachView(Gui::BaseView* pcView, bool bPassiv)
00843 {
00844 if (bPassiv) {
00845 if (find(d->passiveViews.begin(),d->passiveViews.end(),pcView)
00846 != d->passiveViews.end())
00847 d->passiveViews.remove(pcView);
00848 }
00849 else {
00850 if (find(d->baseViews.begin(),d->baseViews.end(),pcView)
00851 != d->baseViews.end())
00852 d->baseViews.remove(pcView);
00853
00854
00855 if (d->baseViews.size() == 0) {
00856
00857 std::list<Gui::BaseView*>::iterator it = d->passiveViews.begin();
00858 while (it != d->passiveViews.end()) {
00859 (*it)->setDocument(0);
00860 it = d->passiveViews.begin();
00861 }
00862
00863
00864 if (d->_isClosing == false)
00865 d->_pcAppWnd->onLastWindowClosed(this);
00866 }
00867 }
00868 }
00869
00870 void Document::onUpdate(void)
00871 {
00872 #ifdef FC_LOGUPDATECHAIN
00873 Base::Console().Log("Acti: Gui::Document::onUpdate()");
00874 #endif
00875
00876 std::list<Gui::BaseView*>::iterator it;
00877
00878 for (it = d->baseViews.begin();it != d->baseViews.end();++it) {
00879 (*it)->onUpdate();
00880 }
00881
00882 for (it = d->passiveViews.begin();it != d->passiveViews.end();++it) {
00883 (*it)->onUpdate();
00884 }
00885 }
00886
00887 void Document::onRelabel(void)
00888 {
00889 #ifdef FC_LOGUPDATECHAIN
00890 Base::Console().Log("Acti: Gui::Document::onRelabel()");
00891 #endif
00892
00893 std::list<Gui::BaseView*>::iterator it;
00894
00895 for (it = d->baseViews.begin();it != d->baseViews.end();++it) {
00896 (*it)->onRelabel(this);
00897 }
00898
00899 for (it = d->passiveViews.begin();it != d->passiveViews.end();++it) {
00900 (*it)->onRelabel(this);
00901 }
00902 }
00903
00904 bool Document::isLastView(void)
00905 {
00906 if (d->baseViews.size() <= 1)
00907 return true;
00908 return false;
00909 }
00910
00915 bool Document::canClose ()
00916 {
00917 if (!getDocument()->isClosable()) {
00918 QMessageBox::warning(getActiveView(),
00919 QObject::tr("Document not closable"),
00920 QObject::tr("The document is not closable for the moment."));
00921 return false;
00922 }
00923 else if (!Gui::Control().isAllowedAlterDocument()) {
00924 QMessageBox::warning(getActiveView(),
00925 QObject::tr("Document not closable"),
00926 QObject::tr("The document is in editing mode and thus cannot be closed for the moment.\n"
00927 "You either have to finish or cancel the editing in the task panel."));
00928 Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
00929 if (dlg) Gui::Control().showDialog(dlg);
00930 return false;
00931 }
00932
00933 if (!isModified())
00934 return true;
00935 bool ok = true;
00936 switch(QMessageBox::question(getActiveView(),
00937 QObject::tr("Unsaved document"),
00938 QObject::tr("Save document before close?"),
00939 QMessageBox::Yes | QMessageBox::Default,
00940 QMessageBox::No,
00941 QMessageBox::Cancel | QMessageBox::Escape))
00942 {
00943 case QMessageBox::Yes:
00944 ok = save();
00945 break;
00946 case QMessageBox::No:
00947 ok = true;
00948 break;
00949 case QMessageBox::Cancel:
00950 ok = false;
00951 break;
00952 }
00953
00954 return ok;
00955 }
00956
00957 std::list<MDIView*> Document::getMDIViews() const
00958 {
00959 std::list<MDIView*> views;
00960 for (std::list<BaseView*>::const_iterator it = d->baseViews.begin();
00961 it != d->baseViews.end(); ++it) {
00962 MDIView* view = dynamic_cast<MDIView*>(*it);
00963 if (view)
00964 views.push_back(view);
00965 }
00966
00967 return views;
00968 }
00969
00971 bool Document::sendMsgToViews(const char* pMsg)
00972 {
00973 std::list<Gui::BaseView*>::iterator it;
00974 const char** pReturnIgnore=0;
00975
00976 for (it = d->baseViews.begin();it != d->baseViews.end();++it) {
00977 if ((*it)->onMsg(pMsg,pReturnIgnore)) {
00978 return true;
00979 }
00980 }
00981
00982 for (it = d->passiveViews.begin();it != d->passiveViews.end();++it) {
00983 if ((*it)->onMsg(pMsg,pReturnIgnore)) {
00984 return true;
00985 }
00986 }
00987
00988 return false;
00989 }
00990
00992 MDIView* Document::getActiveView(void) const
00993 {
00994
00995 MDIView* active = getMainWindow()->activeWindow();
00996
00997
00998 std::list<MDIView*> mdis = getMDIViews();
00999
01000
01001 bool ok=false;
01002 for (std::list<MDIView*>::const_iterator it = mdis.begin(); it != mdis.end(); ++it) {
01003 if ((*it) == active) {
01004 ok = true;
01005 break;
01006 }
01007 }
01008
01009
01010 if (!ok && !mdis.empty())
01011 active = mdis.front();
01012
01013 return active;
01014 }
01015
01016
01017
01018
01019
01028 void Document::openCommand(const char* sName)
01029 {
01030 getDocument()->openTransaction(sName);
01031 }
01032
01033 void Document::commitCommand(void)
01034 {
01035 getDocument()->commitTransaction();
01036 }
01037
01038 void Document::abortCommand(void)
01039 {
01040 getDocument()->abortTransaction();
01041 }
01042
01044 std::vector<std::string> Document::getUndoVector(void) const
01045 {
01046 return getDocument()->getAvailableUndoNames();
01047 }
01048
01050 std::vector<std::string> Document::getRedoVector(void) const
01051 {
01052 return getDocument()->getAvailableRedoNames();
01053 }
01054
01056 void Document::undo(int iSteps)
01057 {
01058 for (int i=0;i<iSteps;i++) {
01059 getDocument()->undo();
01060 }
01061 }
01062
01064 void Document::redo(int iSteps)
01065 {
01066 for (int i=0;i<iSteps;i++) {
01067 getDocument()->redo();
01068 }
01069 }
01070
01071 PyObject* Document::getPyObject(void)
01072 {
01073 _pcDocPy->IncRef();
01074 return _pcDocPy;
01075 }