int newWinMenu = createMenu( tr( "MEN_DESK_NEWWINDOW" ), windowMenu, -1, 0 );
createAction( CloseId, tr( "TOT_CLOSE" ), QIcon(), tr( "MEN_DESK_CLOSE" ), tr( "PRP_CLOSE" ),
- Qt::SHIFT+Qt::Key_C, desk, false, this, SLOT( onCloseWindow() ) );
+ Qt::CTRL+Qt::Key_F4, desk, false, this, SLOT( onCloseWindow() ) );
createAction( CloseAllId, tr( "TOT_CLOSE_ALL" ), QIcon(), tr( "MEN_DESK_CLOSE_ALL" ), tr( "PRP_CLOSE_ALL" ),
0, desk, false, this, SLOT( onCloseAllWindow() ) );
createAction( GroupAllId, tr( "TOT_GROUP_ALL" ), QIcon(), tr( "MEN_DESK_GROUP_ALL" ), tr( "PRP_GROUP_ALL" ),
#endif
createAction( RenameId, tr( "TOT_RENAME" ), QIcon(), tr( "MEN_DESK_RENAME" ), tr( "PRP_RENAME" ),
- Qt::SHIFT+Qt::Key_R, desk, false, this, SLOT( onRenameWindow() ) );
+ Qt::ALT+Qt::SHIFT+Qt::Key_R, desk, false, this, SLOT( onRenameWindow() ) );
createMenu( RenameId, windowMenu, -1 );
int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
return true;
}
+/*!
+ Does nothing by default. Should be redefined in light modules
+ that want to participate in "Dump study" operation.
+*/
+bool LightApp_DataModel::dumpPython( const QString&, CAM_Study*, bool, QStringList& )
+{
+ return true;
+}
+
/*!
Emit closed()
*/
virtual bool save( QStringList& );
virtual bool saveAs( const QString&, CAM_Study*, QStringList& );
virtual bool close();
+ virtual bool dumpPython( const QString&,
+ CAM_Study*,
+ bool,
+ QStringList& );
virtual void update( LightApp_DataObject* = 0, LightApp_Study* = 0 );
return QString();
}
+/*!
+ \brief Returns the string identifier of the data objects referenced by this one.
+
+ This method should be reimplemented in the subclasses.
+ Default implementation returns null string.
+
+ \return ID string of the referenced data object
+*/
+QString LightApp_DataObject::refEntry() const
+{
+ return QString();
+}
+
+/*!
+ \brief Tells if this data objects is a reference to some other or not.
+
+ The base implementation retuns true, if refEntry() returns non-empty string.
+
+ \return true if refEntry() is a non-empty string.
+*/
+bool LightApp_DataObject::isReference() const
+{
+ return !refEntry().isEmpty();
+}
+
/*!
\brief Get the data object unique key.
\return data object key
/*!
\brief Get object text data for the specified column.
- Column with \a id = 0 (NameId) is supposed to be used
+ Column with \a id == NameId is supposed to be used
to get the object name.
- Column with \a id = 1 (EntryId) is supposed to be used
+ Column with \a id == EntryId is supposed to be used
to get the object entry.
+ Column with \a id == RefEntryId is supposed to be used
+ to show the entry of the object referenced by this one.
\param id column id
\return object text data
*/
QString LightApp_DataObject::text( const int id ) const
{
- return id == EntryId ? entry() : CAM_DataObject::text( id );
+ QString txt;
+
+ switch ( id )
+ {
+ case EntryId:
+ txt = entry();
+ break;
+ case RefEntryId:
+ // Issue 21379: reference support at LightApp level
+ if ( isReference() )
+ txt = refEntry();
+ break;
+ default:
+ // Issue 21379: Note that we cannot return some specially decorated
+ // name string (like "* ref_obj_name") when isReference() returns true,
+ // since there is no generic way at LightApp level
+ // to query the object name using refEntry() up to now.
+ // TODO: Think how to make reference name generation
+ // more generic at move it here from SalomeApp level...
+ txt = CAM_DataObject::text( id );
+ break;
+ }
+
+ return txt;
+}
+
+/*!
+ \brief Get data object color for the specified column.
+ \param role color role
+ \param id column id (not used)
+ \return object color for the specified column
+*/
+QColor LightApp_DataObject::color( const ColorRole role, const int id) const
+{
+ QColor c;
+
+ // Issue 21379: reference support at LightApp level
+ // Centralized way for choosing text/background color for references.
+ // Colors for "normal" objects should be chosen by sub-classes.
+ switch ( role )
+ {
+ case Text:
+ case Foreground:
+ // text color (not selected item)
+ // TODO: think how to detect invalid references...
+ if ( isReference() )
+ c = QColor( 255, 0, 0 ); // valid reference (red)
+ break;
+
+ case Highlight:
+ // background color for the highlighted item
+ // TODO: think how to detect invalid references...
+ if ( isReference() )
+ c = QColor( 255, 0, 0 ); // valid reference (red)
+ break;
+
+ case HighlightedText:
+ // text color for the highlighted item
+ if ( isReference() )
+ c = QColor( 255, 255, 255 ); // white
+ break;
+
+ default:
+ break;
+ }
+
+ if ( !c.isValid() )
+ c = CAM_DataObject::color( role, id );
+
+ return c;
}
/*!
public:
//! Column id
- enum {
- EntryId = VisibilityId + 1 //!< entry column
+ enum {
+ EntryId = VisibilityId + 1, //!< entry column
+ RefEntryId //!< reference entry column
};
public:
virtual SUIT_DataObjectKey* key() const;
virtual QString entry() const;
+ virtual QString refEntry() const;
+ virtual bool isReference() const;
+
virtual QString text( const int = NameId ) const;
+ virtual QColor color( const ColorRole, const int = NameId ) const;
virtual SUIT_DataObject* componentObject() const;
virtual QString componentDataType() const;
<parameter name="SUPERVGraph" value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
<parameter name="QxGraph" value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
<parameter name="ToolsGUI" value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
+ <parameter name="LogWindow" value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
</section>
<section name="desktop" >
<!-- Default GUI desktop state, position, size -->
SALOME_PYQT_DataModelLight::SALOME_PYQT_DataModelLight(CAM_Module * theModule)
: LightApp_DataModel( theModule ),
myFileName( "" ),
- myStudyURL( "" )
+ myStudyURL( "" ),
+ myModified( false )
{
}
return false;
LightApp_DataModel::open( theURL, aDoc, theListOfFiles );
+
+ setModified( false );
return aModule->open(theListOfFiles);
theListOfFiles.append(QString(aTmpDir.c_str()));
int listSize = theListOfFiles.size();
aModule->save(theListOfFiles);
+
+ setModified( false );
+
//Return true if in the List of files was added item(s)
//else return false
return theListOfFiles.size() > listSize;
return true;
}
+//=================================================================================
+// function : dumpPython()
+// purpose : Re-defined from LigthApp_DataModel in order to participate
+// in dump study process
+//=================================================================================
+bool SALOME_PYQT_DataModelLight::dumpPython( const QString& theURL,
+ CAM_Study* theStudy,
+ bool isMultiFile,
+ QStringList& theListOfFiles )
+{
+ MESSAGE("SALOME_PYQT_DataModelLight::dumpPython()");
+
+ LightApp_DataModel::dumpPython( theURL, theStudy, isMultiFile, theListOfFiles );
+
+ LightApp_Study* study = dynamic_cast<LightApp_Study*>( theStudy );
+ SALOME_PYQT_ModuleLight* aModule = dynamic_cast<SALOME_PYQT_ModuleLight*>(module());
+
+ if(!aModule || !study)
+ return false;
+
+ std::string aTmpDir = study->GetTmpDir( theURL.toLatin1().constData(), isMultiFile );
+
+ theListOfFiles.append( QString( aTmpDir.c_str() ) );
+ int oldSize = theListOfFiles.size();
+
+ aModule->dumpPython( theListOfFiles );
+
+ //Return true if some items have been added, else return false
+ return theListOfFiles.size() > oldSize;
+}
+
//=================================================================================
// function : isModified()
-// purpose : default implementation, always returns false so as not to mask study's isModified()
+// purpose : returns this model's modification status that can be controlled
+// with help of setModified() calls by the underlying Python module
//=================================================================================
bool SALOME_PYQT_DataModelLight::isModified() const
{
- return false;
+ return myModified;
}
//=================================================================================
-// function : isSaved()
-// purpose : default implementation, always returns true so as not to mask study's isSaved()
+// function : setModified()
+// purpose : sets the model's modification status, should be used by
+// the underlying Python module when its data changes.
//=================================================================================
-bool SALOME_PYQT_DataModelLight::isSaved() const
+void SALOME_PYQT_DataModelLight::setModified( bool flag )
{
- return true;
+ myModified = flag;
}
-
//=================================================================================
// function : close()
// purpose : Close data model operation
virtual bool saveAs ( const QString&, CAM_Study*, QStringList& );
virtual bool close ();
virtual bool create ( CAM_Study* );
+ virtual bool dumpPython( const QString&,
+ CAM_Study*,
+ bool,
+ QStringList& );
virtual bool isModified () const;
- virtual bool isSaved () const;
+ void setModified( bool );
virtual void update ( LightApp_DataObject* = 0, LightApp_Study* = 0 );
private:
QString myFileName;
QString myStudyURL;
+ bool myModified;
};
#endif // SALOME_PYQT_DATAMODELLIGHT_H
return myEntry;
}
+//=================================================================================
+// function : SALOME_PYQT_DataObjectLight::refEntry()
+// purpose : return entry of the data object referenced by this one (if any)
+//=================================================================================
+QString SALOME_PYQT_DataObjectLight::refEntry() const
+{
+ return myRefEntry;
+}
+
+//=================================================================================
+// function : SALOME_PYQT_DataObjectLight::setRefEntry()
+// purpose : sets entry of the data object referenced by this one
+//=================================================================================
+void SALOME_PYQT_DataObjectLight::setRefEntry( const QString& refEntry )
+{
+ myRefEntry = refEntry;
+}
+
//=================================================================================
// function : SALOME_PYQT_DataObjectLight::name()
// purpose : return name of object
return myToolTip;
}
+//=================================================================================
+// function : SALOME_PYQT_DataObjectLight::toolTip()
+// purpose : return toolTip of object
+//=================================================================================
+QColor SALOME_PYQT_DataObjectLight::color( const ColorRole role, const int id ) const
+{
+ QColor c;
+
+ switch ( role )
+ {
+ case Text:
+ case Foreground:
+ if ( !isReference() )
+ c = myColor;
+ break;
+
+ default:
+ break;
+ }
+
+ // Issue 21379: LightApp_DataObject::color() defines colors for valid references
+ if ( !c.isValid() )
+ c = LightApp_DataObject::color( role, id );
+
+ return c;
+}
bool SALOME_PYQT_DataObjectLight::setName(const QString& name)
{
{
myToolTip = tooltip;
}
+
+void SALOME_PYQT_DataObjectLight::setColor(const QColor& color)
+{
+ myColor = color;
+}
virtual ~SALOME_PYQT_DataObjectLight();
virtual QString entry() const;
+
+ virtual QString refEntry() const;
+ void setRefEntry( const QString& refEntry );
virtual QString name() const;
- QPixmap icon(const int = NameId) const;
- QString toolTip(const int = NameId) const;
-
- bool setName(const QString& name);
- void setIcon(const QString& icon);
- void setToolTip(const QString& tooltip);
+ virtual QPixmap icon(const int = NameId) const;
+ virtual QString toolTip(const int = NameId) const;
+
+ bool setName(const QString& name);
+ void setIcon(const QString& icon);
+ void setToolTip(const QString& tooltip);
+
+ virtual QColor color( const ColorRole, const int = NameId ) const;
+ void setColor(const QColor& color);
private:
QString myEntry;
+ QString myRefEntry;
QString myName;
QString myToolTip;
QPixmap myIcon;
+ QColor myColor;
};
#endif // SALOME_PYQT_DATAOBJECTLIGHT_H
return;
if ( PyObject_HasAttrString(myModule, (char*)"saveFiles") ) {
+ // temporary set myInitModule because saveEvent() method
+ // might be called by the framework when this module is inactive,
+ // but still it should be possible to access this module's data
+ // from Python
+ myInitModule = this;
+
PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"saveFiles",
(char*)"s", (*it).toLatin1().constData()));
+
+ myInitModule = 0;
+
+ if( !res ) {
+ PyErr_Print();
+ }
+ else{
+ // parse the return value
+ // result can be one string...
+ if ( PyString_Check( res ) ) {
+ QString astr = PyString_AsString( res );
+ //SCRUTE(astr);
+ theListOfFiles.append(astr);
+ }
+ //also result can be a list...
+ else if ( PyList_Check( res ) ) {
+ int size = PyList_Size( res );
+ for ( int i = 0; i < size; i++ ) {
+ PyObject* value = PyList_GetItem( res, i );
+ if( value && PyString_Check( value ) ) {
+ theListOfFiles.append( PyString_AsString( value ) );
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Python dump request.
+ * Called when user activates dump study operation.
+ */
+void SALOME_PYQT_ModuleLight::dumpPython(QStringList& theListOfFiles)
+{
+ MESSAGE("SALOME_PYQT_ModuleLight::dumpPython()")
+ // perform synchronous request to Python event dispatcher
+ class DumpEvent: public PyInterp_LockRequest
+ {
+ public:
+ DumpEvent(PyInterp_Interp* _py_interp,
+ SALOME_PYQT_ModuleLight* _obj,
+ QStringList& _files_list)
+ : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
+ myObj( _obj ) ,
+ myFilesList(_files_list) {}
+ protected:
+ virtual void execute()
+ {
+ myObj->dumpEvent(myFilesList);
+ }
+ private:
+ SALOME_PYQT_ModuleLight* myObj;
+ QStringList& myFilesList;
+ };
+
+ // Posting the request only if dispatcher is not busy!
+ // Executing the request synchronously
+ if ( !PyInterp_Dispatcher::Get()->IsBusy() )
+ PyInterp_Dispatcher::Get()->Exec( new DumpEvent( myInterp, this, theListOfFiles ) );
+}
+
+void SALOME_PYQT_ModuleLight::dumpEvent(QStringList& theListOfFiles)
+{
+ MESSAGE("SALOME_PYQT_ModuleLight::dumpEvent()");
+ QStringList::Iterator it = theListOfFiles.begin();
+ // Python interpreter should be initialized and Python module should be
+ // import first
+ if ( !myInterp || !myModule || (it == theListOfFiles.end()))
+ return;
+
+ if ( PyObject_HasAttrString(myModule, (char*)"dumpStudy") ) {
+ // temporary set myInitModule because dumpEvent() method
+ // might be called by the framework when this module is inactive,
+ // but still it should be possible to access this module's data
+ // from Python
+ myInitModule = this;
+
+ PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"dumpStudy",
+ (char*)"s", (*it).toLatin1().constData()));
+
+ myInitModule = 0;
+
if( !res ) {
PyErr_Print();
}
}
}
+/*
+ * Return color of object
+ */
+QColor SALOME_PYQT_ModuleLight::getColor(const QString& obj)
+{
+ SALOME_PYQT_DataObjectLight* dataObj = findObject( obj );
+ if( dataObj ) {
+ return dataObj->color( SUIT_DataObject::Foreground );
+ }
+ return QColor();
+}
+
+/*
+ * Set color for object
+ */
+void SALOME_PYQT_ModuleLight::setColor(const QString& obj, const QColor& color)
+{
+ SALOME_PYQT_DataObjectLight* dataObj = findObject( obj );
+ if( dataObj ) {
+ dataObj->setColor( color );
+ }
+}
+
+/*
+ * Return entry of the referenced object (if any)
+ */
+QString SALOME_PYQT_ModuleLight::getReference(const QString& obj)
+{
+ SALOME_PYQT_DataObjectLight* dataObj = findObject(obj);
+ if(dataObj) {
+ return dataObj->refEntry();
+ }
+ return QString::null;
+}
+
+
+/*
+ * Set entry of the referenced object
+ */
+void SALOME_PYQT_ModuleLight::setReference(const QString& obj, const QString& refEntry)
+{
+ SALOME_PYQT_DataObjectLight* dataObj = findObject(obj);
+ if(dataObj) {
+ dataObj->setRefEntry(refEntry);
+ }
+}
+
/*
* Remove object by entry
*/
void setPreferenceProperty( const int, const QString&,
const QVariant& );
- void save(QStringList& theListOfFiles);
-
- bool open(QStringList theListOfFiles);
+ void save(QStringList& theListOfFiles);
+ bool open(QStringList theListOfFiles);
+ void dumpPython(QStringList& theListOfFiles);
/*create new SALOME_PYQT_DataObjectLight and return its entry*/
- QString createObject(const QString& parent);
- QString createObject(const QString& name,
- const QString& iconname,
- const QString& tooltip,
- const QString& parent);
+ QString createObject(const QString& parent);
+ QString createObject(const QString& name,
+ const QString& iconname,
+ const QString& tooltip,
+ const QString& parent);
/*Sets Name, Icon and Tool Tip for object*/
void setName(const QString& obj,const QString& iconname);
void setIcon(const QString& obj,const QString& name);
- void setToolTip(const QString& obj, const QString& name);
+ void setToolTip(const QString& obj, const QString& tooltip);
/*Gets Name and Tool Tip for object*/
QString getName(const QString& obj);
QString getToolTip(const QString& obj);
+
+ void setColor(const QString& obj, const QColor& color);
+ QColor getColor(const QString& obj);
+
+ void setReference( const QString& obj,
+ const QString& refEntry );
+ QString getReference( const QString& obj );
+
/*remove object*/
void removeObject(const QString& obj);
/*remove child*/
void connectView( const SUIT_ViewWindow* );
void saveEvent(QStringList& theListOfFiles);
+ void dumpEvent(QStringList& theListOfFiles);
void openEvent(QStringList theListOfFiles, bool& opened);
SALOME_PYQT_DataObjectLight* findObject(const QString& entry);
#endif
#include <SALOME_PYQT_ModuleLight.h> // this include must be first!!!
+#include <SALOME_PYQT_DataModelLight.h>
#include "SalomePyQt.h"
#include <QApplication>
ProcessVoidEvent( new TEvent( studyId, updateSelection ) );
}
+
+/*!
+ SalomePyQt::isModified()
+ \return The modification status of the data model
+ for the currently active Python module
+ \sa setModified()
+*/
+class TIsModifiedEvent: public SALOME_Event
+{
+public:
+ typedef bool TResult;
+ TResult myResult;
+ TIsModifiedEvent() : myResult( false ) {}
+ virtual void Execute()
+ {
+ SALOME_PYQT_ModuleLight* module = getActiveModule();
+ if ( !module )
+ return;
+
+ SALOME_PYQT_DataModelLight* aModel =
+ dynamic_cast<SALOME_PYQT_DataModelLight*>( module->dataModel() );
+ if ( aModel )
+ myResult = aModel->isModified();
+ }
+};
+bool SalomePyQt::isModified()
+{
+ return ProcessEvent(new TIsModifiedEvent());
+}
+
+/*!
+ SalomePyQt::setModified()
+
+ Sets the modification status of the data model for
+ the currently active Python module. This method should be used
+ by the Python code in order to enable/disable "Save" operation
+ depending on the module's data state.
+
+ \param New modification status of the data model
+
+ \sa isModified()
+*/
+void SalomePyQt::setModified( bool flag )
+{
+ class TEvent: public SALOME_Event
+ {
+ bool myFlag;
+ public:
+ TEvent( bool flag )
+ : myFlag( flag ) {}
+ virtual void Execute()
+ {
+ SALOME_PYQT_ModuleLight* module = getActiveModule();
+ if ( !module )
+ return;
+
+ SALOME_PYQT_DataModelLight* aModel =
+ dynamic_cast<SALOME_PYQT_DataModelLight*>( module->dataModel() );
+ LightApp_Application* aLApp =
+ dynamic_cast<LightApp_Application*>( module->application() );
+ if ( !aModel || !aLApp )
+ return;
+
+ aModel->setModified( myFlag );
+ aLApp->updateActions();
+ }
+ };
+ ProcessVoidEvent( new TEvent( flag ) );
+}
+
/*!
\brief Default resource file section name.
\internal
ProcessVoidEvent(new TSetToolTipEvent(obj,tooltip));
}
+/*!
+ SalomePyQt::setReference(obj,refEntry)
+ Set entry to referenced object
+*/
+class TSetRefEvent: public SALOME_Event
+{
+public:
+ QString myObj;
+ QString myRefEntry;
+ TSetRefEvent( const QString& obj,
+ const QString& refEntry) : myObj(obj),
+ myRefEntry(refEntry) {}
+ virtual void Execute() {
+ SALOME_PYQT_ModuleLight* module = getActiveModule();
+ if ( module )
+ module->setReference(myObj,myRefEntry);
+ }
+};
+void SalomePyQt::setReference(const QString& obj,const QString& refEntry)
+{
+ ProcessVoidEvent(new TSetRefEvent(obj,refEntry));
+}
+
+/*!
+ SalomePyQt::setColor(obj,color)
+ Set object color
+*/
+class TSetColorEvent: public SALOME_Event
+{
+public:
+ QString myObj;
+ QColor myColor;
+ TSetColorEvent( const QString& obj,
+ const QColor& color) : myObj(obj),
+ myColor(color) {}
+ virtual void Execute() {
+ SALOME_PYQT_ModuleLight* module = getActiveModule();
+ if ( module )
+ module->setColor(myObj,myColor);
+ }
+};
+void SalomePyQt::setColor(const QString& obj,const QColor& color)
+{
+ ProcessVoidEvent(new TSetColorEvent(obj,color));
+}
+
/*!
SalomePyQt::getName(obj)
Return name of object
return ProcessEvent(new TGetToolTipEvent(obj));
}
+/*!
+ SalomePyQt::getReference(obj)
+ Return entry of the referenced object (if any)
+*/
+class TGetRefEvent: public SALOME_Event
+{
+public:
+ typedef QString TResult;
+ TResult myResult;
+ QString myObj;
+ TGetRefEvent( const QString& obj ) : myObj(obj) {}
+ virtual void Execute() {
+ SALOME_PYQT_ModuleLight* module = getActiveModule();
+ if ( module )
+ myResult = module->getReference(myObj);
+ }
+};
+QString SalomePyQt::getReference(const QString& obj)
+{
+ return ProcessEvent(new TGetRefEvent(obj));
+}
+
+/*!
+ SalomePyQt::getColor(obj)
+ Return the color of the object
+*/
+class TGetColorEvent: public SALOME_Event
+{
+public:
+ typedef QColor TResult;
+ TResult myResult;
+ QString myObj;
+ TGetColorEvent( const QString& obj ) : myObj(obj) {}
+ virtual void Execute() {
+ SALOME_PYQT_ModuleLight* module = getActiveModule();
+ if ( module )
+ myResult = module->getColor(myObj);
+ }
+};
+QColor SalomePyQt::getColor(const QString& obj)
+{
+ return ProcessEvent(new TGetColorEvent(obj));
+}
/*!
SalomePyQt::removeChild(obj)
static bool activateModule( const QString& );
static void updateObjBrowser( const int = 0, bool = true );
+ static bool isModified();
+ static void setModified( bool );
+
static QString getFileName ( QWidget*, const QString&, const QStringList&, const QString&, bool );
static QStringList getOpenFileNames ( QWidget*, const QString&, const QStringList&, const QString& );
static QString getExistingDirectory( QWidget*, const QString&, const QString& );
static QString getName(const QString& obj);
static QString getToolTip(const QString& obj);
+ static void setColor(const QString& obj,const QColor& color);
+ static QColor getColor(const QString& obj);
+
+ static void setReference( const QString& obj,
+ const QString& refEntry );
+ static QString getReference( const QString& obj );
+
static QIcon loadIcon( const QString&, const QString& );
static void helpContext( const QString&, const QString& );
static const QString getActiveComponent() /ReleaseGIL/ ;
static SIP_PYOBJECT getActivePythonModule() /ReleaseGIL/ ;
static bool activateModule( const QString& ) /ReleaseGIL/ ;
- static void updateObjBrowser( const int = 0, bool = true ) /ReleaseGIL/ ;
+ static void updateObjBrowser( const int = 0, bool = true ) /ReleaseGIL/ ;
+
+ static bool isModified() /ReleaseGIL/ ;
+ static void setModified( bool ) /ReleaseGIL/ ;
static QString getFileName ( QWidget*, const QString&, const QStringList&, const QString&, bool ) /ReleaseGIL/ ;
static QStringList getOpenFileNames ( QWidget*, const QString&, const QStringList&, const QString& ) /ReleaseGIL/ ;
static QString createObject( const QString& = QString("") ) /ReleaseGIL/ ;
static QString createObject( const QString&,
- const QString&,
- const QString&,
- const QString& = QString("") ) /ReleaseGIL/ ;
+ const QString&,
+ const QString&,
+ const QString& = QString("") ) /ReleaseGIL/ ;
static void setName(const QString& ,const QString& ) /ReleaseGIL/ ;
static void setIcon(const QString& ,const QString& ) /ReleaseGIL/ ;
static QString getName(const QString& ) /ReleaseGIL/ ;
static QString getToolTip(const QString& ) /ReleaseGIL/ ;
+ static void setColor( const QString&, const QColor& ) /ReleaseGIL/ ;
+ static QColor getColor( const QString& ) /ReleaseGIL/ ;
+
+ static void setReference( const QString& ,const QString& ) /ReleaseGIL/ ;
+ static QString getReference( const QString& ) /ReleaseGIL/ ;
+
static void removeObject(const QString& ) /ReleaseGIL/ ;
static void removeChild(const QString& = QString("") ) /ReleaseGIL/ ;
static QStringList getChildren(const QString&=QString("") , const bool = false) /ReleaseGIL/ ;
createAction( FileSaveAsId, tr( "TOT_DESK_FILE_SAVEAS" ), QIcon(),
tr( "MEN_DESK_FILE_SAVEAS" ), tr( "PRP_DESK_FILE_SAVEAS" ),
- Qt::CTRL+Qt::Key_A, desk, false, this, SLOT( onSaveAsDoc() ) );
+ Qt::CTRL+Qt::SHIFT+Qt::Key_S, desk, false, this, SLOT( onSaveAsDoc() ) );
createAction( EditCopyId, tr( "TOT_DESK_EDIT_COPY" ),
resMgr->loadPixmap( "STD", tr( "ICON_EDIT_COPY" ) ),
QAction* a = createAction( ViewStatusBarId, tr( "TOT_DESK_VIEW_STATUSBAR" ),
QIcon(), tr( "MEN_DESK_VIEW_STATUSBAR" ),
- tr( "PRP_DESK_VIEW_STATUSBAR" ), Qt::SHIFT+Qt::Key_S, desk, true );
+ tr( "PRP_DESK_VIEW_STATUSBAR" ), Qt::ALT+Qt::SHIFT+Qt::Key_S, desk, true );
a->setChecked( desk->statusBar()->isVisibleTo( desk ) );
connect( a, SIGNAL( toggled( bool ) ), this, SLOT( onViewStatusBar( bool ) ) );
createAction( HelpAboutId, tr( "TOT_DESK_HELP_ABOUT" ), QIcon(),
tr( "MEN_DESK_HELP_ABOUT" ), tr( "PRP_DESK_HELP_ABOUT" ),
- Qt::SHIFT+Qt::Key_A, desk, false, this, SLOT( onHelpAbout() ) );
+ Qt::ALT+Qt::SHIFT+Qt::Key_A, desk, false, this, SLOT( onHelpAbout() ) );
QtxDockAction* dwa = new QtxDockAction( tr( "TOT_DOCKWINDOWS" ), tr( "MEN_DESK_VIEW_DOCKWINDOWS" ), desk );
// But the workstack must occupy as much space as possible -- set Expanding for it.
myWorkstack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
- myWorkstack->setAccel( QtxWorkstack::SplitVertical, Qt::SHIFT + Qt::Key_V );
- myWorkstack->setAccel( QtxWorkstack::SplitHorizontal, Qt::SHIFT + Qt::Key_H );
- myWorkstack->setAccel( QtxWorkstack::Close, Qt::SHIFT + Qt::Key_C );
+ myWorkstack->setAccel( QtxWorkstack::SplitVertical, Qt::ALT + Qt::SHIFT + Qt::Key_V );
+ myWorkstack->setAccel( QtxWorkstack::SplitHorizontal, Qt::ALT + Qt::SHIFT + Qt::Key_H );
+ myWorkstack->setAccel( QtxWorkstack::Close, Qt::CTRL + Qt::Key_F4 );
SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
if ( resMgr ) {
resMgr->loadPixmap( "STD", tr( "ICON_DESK_WINDOW_HSPLIT" ) ) );
myWorkstackAction->setText( QtxWorkstackAction::SplitHorizontal, tr( "MEN_DESK_WINDOW_HSPLIT" ) );
myWorkstackAction->setStatusTip( QtxWorkstackAction::SplitHorizontal, tr( "PRP_DESK_WINDOW_HSPLIT" ) );
- myWorkstackAction->setAccel( QtxWorkstackAction::SplitHorizontal, Qt::SHIFT + Qt::Key_H );
+ myWorkstackAction->setAccel( QtxWorkstackAction::SplitHorizontal, Qt::ALT + Qt::SHIFT + Qt::Key_H );
// Split Vertical
myWorkstackAction->setIcon( QtxWorkstackAction::SplitVertical,
resMgr->loadPixmap( "STD", tr( "ICON_DESK_WINDOW_VSPLIT" ) ) );
myWorkstackAction->setText( QtxWorkstackAction::SplitVertical, tr( "MEN_DESK_WINDOW_VSPLIT" ) );
myWorkstackAction->setStatusTip( QtxWorkstackAction::SplitVertical, tr( "PRP_DESK_WINDOW_VSPLIT" ) );
- myWorkstackAction->setAccel( QtxWorkstackAction::SplitVertical, Qt::SHIFT + Qt::Key_V );
+ myWorkstackAction->setAccel( QtxWorkstackAction::SplitVertical, Qt::ALT + Qt::SHIFT + Qt::Key_V );
QtxActionMenuMgr* mMgr = menuMgr();
if ( !mMgr )
//! Catalog Generator
createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
- Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
+ Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
//! Registry Display
createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
QFileInfo aFileInfo(aFileName);
if( aFileInfo.isDir() ) // IPAL19257
return;
+
+ // Issue 21377 - dump study implementation moved to SalomeApp_Study class
+ bool res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
- int savePoint;
- _PTR(AttributeParameter) ap;
- _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
- if(ip->isDumpPython(appStudy->studyDS())) ip->setDumpPython(appStudy->studyDS()); //Unset DumpPython flag.
- if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
- ip->setDumpPython(appStudy->studyDS());
- savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
- }
- bool res = aStudy->DumpStudy( aFileInfo.absolutePath().toStdString(),
- aFileInfo.baseName().toStdString(),
- toPublish,
- isMultiFile);
- if ( toSaveGUI )
- appStudy->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
if ( !res )
SUIT_MessageBox::warning( desktop(),
QObject::tr("WRN_WARNING"),
int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
- for ( int i = SalomeApp_DataObject::EntryId; i <= SalomeApp_DataObject::RefEntryId; i++ )
+ for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
{
pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
return &_lcc;
}
-/*!Return default engine IOR for light modules*/
-QString SalomeApp_Application::defaultEngineIOR()
-{
- /// Look for a default module engine (needed for CORBAless modules to use SALOMEDS persistence)
- QString anIOR( "" );
- CORBA::Object_ptr anEngine = namingService()->Resolve( "/SalomeAppEngine" );
- if ( !CORBA::is_nil( anEngine ) )
- {
- CORBA::String_var objStr = orb()->object_to_string( anEngine );
- anIOR = QString( objStr.in() );
- }
- return anIOR;
-}
-
/*!Private SLOT. On preferences.*/
void SalomeApp_Application::onProperties()
{
/*!find original object by double click on item */
void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
{
- SalomeApp_DataObject* obj = dynamic_cast<SalomeApp_DataObject*>( theObj );
- SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
+ // Issue 21379: References are supported at LightApp_DataObject level
+ LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
- if( study && obj )
+ if( obj && obj->isReference() )
{
- QString entry = obj->entry();
- _PTR(SObject) sobj = study->studyDS()->FindObjectID( entry.toStdString() ), ref;
-
- if( sobj && sobj->ReferencedObject( ref ) )
- {
- entry = ref->GetID().c_str();
+ QString entry = obj->refEntry();
- SUIT_DataOwnerPtrList aList;
- aList.append( new LightApp_DataOwner( entry ) );
- selectionMgr()->setSelected( aList, false );
+ SUIT_DataOwnerPtrList aList;
+ aList.append( new LightApp_DataOwner( entry ) );
+ selectionMgr()->setSelected( aList, false );
+
+ SUIT_DataBrowser* ob = objectBrowser();
- SUIT_DataBrowser* ob = objectBrowser();
-
- QModelIndexList aSelectedIndexes = ob->selectedIndexes();
- if ( !aSelectedIndexes.isEmpty() )
- ob->treeView()->scrollTo( aSelectedIndexes.first() );
- }
+ QModelIndexList aSelectedIndexes = ob->selectedIndexes();
+ if ( !aSelectedIndexes.isEmpty() )
+ ob->treeView()->scrollTo( aSelectedIndexes.first() );
}
}
void SalomeApp_Application::objectBrowserColumnsVisibility()
{
if ( objectBrowser() )
- for ( int i = SalomeApp_DataObject::EntryId; i <= SalomeApp_DataObject::RefEntryId; i++ )
+ for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
{
bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
objectBrowser()->treeView()->setColumnHidden( i, !shown );
static SALOMEDSClient_StudyManager* studyMgr();
static SALOME_NamingService* namingService();
static SALOME_LifeCycleCORBA* lcc();
- static QString defaultEngineIOR();
SUIT_ViewManager* newViewManager(const QString&);
void updateSavePointDataObjects( SalomeApp_Study* );
{
QString txt;
- // add "Value", "IOR", and "Reference Entry" columns
+ // Text for "Value" and "IOR" columns
switch ( id )
{
case ValueId:
case IORId:
txt = ior( referencedObject() );
break;
- case RefEntryId :
- if ( isReference() )
- txt = entry( referencedObject() );
- break;
default:
+ // Issue 21379: LightApp_DataObject::text() treats "Entry"
+ // and "Reference Entry" columns
txt = LightApp_DataObject::text( id );
break;
}
case Foreground:
// text color (not selected item)
if ( isReference() ) {
- if ( !(QString(referencedObject()->GetName().c_str()).isEmpty()) )
- c = QColor( 255, 0, 0 ); // valid reference (red)
- else
+ if ( QString(referencedObject()->GetName().c_str()).isEmpty() )
c = QColor( 200, 200, 200 ); // invalid reference (grayed)
}
else if ( myObject ) {
}
}
break;
+
case Highlight:
// background color for the highlighted item
if ( isReference() ) {
- if ( !(QString(referencedObject()->GetName().c_str()).isEmpty()) )
- c = QColor( 255, 0, 0 ); // valid reference (red)
- else
+ if ( QString(referencedObject()->GetName().c_str()).isEmpty() )
c = QColor( 200, 200, 200 ); // invalid reference (grayed)
}
else if ( myObject ) {
}
}
break;
- case HighlightedText:
- // text color for the highlighted item
- if ( isReference() )
- c = QColor( 255, 255, 255 ); // white
+ default:
break;
}
+
+ // Issue 21379: LightApp_DataObject::color() defines colors for valid references
if ( !c.isValid() )
c = LightApp_DataObject::color( role, id );
+
return c;
}
return myObject;
}
+/*!
+ \brief Returns the string identifier of the data objects referenced by this one.
+
+ Re-implemented from LightApp_DataObject using SALOMEDS API.
+
+ \return ID string of the referenced SObject
+*/
+QString SalomeApp_DataObject::refEntry() const
+{
+ return entry( referencedObject() );
+}
+
/*!
\brief Check if the data object is a reference.
+
+ Re-implemented from LightApp_DataObject using SALOMEDS API.
+
\return \c true if this data object actually refers to another one
*/
bool SalomeApp_DataObject::isReference() const
public:
//! Column id
enum {
- ValueId = EntryId + 1, //!< value column
- IORId, //!< IOR column
- RefEntryId //!< reference entry column
+ ValueId = RefEntryId + 1, //!< value column
+ IORId, //!< IOR column
+ LastId //!< indicates last Id value
};
public:
virtual _PTR(SObject) object() const;
- bool isReference() const;
+ virtual QString refEntry() const;
+ virtual bool isReference() const;
_PTR(SObject) referencedObject() const;
+
bool hasChildren() const;
bool expandable() const;
#include <QCoreApplication>
#include <QEvent>
+#include <QFileInfo>
#include "SALOME_Event.h"
#include "Basics_Utils.hxx"
QListIterator<CAM_DataModel*> it( list );
QStringList listOfFiles;
while ( it.hasNext() ) {
- if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() ) {
+ // Cast to LightApp class in order to give a chance
+ // to light modules to save their data
+ if ( LightApp_DataModel* aModel =
+ dynamic_cast<LightApp_DataModel*>( it.next() ) ) {
listOfFiles.clear();
aModel->saveAs( theFileName, this, listOfFiles );
if ( !listOfFiles.isEmpty() )
QListIterator<CAM_DataModel*> it( list );
QStringList listOfFiles;
while ( it.hasNext() ) {
- if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() ) {
+ // Cast to LightApp class in order to give a chance
+ // to light modules to save their data
+ if ( LightApp_DataModel* aModel =
+ dynamic_cast<LightApp_DataModel*>( it.next() ) ) {
listOfFiles.clear();
aModel->save(listOfFiles);
if ( !listOfFiles.isEmpty() )
}
}
+/*!
+ Dump study operation. Writes a Python dump file using
+ SALOMEDS services. Additionally, gives a chance to light modules
+ to participate in dump study operation.
+
+ \param theFileName - full path to the output Python file
+ \param toPublish - if true, all objects are published in a study
+ by the output script, including those not orignally present
+ in the current study.
+ \param isMultiFile - if true, each module's dump is written into
+ a separate Python file, otherwise a single output file is written
+ \param toSaveGUI - if true, the GUI state is written
+
+ \return - true if the operation succeeds, and false otherwise.
+*/
+bool SalomeApp_Study::dump( const QString& theFileName,
+ bool toPublish,
+ bool isMultiFile,
+ bool toSaveGUI )
+{
+ int savePoint;
+ _PTR(AttributeParameter) ap;
+ _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
+ _PTR(Study) aStudy = studyDS();
+
+ if( ip->isDumpPython( aStudy ) )
+ ip->setDumpPython( aStudy ); //Unset DumpPython flag.
+
+ if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
+ ip->setDumpPython( aStudy );
+ //SRN: create a temporary save point
+ savePoint = SalomeApp_VisualState(
+ dynamic_cast<SalomeApp_Application*>( application() ) ).storeState();
+ }
+
+ // Issue 21377 - Each data model is asked to dump its data not present in SALOMEDS study.
+ // This is an optional but important step, it gives a chance to light modules
+ // to dump their data as a part of common dump study operation
+ ModelList list;
+ dataModels( list );
+
+ QListIterator<CAM_DataModel*> it( list );
+ QStringList listOfFiles;
+ while ( it.hasNext() ) {
+ if ( LightApp_DataModel* aModel =
+ dynamic_cast<LightApp_DataModel*>( it.next() ) ) {
+ listOfFiles.clear();
+ if ( aModel->dumpPython( theFileName, this, isMultiFile, listOfFiles ) &&
+ !listOfFiles.isEmpty() )
+ // This call simply passes the data model's dump output to SalomeApp_Engine servant.
+ // This code is shared with persistence mechanism.
+ // NOTE: this should be revised if behavior of saveModuleData() changes!
+ saveModuleData(aModel->module()->name(), listOfFiles);
+ }
+ }
+
+ // Now dump SALOMEDS part that also involves SalomeApp_Engine in case if
+ // any light module is present in the current configuration
+ QFileInfo aFileInfo( theFileName );
+ bool res = aStudy->DumpStudy( aFileInfo.absolutePath().toStdString(),
+ aFileInfo.baseName().toStdString(),
+ toPublish,
+ isMultiFile);
+ if ( toSaveGUI )
+ removeSavePoint( savePoint ); //SRN: remove the created temporary save point.
+
+ // Issue 21377 - Clean up light module data in SalomeApp_Engine servant
+ // This code is shared with persistence mechanism.
+ // NOTE: this should be revised if behavior of saveStudyData() changes!
+ saveStudyData( theFileName );
+
+ return res;
+}
+
/*!
\return true, if study is modified in comparison with last open/save
*/
}
/*!
- Saves data from study
+ Re-implemented from LightApp_Study, actually does not save anything but
+ simply cleans up light modules' data
*/
bool SalomeApp_Study::saveStudyData( const QString& theFileName )
{
ModelList list; dataModels( list );
QListIterator<CAM_DataModel*> it( list );
std::vector<std::string> listOfFiles(0);
- while ( it.hasNext() )
- if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() )
- SetListOfFiles(aModel->module()->name().toStdString().c_str(), listOfFiles);
+ while ( it.hasNext() ){
+ LightApp_DataModel* aLModel =
+ dynamic_cast<LightApp_DataModel*>( it.next() );
+ // It is safe to call SetListOfFiles() for any kind of module
+ // because SetListOfFiles() does nothing for full modules :)
+ if ( aLModel )
+ SetListOfFiles(aLModel->module()->name().toStdString().c_str(), listOfFiles);
+ }
return true;
}
_PTR(Study) aStudy = studyDS();
if (!aStudy)
return;
- _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name().toStdString());
+
+ std::string aCompDataType = dm->module()->name().toStdString();
+
+ _PTR(SComponent) aComp = aStudy->FindComponent(aCompDataType);
if (!aComp) {
// Create SComponent
_PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
- aComp = aBuilder->NewComponent(dm->module()->name().toStdString());
+ aComp = aBuilder->NewComponent(aCompDataType);
aBuilder->SetName(aComp, dm->module()->moduleName().toStdString());
QString anIconName = dm->module()->iconName();
if (!anIconName.isEmpty()) {
if (anAttr)
anAttr->SetPixMap(anIconName.toStdString());
}
+
// Set default engine IOR
- aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().toStdString());
+ // Issue 21377 - using separate engine for each type of light module
+ std::string anEngineIOR = SalomeApp_Engine_i::EngineIORForComponent( aCompDataType.c_str(),
+ true );
+ aBuilder->DefineComponentInstance(aComp, anEngineIOR);
//SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true );
SalomeApp_DataModel::synchronize( aComp, this );
}
QString anEngine;
// 1. aModule == 0 means that this is a light module (no CORBA enigine)
if (!aModule) {
- anEngine = SalomeApp_Application::defaultEngineIOR();
- aSComp = aStudy->FindComponent(dm->module()->name().toStdString());
+ // Issue 21377 - using separate engine for each type of light module
+ std::string aCompDataType = dm->module()->name().toStdString();
+ anEngine = SalomeApp_Engine_i::EngineIORForComponent( aCompDataType.c_str(), true ).c_str();
+ aSComp = aStudy->FindComponent( aCompDataType );
}
else {
SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
}
/*!
+ Note that this method does not create or activate SalomeApp_Engine_i instance,
+ therefore it can be called safely for any kind of module, but for full
+ modules it returns an empty list.
\return list of files used by module: to be used by CORBAless modules
\param theModuleName - name of module
*/
std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName ) const
{
- SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
+ // Issue 21377 - using separate engine for each type of light module
+ SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance( theModuleName, false );
if (aDefaultEngine)
- return aDefaultEngine->GetListOfFiles(id(), theModuleName);
+ return aDefaultEngine->GetListOfFiles(id());
std::vector<std::string> aListOfFiles;
return aListOfFiles;
}
/*!
- Sets list of files used by module: to be used by CORBAless modules
+ Sets list of files used by module: to be used by CORBAless modules.
+ Note that this method does not create or activate SalomeApp_Engine_i instance,
+ therefore it can be called safely for any kind of module, but for full
+ modules it simply does nothing.
\param theModuleName - name of module
\param theListOfFiles - list of files
*/
void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
const std::vector<std::string> theListOfFiles )
{
- SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
+ // Issue 21377 - using separate engine for each type of light module
+ SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance( theModuleName, false );
if (aDefaultEngine)
- aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName);
+ aDefaultEngine->SetListOfFiles(theListOfFiles, id());
}
/*!
virtual void closeDocument(bool permanently = true);
+ virtual bool dump( const QString&, bool, bool, bool );
+
virtual bool isSaved() const;
virtual bool isModified() const;
virtual void Modified();
//
#include "SalomeApp_Engine_i.hxx"
-#include "SALOMEDS_Tool.hxx"
+#include <SALOME_NamingService.hxx>
+#include <SALOMEDS_Tool.hxx>
+#include <Utils_ORB_INIT.hxx>
+#include <Utils_SINGLETON.hxx>
+#include <Utils_SALOME_Exception.hxx>
+#include <utilities.h>
+
+#include <QApplication>
+#include <QDir>
+#include <QFile>
#include <iostream>
using namespace std;
-SalomeApp_Engine_i* SalomeApp_Engine_i::myInstance = NULL;
-
/*!
Constructor
*/
-SalomeApp_Engine_i::SalomeApp_Engine_i()
+SalomeApp_Engine_i::SalomeApp_Engine_i( const char* theComponentName )
{
- myInstance = this;
+ myComponentName = theComponentName;
+ MESSAGE("SalomeApp_Engine_i::SalomeApp_Engine_i(): myComponentName = " <<
+ myComponentName << ", this = " << this);
}
/*!
*/
SalomeApp_Engine_i::~SalomeApp_Engine_i()
{
+ MESSAGE("SalomeApp_Engine_i::~SalomeApp_Engine_i(): myComponentName = " <<
+ myComponentName << ", this = " << this);
}
SALOMEDS::TMPFile* SalomeApp_Engine_i::Save (SALOMEDS::SComponent_ptr theComponent,
{
SALOMEDS::TMPFile_var aStreamFile = new SALOMEDS::TMPFile;
- cout << "SalomeApp_Engine_i::Save() isMultiFile = " << isMultiFile << endl;
if (CORBA::is_nil(theComponent) || CORBA::is_nil(theComponent->GetStudy()))
return aStreamFile._retn();
const int studyId = theComponent->GetStudy()->StudyId();
- cout << "SalomeApp_Engine_i::Save() - studyId = " << studyId << endl;
// Get a temporary directory to store a file
//std::string aTmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
if (myMap.count(studyId)) {
- cout << "SalomeApp_Engine_i::Save() - myMap.count(studyId)" << endl;
- MapOfListOfFiles mapOfListOfFiles = myMap[studyId];
std::string componentName (theComponent->ComponentDataType());
- cout << "SalomeApp_Engine_i::Save() - componentName = " << componentName << endl;
- ListOfFiles listOfFiles = mapOfListOfFiles[componentName];
+
+ // Error somewhere outside - Save() called with
+ // wrong SComponent instance
+ if ( myComponentName != componentName )
+ return aStreamFile._retn();
+
+ const ListOfFiles& listOfFiles = myMap[studyId];
// listOfFiles must contain temporary directory name in its first item
// and names of files (relatively the temporary directory) in the others
if (n > 0) { // there are some files, containing persistent data of the component
std::string aTmpDir = listOfFiles[0];
- cout << "SalomeApp_Engine_i::Save() - aTmpDir = " << aTmpDir << endl;
// Create a list to store names of created files
SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
if (CORBA::is_nil(theComponent) || CORBA::is_nil(theComponent->GetStudy()))
return false;
+ // Error somewhere outside - Load() called with
+ // wrong SComponent instance
+ std::string componentName (theComponent->ComponentDataType());
+ if ( myComponentName != componentName )
+ return false;
+
const int studyId = theComponent->GetStudy()->StudyId();
// Create a temporary directory for the component's data files
for (int i = 1; i < n; i++)
listOfFiles[i] = std::string(aSeq[i - 1]);
- //MapOfListOfFiles mapOfListOfFiles;
- //if (myMap.count(studyId))
- // mapOfListOfFiles = myMap[studyId];
- //std::string componentName (theComponent->ComponentDataType());
- //mapOfListOfFiles[componentName] = listOfFiles;
- //myMap[studyId] = mapOfListOfFiles;
-
- SetListOfFiles(listOfFiles, studyId, theComponent->ComponentDataType());
+ SetListOfFiles(listOfFiles, studyId);
return true;
}
-SalomeApp_Engine_i::ListOfFiles SalomeApp_Engine_i::GetListOfFiles (const int theStudyId,
- const char* theComponentName)
+SalomeApp_Engine_i::ListOfFiles SalomeApp_Engine_i::GetListOfFiles (const int theStudyId)
{
ListOfFiles aListOfFiles;
- if (myMap.count(theStudyId))
+ if (myMap.find(theStudyId) != myMap.end())
{
- MapOfListOfFiles mapOfListOfFiles = myMap[theStudyId];
- std::string componentName (theComponentName);
- if (mapOfListOfFiles.count(componentName))
- aListOfFiles = mapOfListOfFiles[componentName];
+ aListOfFiles = myMap[theStudyId];
}
return aListOfFiles;
}
-void SalomeApp_Engine_i::SetListOfFiles (const ListOfFiles theListOfFiles,
- const int theStudyId,
- const char* theComponentName)
+void SalomeApp_Engine_i::SetListOfFiles (const ListOfFiles& theListOfFiles,
+ const int theStudyId)
{
- //if (!myMap.count(theStudyId)) {
- // MapOfListOfFiles mapOfListOfFiles;
- // myMap[theStudyId] = mapOfListOfFiles;
- //}
-
- MapOfListOfFiles& mapOfListOfFiles = myMap[theStudyId];
- std::string componentName (theComponentName);
- mapOfListOfFiles[componentName] = theListOfFiles;
+ myMap[theStudyId] = theListOfFiles;
+}
+
+/*!
+ * DumpPython implementation for light modules
+ */
+Engines::TMPFile* SalomeApp_Engine_i::DumpPython(CORBA::Object_ptr theStudy,
+ CORBA::Boolean isPublished,
+ CORBA::Boolean isMultiFile,
+ CORBA::Boolean& isValidScript)
+{
+ MESSAGE("SalomeApp_Engine_i::DumpPython(): myComponentName = "<<
+ myComponentName << ", this = " << this);
+
+ // Temporary solution: returning a non-empty sequence
+ // even if there's nothing to dump, to avoid crashes in SALOMEDS
+ // TODO: Improve SALOMEDSImpl_Study::DumpStudy() by skipping the components
+ // with isValidScript == false, and initialize isValidScript by false below.
+ Engines::TMPFile_var aStreamFile = new Engines::TMPFile(1);
+ aStreamFile->length( 1 );
+ aStreamFile[0] = '\0';
+ isValidScript = true;
+
+ if (CORBA::is_nil(theStudy))
+ return aStreamFile._retn();
+
+ SALOMEDS::Study_var studyDS = SALOMEDS::Study::_narrow( theStudy );
+ const int studyId = studyDS->StudyId();
+
+ if (!myMap.count(studyId))
+ return aStreamFile._retn();
+
+ ListOfFiles listOfFiles = myMap[studyId];
+
+ // listOfFiles must contain temporary directory name in its first item
+ // and names of files (relatively the temporary directory) in the others
+ if ( listOfFiles.size() < 2 )
+ return aStreamFile._retn();
+
+ // there are some files, containing persistent data of the component
+ QString aTmpPath( listOfFiles.front().c_str() );
+ QDir aTmpDir( aTmpPath );
+ if ( !aTmpDir.exists() )
+ return aStreamFile._retn();
+
+ // Calculate file sizes
+ QStringList aFilePaths;
+ QList<qint64> aFileSizes;
+ qint64 aBuffSize = 0;
+ ListOfFiles::const_iterator aFIt = listOfFiles.begin();
+ ListOfFiles::const_iterator aFEnd = listOfFiles.end();
+ aFIt++;
+ for (; aFIt != aFEnd; aFIt++){
+ QString aFileName( (*aFIt).c_str() );
+ if ( !aTmpDir.exists( aFileName ) ){
+ continue;
+ }
+
+ QFile aFile( aTmpDir.filePath( aFileName ) );
+ if ( !aFile.open( QIODevice::ReadOnly ) ){
+ continue;
+ }
+
+ aFilePaths.push_back( aTmpDir.filePath( aFileName ) );
+ aFileSizes.push_back( aFile.size() );
+ aBuffSize += aFileSizes.back();
+
+ aFile.close();
+ }
+
+ if ( !aFilePaths.size() || !aBuffSize )
+ return aStreamFile._retn();
+
+ char* aBuffer = new char[aBuffSize + 1];
+ if ( !aBuffer )
+ return aStreamFile._retn();
+
+ // Convert the file(s) to the byte stream, multiple files are simply
+ // concatenated
+ // TODO: imporve multi-script support if necessary...
+ qint64 aCurrPos = 0;
+ QStringList::const_iterator aFileIt = aFilePaths.begin();
+ QStringList::const_iterator aFileEnd = aFilePaths.end();
+ QList<qint64>::const_iterator aSIt = aFileSizes.begin();
+ for ( ; aFileIt != aFileEnd; aFileIt++, aSIt++ ){
+ QFile aFile( aTmpDir.filePath( *aFileIt ) );
+ if ( !aFile.open( QIODevice::ReadOnly ) ){
+ continue;
+ }
+
+ // Incorrect size of file
+ // Do not remove the bad file to have some diagnostic means
+ if ( aFile.read( aBuffer + aCurrPos, *aSIt ) != *aSIt ){
+ aFile.close();
+ return aStreamFile._retn();
+ }
+
+ aCurrPos += (*aSIt);
+ aFile.remove();
+ }
+
+ // Here we should end up with empty aTmpDir
+ // TODO: Handle QDir::rmdir() error status somehow...
+ aTmpDir.rmdir( aTmpPath );
+
+ aBuffer[aBuffSize] = '\0';
+ CORBA::Octet* anOctetBuf = (CORBA::Octet*)aBuffer;
+ aStreamFile = new Engines::TMPFile(aBuffSize + 1, aBuffSize + 1, anOctetBuf, 1);
+
+ return aStreamFile._retn();
}
/*!
- \return shared instance of engine
+ \return Component data type string for this instance of the engine
*/
-SalomeApp_Engine_i* SalomeApp_Engine_i::GetInstance()
+char* SalomeApp_Engine_i::ComponentDataType()
{
- return myInstance;
+ return const_cast<char*>( myComponentName.c_str() );
}
+
+/*!
+ \return
+*/
+CORBA::ORB_var SalomeApp_Engine_i::orb()
+{
+ ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
+ // TODO: using QApplication here looks ugly, think how to
+ // obtain the ORB reference in a nicer way...
+ static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
+ return _orb;
+}
+
+/*!
+ \return
+*/
+PortableServer::POA_var SalomeApp_Engine_i::poa()
+{
+ static PortableServer::POA_var _poa;
+ if ( CORBA::is_nil( _poa ) ){
+ CORBA::Object_var obj = orb()->resolve_initial_references( "RootPOA" );
+ _poa = PortableServer::POA::_narrow( obj );
+ }
+ return _poa;
+}
+
+/*!
+ \return
+*/
+SALOME_NamingService* SalomeApp_Engine_i::namingService()
+{
+ static SALOME_NamingService _ns(orb());
+ return &_ns;
+}
+
+/*!
+ Internal method, creates a CORBA engine for a light SALOME module
+ with the given "component data type" string,
+ activates it and registers in SALOME naming service with
+ /SalomeAppEngine/comp_data_type path. If the engine is already in the
+ naming service, simply returns and object reference to it.
+ \param theComponentName - synthetic "component data type" used to identify a given light module
+ \return Object reference to the CORBA engine
+*/
+CORBA::Object_ptr SalomeApp_Engine_i::engineForComponent( const char* theComponentName,
+ bool toCreate )
+{
+ CORBA::Object_var anEngine;
+ if ( !theComponentName || !strlen( theComponentName ) )
+ return anEngine._retn();
+
+ std::string aPath( "/SalomeAppEngine/" );
+ aPath += theComponentName;
+ anEngine = namingService()->Resolve( aPath.c_str() );
+
+ // Activating a new instance of the servant
+ if ( toCreate && CORBA::is_nil( anEngine ) ){
+ try {
+ SalomeApp_Engine_i* aServant = new SalomeApp_Engine_i( theComponentName );
+ PortableServer::ObjectId_var id = poa()->activate_object( aServant );
+ anEngine = aServant->_this();
+ aServant->_remove_ref();
+ namingService()->Register( anEngine.in(), aPath.c_str() );
+ }
+ catch (CORBA::SystemException&) {
+ INFOS("Caught CORBA::SystemException.");
+ }
+ catch (CORBA::Exception&) {
+ INFOS("Caught CORBA::Exception.");
+ }
+ catch (...) {
+ INFOS("Caught unknown exception.");
+ }
+ }
+
+ return anEngine._retn();
+}
+
+/*!
+ \param theComponentName - synthetic "component data type" used to identify a given light module
+ \return IOR string for the CORBA engine for a light SALOME module
+ with the given "component data type" string
+ \sa GetInstance( const char* theComponentName )
+*/
+std::string SalomeApp_Engine_i::EngineIORForComponent( const char* theComponentName,
+ bool toCreate )
+{
+ std::string anIOR( "" );
+ CORBA::Object_var anEngine = engineForComponent( theComponentName, toCreate );
+ if ( !CORBA::is_nil( anEngine ) )
+ {
+ CORBA::String_var objStr = orb()->object_to_string( anEngine.in() );
+ anIOR = std::string( objStr.in() );
+ }
+ return anIOR;
+}
+
+/*!
+ \param theComponentName - synthetic "component data type" used to identify a given light module
+ \return A pointer to corresponding C++ engine instance, null means some internal problems.
+ \sa EngineIORForComponent( const char* theComponentName )
+*/
+SalomeApp_Engine_i* SalomeApp_Engine_i::GetInstance( const char* theComponentName,
+ bool toCreate )
+{
+ SalomeApp_Engine_i* aServant = 0;
+ CORBA::Object_var anEngine = engineForComponent( theComponentName, toCreate );
+ if ( !CORBA::is_nil( anEngine ) )
+ {
+ PortableServer::Servant aServantBase = poa()->reference_to_servant( anEngine.in() );
+ aServant = dynamic_cast<SalomeApp_Engine_i*>( aServantBase );
+ }
+ MESSAGE("SalomeApp_Engine_i::GetInstance(): theComponentName = " <<
+ theComponentName << ", aServant = " << aServant);
+ return aServant;
+}
+
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SalomeApp_Engine)
+class SALOME_NamingService;
+
class SESSION_EXPORT SalomeApp_Engine_i: public POA_SalomeApp::Engine,
- public Engines_Component_i
+ public Engines_Component_i
{
public:
- SalomeApp_Engine_i();
+ SalomeApp_Engine_i( const char* theComponentName );
~SalomeApp_Engine_i();
SALOMEDS::TMPFile* Save( SALOMEDS::SComponent_ptr theComponent,
const char* theURL,
bool isMultiFile );
+ virtual Engines::TMPFile* DumpPython(CORBA::Object_ptr theStudy,
+ CORBA::Boolean isPublished,
+ CORBA::Boolean isMultiFile,
+ CORBA::Boolean& isValidScript);
+
public:
typedef std::vector<std::string> ListOfFiles;
- ListOfFiles GetListOfFiles (const int theStudyId,
- const char* theComponentName);
-
- void SetListOfFiles (const ListOfFiles theListOfFiles,
- const int theStudyId,
- const char* theComponentName);
+ ListOfFiles GetListOfFiles (const int theStudyId);
+ void SetListOfFiles (const ListOfFiles& theListOfFiles,
+ const int theStudyId);
- static SalomeApp_Engine_i* GetInstance();
+ static std::string EngineIORForComponent( const char* theComponentName,
+ bool toCreate );
+ static SalomeApp_Engine_i* GetInstance ( const char* theComponentName,
+ bool toCreate );
public:
// methods from SALOMEDS::Driver without implementation. Must be redefined because
SALOMEDS::TMPFile* SaveASCII( SALOMEDS::SComponent_ptr, const char*, bool ) {return 0;}
CORBA::Boolean LoadASCII( SALOMEDS::SComponent_ptr, const SALOMEDS::TMPFile&, const char*, bool ) {return 0;}
void Close( SALOMEDS::SComponent_ptr ) {}
- char* ComponentDataType() {return 0;}
+ char* ComponentDataType();
char* IORToLocalPersistentID( SALOMEDS::SObject_ptr, const char*, CORBA::Boolean, CORBA::Boolean ) {return 0;}
char* LocalPersistentIDToIOR( SALOMEDS::SObject_ptr, const char*, CORBA::Boolean, CORBA::Boolean ) {return 0;}
bool CanPublishInStudy( CORBA::Object_ptr ) {return 0;}
SALOMEDS::SObject_ptr PasteInto( const SALOMEDS::TMPFile&, CORBA::Long, SALOMEDS::SObject_ptr ) {return 0;}
private:
- typedef std::map<std::string, ListOfFiles> MapOfListOfFiles;
- typedef std::map<int, MapOfListOfFiles> MapOfMapOfListOfFiles;
- MapOfMapOfListOfFiles myMap;
+ static CORBA::ORB_var orb();
+ static PortableServer::POA_var poa();
+ static SALOME_NamingService* namingService();
+ static CORBA::Object_ptr engineForComponent( const char* theComponentName,
+ bool toCreate );
+
+private:
+ typedef std::map<int, ListOfFiles> MapOfListOfFiles;
+ MapOfListOfFiles myMap;
- static SalomeApp_Engine_i* myInstance;
+ std::string myComponentName;
};
#endif
}
case 1: // looking for server type
{
+ // Temporary solution
+ // Issue 21337 - no more SalomeApp_Engine_i activation here
+ // TODO: To be removed as soon as any trace of SalomeAppEngine
+ // has been eliminated from KERNEL scripts
+ if (strcmp(_argv[iarg], "SalomeAppEngine")==0){
+ argState = 0;
+ iarg += 2; // skipping "()"
+ break;
+ }
+ // Temporary solution
+
for (int i=0; i<Session_ServerThread::NB_SRV_TYP; i++)
if (strcmp(_argv[iarg],Session_ServerThread::_serverTypes[i])==0)
{
#include <RegistryService.hxx>
#include "Session_Session_i.hxx"
-#include "SalomeApp_Engine_i.hxx"
#include <Utils_ORB_INIT.hxx>
#include <Utils_SINGLETON.hxx>
using namespace std;
-const int Session_ServerThread::NB_SRV_TYP = 7;
+const int Session_ServerThread::NB_SRV_TYP = 6;
const char* Session_ServerThread::_serverTypes[NB_SRV_TYP] = {"Container",
"ModuleCatalog",
"Registry",
"SALOMEDS",
"Session",
- "SalomeAppEngine",
"ContainerManager"};
/*!
ActivateSession(_argc, _argv);
break;
}
- case 5: // SalomeApp_Engine
- {
- NamingService_WaitForServerReadiness(_NS,"/myStudyManager");
- ActivateEngine(_argc, _argv);
- break;
- }
- case 6: // Container Manager
+ case 5: // Container Manager
{
NamingService_WaitForServerReadiness(_NS,"");
ActivateContainerManager(_argc, _argv);
}
}
-void Session_ServerThread::ActivateEngine(int /*argc*/, char ** /*argv*/)
-{
- try {
- MESSAGE("SalomeApp_Engine thread started");
- SalomeApp_Engine_i* anEngine = new SalomeApp_Engine_i();
- PortableServer::ObjectId_var id =_root_poa->activate_object( anEngine );
- MESSAGE("poa->activate_object( SalomeApp_Engine )");
-
- CORBA::Object_var obj = anEngine->_this();
- anEngine->_remove_ref();
- _NS->Register( obj ,"/SalomeAppEngine");
- }
- catch (CORBA::SystemException&) {
- INFOS("Caught CORBA::SystemException.");
- }
- catch (CORBA::Exception&) {
- INFOS("Caught CORBA::Exception.");
- }
- catch (...) {
- INFOS("Caught unknown exception.");
- }
-}
-
void Session_ServerThread::ActivateSession(int argc,
char ** argv)
{