+#include "SALOMEDS_Tool.hxx"
+
+#include "SALOMEDSClient_ClientFactory.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SALOME_Exception)
+
+//#define NOTIFY_BY_EVENT
+
+class ObserverEvent : public QEvent
+{
+public:
+ ObserverEvent(const char* theID, CORBA::Long event):QEvent(QEvent::User)
+ {
+ _anID=theID;
+ _event=event;
+ }
+
+ std::string _anID;
+ CORBA::Long _event;
+};
+
+class SalomeApp_Study::Observer_i : public virtual POA_SALOMEDS::Observer, QObject
+{
+ typedef std::map<std::string, SalomeApp_DataObject*> EntryMap;
+ typedef std::map<std::string, SalomeApp_DataObject*>::iterator EntryMapIter;
+
+public:
+
+ Observer_i( SalomeApp_Study* aStudy):QObject(aStudy)
+ {
+ myStudy=aStudy;
+ fillEntryMap();
+ }
+
+ SUIT_DataObject* findObject( const char* theID ) const
+ {
+ EntryMap::const_iterator it = entry2SuitObject.find( theID );
+ return it != entry2SuitObject.end() ? it->second : 0;
+ }
+
+ virtual void notifyObserverID(const char* theID, CORBA::Long event)
+ {
+#ifdef NOTIFY_BY_EVENT
+ QCoreApplication::postEvent(this,new ObserverEvent(theID,event));
+#else
+ notifyObserverID_real(theID,event);
+#endif
+ }
+
+ virtual bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::User )
+ {
+ //START_TIMING(notify);
+ notifyObserverID_real(static_cast<ObserverEvent *>(event)->_anID.c_str(),static_cast<ObserverEvent *>(event)->_event);
+ //END_TIMING(notify,100);
+ }
+ return true;
+ }
+
+ void notifyObserverID_real(const std::string& theID, long event)
+ {
+ SalomeApp_DataObject* suit_obj = 0;
+
+ switch(event) {
+ case 1:
+ { //Add sobject
+ _PTR(SObject) aSObj = SalomeApp_Application::getStudy()->FindObjectID(theID);
+ _PTR(SComponent) aSComp = aSObj->GetFatherComponent();
+
+ if (!aSComp || aSComp->IsNull()) {
+ MESSAGE("Entry " << theID << " has not father component. Problem ??");
+ return;
+ }
+
+ // Mantis issue 0020136: Drag&Drop in OB
+ _PTR(UseCaseBuilder) aUseCaseBuilder = SalomeApp_Application::getStudy()->GetUseCaseBuilder();
+ if (aUseCaseBuilder->IsUseCaseNode(aSComp)) { // BEGIN: work with tree nodes structure
+ if (!aUseCaseBuilder->IsUseCaseNode(aSObj)) {
+ // tree node is not yet set, it is a normal situation
+ return;
+ }
+
+ _PTR(SObject) aFatherSO = aUseCaseBuilder->GetFather(aSObj);
+ if (!aFatherSO || aFatherSO->IsNull()) {
+ MESSAGE("Father SObject is not found. Problem ??");
+ return;
+ }
+
+ std::string parent_id = aFatherSO->GetID();
+ EntryMapIter it = entry2SuitObject.find(parent_id.c_str());
+
+ if (it == entry2SuitObject.end()) {
+ MESSAGE("Father data object is not found. Problem ??");
+ return;
+ }
+
+ SalomeApp_DataObject* aFatherDO = it->second;
+
+ it = entry2SuitObject.find(theID);
+ if (it != entry2SuitObject.end()) { // this SOobject is already added somethere
+ suit_obj = it->second;
+ SUIT_DataObject* oldFather = suit_obj->parent();
+ if (oldFather) {
+ oldFather->removeChild(suit_obj, false);
+ SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( myStudy->application() );
+// MESSAGE("myStudy: " << myStudy->id() << " app " << app);
+// MESSAGE("objectBrowser: "<< app->objectBrowser());
+ if (!app->objectBrowser()) {
+ MESSAGE("Object Browser not found. Problem ??");
+ return;
+ }
+ SUIT_AbstractModel* model = dynamic_cast<SUIT_AbstractModel*>(app->objectBrowser()->model());
+ model->forgetObject( suit_obj );
+
+ if (SalomeApp_DataObject* oldFatherSA = dynamic_cast<SalomeApp_DataObject*>(oldFather)) {
+ oldFatherSA->updateItem();
+ }
+ }
+ }
+ else {
+ suit_obj = new SalomeApp_DataObject(aSObj);
+ entry2SuitObject[theID] = suit_obj;
+ }
+
+ suit_obj->updateItem();
+ // define position in the data tree (in aFatherDO) to insert the aSObj
+ int pos = -1;
+ //int childDataObjCount = aFatherDO->childCount();
+ _PTR(UseCaseIterator) aUseCaseIter = aUseCaseBuilder->GetUseCaseIterator(aFatherSO);
+ for (int cur = 0; aUseCaseIter->More() && pos < 0; cur++, aUseCaseIter->Next()) {
+ if (aUseCaseIter->Value()->GetID() == theID) {
+ pos = cur;
+ break;
+ }
+ }
+
+ aFatherDO->insertChildAtPos(suit_obj, pos);
+ //aFatherDO->insertChild(suit_obj, pos);
+ aFatherDO->updateItem();
+
+ /* Define visibility state */
+ bool isComponent = dynamic_cast<SalomeApp_ModuleObject*>( suit_obj ) != 0;
+ if ( suit_obj && !isComponent && myStudy->visibilityState( theID.c_str() ) == Qtx::UnpresentableState ) {
+ QString moduleTitle = ((CAM_Application*)myStudy->application())->moduleTitle(suit_obj->componentDataType());
+ if (!moduleTitle.isEmpty()) {
+ LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer(moduleTitle,false);
+ if (aDisplayer) {
+ if(aDisplayer->canBeDisplayed(theID.c_str())) {
+ myStudy->setVisibilityState( theID.c_str(), Qtx::HiddenState ); //hide the just added object
+ //MESSAGE("Object with entry : "<< theID <<" CAN be displayed !!!");
+ }
+ //else
+ //MESSAGE("Object with entry : "<< theID <<" CAN'T be displayed !!!");
+ }
+ }
+ }
+ } // END: work with tree nodes structure
+ else { // BEGIN: work with study structure
+ EntryMapIter it = entry2SuitObject.find( theID );
+ if ( it != entry2SuitObject.end() ) {
+ MESSAGE("Entry " << theID << " is already added. Problem ??");
+ return;
+ }
+
+ int last2Pnt_pos = theID.rfind( ":" );
+ std::string parent_id = theID.substr( 0, last2Pnt_pos );
+ int tag = atoi( theID.substr( last2Pnt_pos+1 ).c_str() );
+
+ if ( parent_id.length() == 3 ) // "0:1" - root item?
+ {
+ // It's probably a SComponent
+ if ( theID == aSComp->GetID() )
+ suit_obj = new SalomeApp_ModuleObject( aSComp );
+ else
+ suit_obj = new SalomeApp_DataObject( aSObj );
+ }
+ else
+ {
+ suit_obj = new SalomeApp_DataObject( aSObj );
+ }
+
+ it = entry2SuitObject.find( parent_id );
+ if ( it != entry2SuitObject.end() ) {
+ SalomeApp_DataObject* father = it->second;
+ father->insertChildAtTag( suit_obj, tag );
+ }
+ else {
+ if ( parent_id.length() == 3 ) // "0:1" - root item?
+ {
+ // This should be for a module
+ SUIT_DataObject* father=myStudy->root();
+ father->appendChild(suit_obj);
+ }
+ else
+ {
+ MESSAGE("SHOULD NEVER GET HERE!!!");
+
+ //Try to find the SalomeApp_DataObject object parent
+ std::string root_id = parent_id.substr( 0, 4 );
+ std::string obj_id = parent_id.substr( 4 );
+
+ std::string anID;
+ std::string::size_type debut = 0;
+ std::string::size_type fin;
+ SalomeApp_DataObject* anObj = dynamic_cast<SalomeApp_DataObject*>( myStudy->root() );
+ while ( anObj ) {
+ fin = obj_id.find_first_of( ':', debut );
+ if ( fin == std::string::npos ) {
+ //last id
+ anObj = dynamic_cast<SalomeApp_DataObject*>(anObj->childObject(atoi(obj_id.substr(debut).c_str())-1));
+ if ( anObj )
+ entry2SuitObject[parent_id] = anObj;
+ break;
+ }
+ anID = root_id + obj_id.substr( 0, fin );
+ EntryMapIter it2 = entry2SuitObject.find( anID );
+ if ( it2 == entry2SuitObject.end() ) {
+ //the ID is not known in entry2SuitObject
+ anObj = dynamic_cast<SalomeApp_DataObject*>(anObj->childObject(atoi(obj_id.substr(debut, fin-debut).c_str())-1));
+ if ( anObj )
+ entry2SuitObject[anID] = anObj;
+ }
+ else
+ anObj = it2->second;
+ debut = fin+1;
+ }
+ if ( anObj )
+ anObj->insertChildAtTag( suit_obj, tag );
+ }
+ }
+ entry2SuitObject[theID] = suit_obj;
+ } // END: work with study structure
+ break;
+ }
+ case 2:
+ { // Remove sobject
+ EntryMapIter it = entry2SuitObject.find( theID );
+ if ( it != entry2SuitObject.end() )
+ {
+ suit_obj = it->second;
+ suit_obj->updateItem();
+ SUIT_DataObject* father=suit_obj->parent();
+ if(father)
+ father->removeChild(suit_obj);
+ entry2SuitObject.erase(it);
+ }
+ else
+ {
+ MESSAGE("Want to remove an unknown object" << theID);
+ }
+ break;
+ }
+ case 0:
+ { //modify sobject
+ //MESSAGE("Want to modify an object " << theID);
+ EntryMapIter it = entry2SuitObject.find( theID );
+ if ( it != entry2SuitObject.end() )
+ {
+ suit_obj = it->second;
+ suit_obj->updateItem();
+ }
+ else
+ {
+ MESSAGE("Want to modify an unknown object" << theID);
+ }
+ break;
+ }
+ case 5: //IOR of the object modified
+ {
+ EntryMapIter it = entry2SuitObject.find( theID );
+ if ( it != entry2SuitObject.end() )
+ suit_obj = it->second;
+
+ /* Define visibility state */
+ bool isComponent = dynamic_cast<SalomeApp_ModuleObject*>( suit_obj ) != 0;
+ if ( suit_obj && !isComponent ) {
+ QString moduleTitle = ((CAM_Application*)myStudy->application())->moduleTitle(suit_obj->componentDataType());
+ if (!moduleTitle.isEmpty()) {
+ LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer(moduleTitle,false);
+ if (aDisplayer) {
+ if(aDisplayer->canBeDisplayed(theID.c_str())) {
+ myStudy->setVisibilityState( theID.c_str(), Qtx::HiddenState );
+ //MESSAGE("Object with entry : "<< theID <<" CAN be displayed !!!");
+ }
+ //else
+ //MESSAGE("Object with entry : "<< theID <<" CAN'T be displayed !!!");
+ }
+ }
+ }
+ break;
+ }
+#ifndef DISABLE_PYCONSOLE
+ case 6: //NoteBook variables were modified
+ {
+ myStudy->onNoteBookVarUpdate( QString( theID.c_str() ) );
+ break;
+ }
+#endif
+ default:MESSAGE("Unknown event: " << event);break;
+ } //switch
+ } //notifyObserverID_real
+
+private:
+ void fillEntryMap()
+ {
+ entry2SuitObject.clear();
+ SUIT_DataObject* o = myStudy->root();
+ while (o) {
+ SalomeApp_DataObject* so = dynamic_cast<SalomeApp_DataObject*>( o );
+ if ( so ) {
+ std::string entry = so->entry().toUtf8().constData();
+ if ( entry.size() )
+ entry2SuitObject[entry] = so;
+ }
+ if ( o->childCount() > 0 ) {
+ // parse the children
+ o = o->firstChild();
+ }
+ else if ( o->nextBrother() > 0 ) {
+ o = o->nextBrother();
+ }
+ else {
+ // step to the next appropriate parent
+ o = o->parent();
+ while ( o ) {
+ if ( o->nextBrother() ) {
+ o = o->nextBrother();
+ break;
+ }
+ o = o->parent();
+ }
+ }
+ }
+ }
+
+private:
+ SalomeApp_Study* myStudy;
+ EntryMap entry2SuitObject;
+};
+
+
+/*!
+ Constructor.
+*/