export CSF_XSMessage=${CAS_ROOT_DIR}/src/XSMessage
# Variable for Font :
export CSF_MDTVFontDirectory=${CAS_ROOT_DIR}/src/FontMFT
-export CSF_MDTVTexturesDirectory=${CAS_ROOT_DIR}/src/Textures
+export CSF_MDTVTexturesDirectory=${CAS_ROOT_DIR}/src/Textures
+# Defaults
+export CSF_PluginDefaults=${CAS_ROOT_DIR}/src/StdResource
+export CSF_StandardDefaults=${CAS_ROOT_DIR}/src/StdResource
# Activation of OCCT Kernel multithreading :
export MMGT_REENTRANT=1
# this variable only needed for DRAWEXE
myGroupId = "";
myWorkbenchId = "";
+ myPluginLibrary = "";
+
+ myInternal = false;
+ myUseInput = false;
+ myNestedFeatures = "";
}
const std::string& Config_FeatureMessage::icon() const
return myUseInput;
}
+bool Config_FeatureMessage::isInternal() const
+{
+ return myInternal;
+}
+
void Config_FeatureMessage::setUseInput(bool isUseInput)
{
myUseInput = isUseInput;
}
+void Config_FeatureMessage::setInternal(bool isInternal)
+{
+ myInternal = isInternal;
+}
+
const std::string& Config_FeatureMessage::nestedFeatures() const
{
return myNestedFeatures;
std::string myPluginLibrary; //Name of feature's library\r
\r
bool myUseInput; //Action is being checked until user commit the operation\r
+ bool myInternal; //Internal feature without GUI representation\r
std::string myNestedFeatures;\r
\r
public:\r
CONFIG_EXPORT const std::string& pluginLibrary() const;\r
CONFIG_EXPORT const std::string& nestedFeatures() const;\r
CONFIG_EXPORT bool isUseInput() const;\r
+ CONFIG_EXPORT bool isInternal() const;\r
\r
CONFIG_EXPORT void setIcon(const std::string& icon);\r
CONFIG_EXPORT void setId(const std::string& id);\r
CONFIG_EXPORT void setPluginLibrary(const std::string& thePluginLibrary);\r
CONFIG_EXPORT void setNestedFeatures(const std::string& theNestedFeatures);\r
CONFIG_EXPORT void setUseInput(bool isUseInput);\r
+ CONFIG_EXPORT void setInternal(bool isInternal);\r
};\r
\r
#endif // CONFIG_MESSAGE_H\r
#include <libxml/xmlstring.h>
#include <string>
+#include <algorithm>
#ifdef _DEBUG
#include <iostream>
void Config_FeatureReader::fillFeature(xmlNodePtr theRoot, Config_FeatureMessage& outFtMessage)
{
outFtMessage.setId(getProperty(theRoot, _ID));
+ outFtMessage.setPluginLibrary(myLibraryName);
+ outFtMessage.setNestedFeatures(getProperty(theRoot, FEATURE_NESTED));
+ bool isFtInternal = isInternalFeature(theRoot);
+ outFtMessage.setInternal(isFtInternal);
+ if(isFtInternal) {
+ //Internal feature has no visual representation.
+ return;
+ }
outFtMessage.setText(getProperty(theRoot, FEATURE_TEXT));
outFtMessage.setTooltip(getProperty(theRoot, FEATURE_TOOLTIP));
outFtMessage.setIcon(getProperty(theRoot, FEATURE_ICON));
outFtMessage.setKeysequence(getProperty(theRoot, FEATURE_KEYSEQUENCE));
outFtMessage.setGroupId(myLastGroup);
outFtMessage.setWorkbenchId(myLastWorkbench);
- outFtMessage.setPluginLibrary(myLibraryName);
- outFtMessage.setNestedFeatures(getProperty(theRoot, FEATURE_NESTED));
+}
+
+bool Config_FeatureReader::isInternalFeature(xmlNodePtr theRoot)
+{
+ std::string prop = getProperty(theRoot, FEATURE_INTERNAL);
+ std::transform(prop.begin(), prop.end(), prop.begin(), ::tolower);
+ if(prop.empty() || prop == "false" || prop == "0") {
+ return false;
+ }
+ return true;
}
bool processChildren(xmlNodePtr aNode);
void fillFeature(xmlNodePtr theRoot, Config_FeatureMessage& outFeatureMessage);
+ bool isInternalFeature(xmlNodePtr theRoot);
private:
std::string myLastWorkbench;
//const static char* WORKBENCH_ID = "id";
//const static char* GROUP_ID = "id";
//const static char* FEATURE_ID = "id";
-const static char* FEATURE_TEXT = "text";
+const static char* FEATURE_TEXT = "title";
const static char* FEATURE_TOOLTIP = "tooltip";
const static char* FEATURE_ICON = "icon";
const static char* FEATURE_KEYSEQUENCE = "keysequence";
const static char* FEATURE_NESTED = "nested";
+const static char* FEATURE_INTERNAL = "internal";
const static char* SOURCE_FILE = "path";
void Config_ModuleReader::loadLibrary(const std::string theLibName)
{
-#ifdef _DEBUG
- std::cout << "Config_ModuleReader::loading library... " << theLibName.c_str() << std::endl;
-#endif
std::string aFileName = library(theLibName);
if (aFileName.empty())
return;
<plugin>
<workbench id="Construction">
<group id="Basic">
- <feature id="Point" text="Point" tooltip="Create a new point" icon=":icons/point.png">
+ <feature id="Point" title="Point" tooltip="Create a new point" icon=":icons/point.png">
<source path="point_widget.xml"/>
</feature>
- <feature id="Axis" text="Axis" tooltip="Create a new axis" icon=":icons/axis.png" keysequence=""/>
- <feature id="Plane" text="Plane" tooltip="Create a new plane" icon=":icons/plane.png" keysequence=""/>
+ <feature id="Axis" title="Axis" tooltip="Create a new axis" icon=":icons/axis.png" keysequence="" internal="true"/>
+ <feature id="Plane" title="Plane" tooltip="Create a new plane" icon=":icons/plane.png" keysequence="" internal="true"/>
</group>
</workbench>
</plugin>
SET(PROJECT_HEADERS
Events.h
Events_Message.h
+ Events_MessageGroup.h
Events_Listener.h
Events_Loop.h
Events_Error.h
// Author: Mikhail PONIKAROV
#include <Events_Loop.h>
+#include <Events_MessageGroup.h>
#include <string>
#include <cstring>
return Events_ID(aResult);
}
-void Events_Loop::send(Events_Message& theMessage)
+void Events_Loop::send(Events_Message& theMessage, bool isGroup)
{
- // TO DO: make it in thread and wit husage of semaphores
+ // if it is grouped message, just accumulate it
+ if (isGroup) {
+ Events_MessageGroup* aGroup = dynamic_cast<Events_MessageGroup*>(&theMessage);
+ if (aGroup) {
+ std::map<char*, Events_MessageGroup*>::iterator aMyGroup =
+ myGroups.find(aGroup->eventID().eventText());
+ if (aMyGroup == myGroups.end()) { // create a new group of messages for accumulation
+ myGroups[aGroup->eventID().eventText()] = aGroup->newEmpty();
+ aMyGroup = myGroups.find(aGroup->eventID().eventText());
+ }
+ aMyGroup->second->Join(*aGroup);
+ return;
+ }
+ }
+
+ // TO DO: make it in thread and with usage of semaphores
map<char*, map<void*, list<Events_Listener*> > >::iterator aFindID = myListeners.find(
theMessage.eventID().eventText());
aListeners.push_back(theListener);
}
+
+void Events_Loop::flush(const Events_ID& theID)
+{
+ std::map<char*, Events_MessageGroup*>::iterator aMyGroup =
+ myGroups.find(theID.eventText());
+ if (aMyGroup != myGroups.end()) { // really sends
+ Events_MessageGroup* aGroup = aMyGroup->second;
+ myGroups.erase(aMyGroup);
+ send(*aGroup, false);
+ delete aGroup;
+ }
+}
#include <map>
#include <list>
+class Events_MessageGroup;
+
/**\class Events_Lopp
* \ingroup EventsLoop
* \brief Base class that manages the receiving and sending of all
* control back immideately.
*/
class Events_Loop {
+ /// map from event ID to sender pointer to listeners that must be called for this
std::map<char*, std::map<void*, std::list<Events_Listener*> > >
- myListeners; ///< map from event ID to sender pointer to listeners that must be called for this
+ myListeners;
+
+ /// map from event ID to groupped messages (accumulated on flush)
+ std::map<char*, Events_MessageGroup*> myGroups;
//! The empty constructor, will be called at startup of the application, only once
Events_Loop() {};
EVENTS_EXPORT static Events_ID eventByName(const char* theName);
//! Allows to send an event
- EVENTS_EXPORT void send(Events_Message& theMessage);
+ //! \param isGroup is true for grouping messages if possible
+ EVENTS_EXPORT void send(Events_Message& theMessage, bool isGroup = true);
//! Registers (or adds if such listener is already registered) a listener
//! that will be called on the event and from the defined sender
EVENTS_EXPORT void registerListener(Events_Listener* theListener, const Events_ID theID,
void* theSender = 0);
+
+ //! Initializes sending of a group-message by the given ID
+ EVENTS_EXPORT void flush(const Events_ID& theID);
};
#endif
--- /dev/null
+// File: Events_MessageGroup.hxx
+// Created: Thu Mar 13 2014
+// Author: Mikhail PONIKAROV
+
+#ifndef Events_MessageGroup_HeaderFile
+#define Events_MessageGroup_HeaderFile
+
+#include <Events_Message.h>
+
+/**\class Events_Message
+ * \ingroup EventsLoop
+ * \brief Message that allows to group messages and send them later as a group of messages.
+ *
+ * Loop detects such messages and accumulates them without sending. On "flush" loop sends it
+ * as a group-message.
+ */
+class EVENTS_EXPORT Events_MessageGroup : public Events_Message {
+
+public:
+
+ //! Creates the message
+ Events_MessageGroup(const Events_ID theID, const void* theSender = 0)
+ : Events_Message(theID, theSender) {}
+ //! do nothing in the destructor yet
+ virtual ~Events_MessageGroup() {}
+
+ //! Creates a new empty group (to store it in the loop before flush)
+ virtual Events_MessageGroup* newEmpty() = 0;
+ //! Allows to join the given message with the current one
+ virtual void Join(Events_MessageGroup& theJoined) = 0;
+};
+
+#endif
#include <GeomData_Point2D.h>
#include <GeomData_Dir.h>
#include <TDataStd_Name.hxx>
+#include "Model_Events.h"
+#include <Events_Loop.h>
using namespace std;
void Model_Data::setName(string theName)
{
TDataStd_Name::Set(myLab, theName.c_str());
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
+ Model_FeatureUpdatedMessage aMsg(myFeature, anEvent);
+ Events_Loop::loop()->send(aMsg, false);
}
void Model_Data::addAttribute(string theID, string theAttrType)
void Model_Document::close()
{
+ boost::shared_ptr<ModelAPI_PluginManager> aPM = Model_PluginManager::get();
+ if (this != aPM->rootDocument().get() &&
+ this == aPM->currentDocument().get()) {
+ aPM->setCurrentDocument(aPM->rootDocument());
+ }
// close all subs
set<string>::iterator aSubIter = mySubs.begin();
for(; aSubIter != mySubs.end(); aSubIter++)
void Model_Document::startOperation()
{
- // check is it nested or not
- if (myDoc->HasOpenCommand()) {
- myNestedStart = myTransactionsAfterSave;
+ if (myDoc->HasOpenCommand()) { // start of nested command
+ if (myNestedNum == -1) {
+ myNestedNum = 0;
+ myDoc->InitDeltaCompaction();
+ }
+ myDoc->NewCommand();
+ } else { // start of simple command
+ myDoc->NewCommand();
}
- // new command for this
- myDoc->NewCommand();
// new command for all subs
set<string>::iterator aSubIter = mySubs.begin();
for(; aSubIter != mySubs.end(); aSubIter++)
void Model_Document::finishOperation()
{
- if (myNestedStart > myTransactionsAfterSave) // this nested transaction is owervritten
- myNestedStart = 0;
- // returns false if delta is empty and no transaction was made
- myIsEmptyTr[myTransactionsAfterSave] = !myDoc->CommitCommand();
- myTransactionsAfterSave++;
+ // just to be sure that everybody knows that changes were performed
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_CREATED));
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_DELETED));
+
+ if (myNestedNum != -1) // this nested transaction is owervritten
+ myNestedNum++;
+ if (!myDoc->HasOpenCommand()) {
+ if (myNestedNum != -1) {
+ myNestedNum -= 2; // one is just incremented before, one is left (and not empty!)
+ while(myNestedNum != -1) {
+ myIsEmptyTr.erase(myTransactionsAfterSave);
+ myTransactionsAfterSave--;
+ myNestedNum--;
+ }
+ myIsEmptyTr[myTransactionsAfterSave] = false;
+ myTransactionsAfterSave++;
+ myDoc->PerformDeltaCompaction();
+ }
+ } else {
+ // returns false if delta is empty and no transaction was made
+ myIsEmptyTr[myTransactionsAfterSave] = !myDoc->CommitCommand() && (myNestedNum == -1);
+ myTransactionsAfterSave++;
+ }
+
// finish for all subs
set<string>::iterator aSubIter = mySubs.begin();
for(; aSubIter != mySubs.end(); aSubIter++)
void Model_Document::abortOperation()
{
+ if (myNestedNum == 0)
+ myNestedNum = -1;
myDoc->AbortCommand();
synchronizeFeatures();
// abort for all subs
bool Model_Document::isOperation()
{
// operation is opened for all documents: no need to check subs
- return myDoc->HasOpenCommand() == Standard_True ;
+ return myDoc->HasOpenCommand() == Standard_True;
}
bool Model_Document::isModified()
bool Model_Document::canUndo()
{
- if (myDoc->GetAvailableUndos() > 0 && myNestedStart != myTransactionsAfterSave)
+ if (myDoc->GetAvailableUndos() > 0 && myNestedNum != 0 && myTransactionsAfterSave != 0 /* for omitting the first useless transaction */)
return true;
// check other subs contains operation that can be undoed
set<string>::iterator aSubIter = mySubs.begin();
void Model_Document::undo()
{
myTransactionsAfterSave--;
+ if (myNestedNum > 0) myNestedNum--;
if (!myIsEmptyTr[myTransactionsAfterSave])
myDoc->Undo();
synchronizeFeatures();
void Model_Document::redo()
{
+ if (myNestedNum != -1) myNestedNum++;
if (!myIsEmptyTr[myTransactionsAfterSave])
myDoc->Redo();
myTransactionsAfterSave++;
Handle(TDataStd_ReferenceArray) aRefs;
if (theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
if (aRefs->Length() == 1) { // just erase an array
- if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0)
+ if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0) {
theArrayLab.ForgetAttribute(TDataStd_ReferenceArray::GetID());
+ }
aResult = 0;
} else { // reduce the array
Handle(TDataStd_HLabelArray1) aNewArray =
aNewArray->SetValue(aCount, aRefs->Value(a));
}
}
- aRefs->SetInternalArray(aNewArray);
+ aRefs->SetInternalArray(aNewArray);
}
}
return aResult;
{
myDoc->SetUndoLimit(UNDO_LIMIT);
myTransactionsAfterSave = 0;
- myNestedStart = 0;
- myDoc->SetNestedTransactionMode();
+ myNestedNum = -1;
+ //myDoc->SetNestedTransactionMode();
// to have something in the document and avoid empty doc open/save problem
+ // in transaction for nesting correct working
+ myDoc->NewCommand();
TDataStd_Integer::Set(myDoc->Main().Father(), 0);
+ myDoc->CommitCommand();
}
TDF_Label Model_Document::groupLabel(const string theGroup)
aFLabIter.Next();
}
}
+ // after all updates, sends a message that groups of features were created or updated
+ boost::static_pointer_cast<Model_PluginManager>(Model_PluginManager::get())->
+ setCheckTransactions(false);
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_CREATED));
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_DELETED));
+ boost::static_pointer_cast<Model_PluginManager>(Model_PluginManager::get())->
+ setCheckTransactions(true);
}
Handle_TDocStd_Document myDoc; ///< OCAF document
/// number of transactions after the last "save" call, used for "IsModified" method
int myTransactionsAfterSave;
- /// number of myTransactionsAfterSave for the nested transaction start
- int myNestedStart;
+ /// number of nested transactions performed (or -1 if not nested)
+ int myNestedNum;
/// All features managed by this document (not only in history of OB)
std::vector<boost::shared_ptr<ModelAPI_Feature> > myFeatures;
#include <Model_Events.h>
#include <Events_Loop.h>
-Model_FeatureDeletedMessage::Model_FeatureDeletedMessage(
- const boost::shared_ptr<ModelAPI_Document>& theDoc, const std::string& theGroup)
- : Events_Message(messageId(), 0), myDoc(theDoc), myGroup(theGroup)
-
-{
-}
-
-const Events_ID Model_FeatureDeletedMessage::messageId()
-{
- static Events_ID MY_ID = Events_Loop::eventByName(EVENT_FEATURE_DELETED);
- return MY_ID;
-}
-
-Model_FeaturesMovedMessage::Model_FeaturesMovedMessage()
-: Events_Message(messageId(), 0)
-{
-}
-
-const Events_ID Model_FeaturesMovedMessage::messageId()
-{
- static Events_ID MY_ID = Events_Loop::eventByName(EVENT_FEATURES_MOVED);
- return MY_ID;
-}
-
-void Model_FeaturesMovedMessage::setFeatures(
- const std::list<boost::shared_ptr<ModelAPI_Feature> >& theFeatures)
-{
- myFeatures = theFeatures;
-}
-
-const std::list<boost::shared_ptr<ModelAPI_Feature> >& Model_FeaturesMovedMessage::features() const
-{
- return myFeatures;
-}
-
+// DELETED methods
+//Events_MessageGroup* Model_FeatureDeletedMessage::newEmpty() {
+// return new Model_FeatureDeletedMessage(myDoc, "");
+//}
+//
+//Model_FeatureDeletedMessage::Model_FeatureDeletedMessage(
+// const boost::shared_ptr<ModelAPI_Document>& theDoc, const std::string& theGroup)
+// : Events_MessageGroup(messageId(), 0), myDoc(theDoc)
+//
+//{
+// if (!theGroup.empty())
+// myGroups.insert(theGroup);
+//}
+//
+//const Events_ID Model_FeatureDeletedMessage::messageId()
+//{
+// static Events_ID MY_ID = Events_Loop::eventByName(EVENT_FEATURE_DELETED);
+// return MY_ID;
+//}
+//
+//void Model_FeatureDeletedMessage::Join(Events_MessageGroup& theJoined)
+//{
+// Model_FeatureDeletedMessage* aJoined = dynamic_cast<Model_FeatureDeletedMessage*>(&theJoined);
+// std::set<std::string>::iterator aGIter = aJoined->myGroups.begin();
+// for(; aGIter != aJoined->myGroups.end(); aGIter++) {
+// myGroups.insert(*aGIter);
+// }
+//}
#define Model_Events_HeaderFile
#include <Model.h>
-#include <Events_Message.h>
+#include <Events_MessageGroup.h>
#include <Events_Loop.h>
#include <boost/shared_ptr.hpp>
#include <string>
-#include <list>
+#include <set>
class ModelAPI_Feature;
class ModelAPI_Document;
/// Event ID that data of feature is deleted (comes with Model_FeatureDeletedMessage)
static const char * EVENT_FEATURE_DELETED = "FeatureDeleted";
/// Event ID that data of feature is updated (comes with Model_FeaturesMovedMessage)
-static const char * EVENT_FEATURES_MOVED = "FeaturesMoved";
+static const char * EVENT_FEATURE_MOVED = "FeaturesMoved";
-/// Message that feature was changed (used for Object Browser update)
-class Model_FeatureUpdatedMessage : public Events_Message {
- boost::shared_ptr<ModelAPI_Feature> myFeature; ///< which feature is changed
+/// Message that feature was changed (used for Object Browser update): moved, updated and deleted
+class Model_FeatureUpdatedMessage : public Events_MessageGroup {
+ std::set<boost::shared_ptr<ModelAPI_Feature> > myFeatures; ///< which feature is changed
public:
/// sender is not important, all information is located in the feature
Model_FeatureUpdatedMessage(
const boost::shared_ptr<ModelAPI_Feature>& theFeature,
- const Events_ID& theEvent) : Events_Message(theEvent, 0), myFeature(theFeature)
- {}
+ const Events_ID& theEvent) : Events_MessageGroup(theEvent, 0)
+ {if (theFeature) myFeatures.insert(theFeature);}
/// Returns the feature that has been updated
- boost::shared_ptr<ModelAPI_Feature> feature() const {return myFeature;}
+ std::set<boost::shared_ptr<ModelAPI_Feature> > features() const {return myFeatures;}
+
+ //! Creates a new empty group (to store it in the loop before flush)
+ virtual Events_MessageGroup* newEmpty() {
+ boost::shared_ptr<ModelAPI_Feature> anEmptyFeature;
+ return new Model_FeatureUpdatedMessage(anEmptyFeature, eventID());
+ }
+
+ //! Allows to join the given message with the current one
+ virtual void Join(Events_MessageGroup& theJoined) {
+ Model_FeatureUpdatedMessage* aJoined = dynamic_cast<Model_FeatureUpdatedMessage*>(&theJoined);
+ std::set<boost::shared_ptr<ModelAPI_Feature> >::iterator aFIter = aJoined->myFeatures.begin();
+ for(; aFIter != aJoined->myFeatures.end(); aFIter++) {
+ myFeatures.insert(*aFIter);
+ }
+ }
};
/// Message that feature was deleted (used for Object Browser update)
-class Model_FeatureDeletedMessage : public Events_Message {
+class Model_FeatureDeletedMessage : public Events_MessageGroup {
boost::shared_ptr<ModelAPI_Document> myDoc; ///< document owner of the feature
- std::string myGroup; ///< group identifier that contained the deleted feature
+ std::set<std::string> myGroups; ///< group identifiers that contained the deleted feature
public:
/// creates a message by initialization of fields
- Model_FeatureDeletedMessage(const boost::shared_ptr<ModelAPI_Document>& theDoc,
- const std::string& theGroup);
+// Model_FeatureDeletedMessage(const boost::shared_ptr<ModelAPI_Document>& theDoc,
+// const std::string& theGroup);
/// Returns the ID of this message (EVENT_FEATURE_DELETED)
- static const Events_ID messageId();
+// static const Events_ID messageId();
/// Returns the feature that has been updated
boost::shared_ptr<ModelAPI_Document> document() const {return myDoc;}
/// Returns the group where the feature was deleted
- const std::string& group() const {return myGroup;}
-};
+ const std::set<std::string >& groups() const {return myGroups;}
-/// Message that features were moved (used for the feature preview update)
-class Model_FeaturesMovedMessage : public Events_Message {
- std::list<boost::shared_ptr<ModelAPI_Feature> > myFeatures; ///< which features are moved
-public:
- /// creates a message by initialization of fields
- MODEL_EXPORT Model_FeaturesMovedMessage();
+ //! Creates a new empty group (to store it in the loop before flush)
+// virtual Events_MessageGroup* newEmpty();
+
+ //! Allows to join the given message with the current one
+// virtual void Join(Events_MessageGroup& theJoined);
+
+ Events_MessageGroup* newEmpty() {
+ return new Model_FeatureDeletedMessage(myDoc, "");
+ }
+
+ Model_FeatureDeletedMessage(
+ const boost::shared_ptr<ModelAPI_Document>& theDoc, const std::string& theGroup)
+ : Events_MessageGroup(messageId(), 0), myDoc(theDoc)
- /// Returns the ID of this message (EVENT_FEATURES_MOVED)
- static const Events_ID messageId();
+ {
+ if (!theGroup.empty())
+ myGroups.insert(theGroup);
+ }
- /// Sets a list of features
- MODEL_EXPORT void setFeatures(const std::list<boost::shared_ptr<ModelAPI_Feature> >& theFeatures);
+ const Events_ID messageId()
+ {
+ static Events_ID MY_ID = Events_Loop::eventByName(EVENT_FEATURE_DELETED);
+ return MY_ID;
+ }
- /// Returns a list of features
- MODEL_EXPORT const std::list<boost::shared_ptr<ModelAPI_Feature> >& features() const;
+ void Join(Events_MessageGroup& theJoined)
+ {
+ Model_FeatureDeletedMessage* aJoined = dynamic_cast<Model_FeatureDeletedMessage*>(&theJoined);
+ std::set<std::string>::iterator aGIter = aJoined->myGroups.begin();
+ for(; aGIter != aJoined->myGroups.end(); aGIter++) {
+ myGroups.insert(*aGIter);
+ }
+ }
};
#endif
#include "Model_Object.h"
#include <TCollection_AsciiString.hxx>
+#include "Model_Events.h"
+#include <Events_Loop.h>
boost::shared_ptr<ModelAPI_Feature> Model_Object::featureRef()
{
void Model_Object::setName(std::string theName)
{
- myName->Set(theName.c_str());
+ if (myName->Get() != theName.c_str()) {
+ myName->Set(theName.c_str());
+ /*
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
+ Model_FeatureUpdatedMessage aMsg(boost::shared_ptr<ModelAPI_Object>(this), anEvent);
+ Events_Loop::loop()->send(aMsg, false);
+ */
+ }
}
Model_Object::Model_Object(boost::shared_ptr<ModelAPI_Feature> theRef,
/// Returns to which group in the document must be added feature
MODEL_EXPORT virtual const std::string& getGroup() {return myRef->getGroup();}
+ /// Returns document this feature belongs to
+ MODEL_EXPORT virtual boost::shared_ptr<ModelAPI_Document> document()
+ {return myRef->document();}
+
+ /// Returns true if feature refers to the same model data instance
+ MODEL_EXPORT virtual bool isSame(const boost::shared_ptr<ModelAPI_Feature>& theFeature)
+ {
+ boost::shared_ptr<Model_Object> anObj = boost::dynamic_pointer_cast<Model_Object>(theFeature);
+ return anObj && myRef == anObj->myRef;
+ }
+
/// It is just a reference: don't init attributes
MODEL_EXPORT virtual void initAttributes() {}
/// Constructor fully defines this object
Model_Object(boost::shared_ptr<ModelAPI_Feature> theRef, Handle_TDataStd_Name theName);
- friend class Model_Document;
+ friend class Model_Document;
};
#endif
#include <Model_Data.h>
#include <Model_Document.h>
#include <Model_Application.h>
+#include <Model_Events.h>
#include <Events_Loop.h>
#include <Events_Error.h>
#include <Config_FeatureMessage.h>
Model_PluginManager::Model_PluginManager()
{
myPluginsInfoLoaded = false;
- //TODO(sbh): Implement static method to extract event id [SEID]
- static Events_ID aFeatureEvent = Events_Loop::eventByName("FeatureRegisterEvent");
-
+ myCheckTransactions = true;
ModelAPI_PluginManager::SetPluginManager(boost::shared_ptr<ModelAPI_PluginManager>(this));
// register the configuration reading listener
Events_Loop* aLoop = Events_Loop::loop();
- aLoop->registerListener(this, aFeatureEvent);
+ static Events_ID FeatureEvent = Events_Loop::eventByName("FeatureRegisterEvent");
+ aLoop->registerListener(this, FeatureEvent);
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_CREATED));
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_DELETED));
}
void Model_PluginManager::processEvent(const Events_Message* theMessage)
{
- const Config_FeatureMessage* aMsg =
- dynamic_cast<const Config_FeatureMessage*>(theMessage);
- if (aMsg) {
- // proccess the plugin info, load plugin
- if (myPlugins.find(aMsg->id()) == myPlugins.end()) {
- myPlugins[aMsg->id()] = aMsg->pluginLibrary();
+ static Events_ID FeatureEvent = Events_Loop::eventByName("FeatureRegisterEvent");
+ if (theMessage->eventID() == FeatureEvent) {
+ const Config_FeatureMessage* aMsg =
+ dynamic_cast<const Config_FeatureMessage*>(theMessage);
+ if (aMsg) {
+ // proccess the plugin info, load plugin
+ if (myPlugins.find(aMsg->id()) == myPlugins.end()) {
+ myPlugins[aMsg->id()] = aMsg->pluginLibrary();
+ }
}
+ // plugins information was started to load, so, it will be loaded
+ myPluginsInfoLoaded = true;
+ } else { // create/update/delete
+ if (myCheckTransactions && !rootDocument()->isOperation())
+ Events_Error::send("Modification of data structure outside of the transaction");
}
- // plugins information was started to load, so, it will be loaded
- myPluginsInfoLoaded = true;
}
void Model_PluginManager::LoadPluginsInfo()
std::map<std::string, ModelAPI_Plugin*> myPluginObjs; ///< instances of the already plugins
std::string myCurrentPluginName; ///< name of the plugin that must be loaded currently
boost::shared_ptr<ModelAPI_Document> myCurrentDoc; ///< current working document
+ bool myCheckTransactions; ///< if true, generates error if document is updated outside of transaction
public:
/// Returns the root document of the application (that may contains sub-documents)
MODEL_EXPORT virtual boost::shared_ptr<ModelAPI_Document> rootDocument();
MODEL_EXPORT virtual boost::shared_ptr<ModelAPI_Document> copy(
boost::shared_ptr<ModelAPI_Document> theSource, std::string theID);
+ void setCheckTransactions(const bool theCheck) {myCheckTransactions = theCheck;}
+
/// Is called only once, on startup of the application
Model_PluginManager();
MODELAPI_EXPORT virtual boost::shared_ptr<ModelAPI_Document> document()
{return myDoc;}
+ /// Returns true if feature refers to the same model data instance
+ MODELAPI_EXPORT virtual bool isSame(const boost::shared_ptr<ModelAPI_Feature>& theFeature)
+ {return true;}
+
/// To virtually destroy the fields of successors
virtual ~ModelAPI_Feature() {}
boost::shared_ptr<ModelAPI_PluginManager> ModelAPI_PluginManager::get()
{
if (!MY_MANAGER) { // import Model library that implements this interface of ModelAPI
- #ifdef _DEBUG
- std::cout << "ModelAPI_PluginManager::get: " << "Model library has not been loaded from xml." << std::endl;
- #endif
Config_ModuleReader::loadLibrary("Model");
}
return MY_MANAGER;
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/src/Config
+ ${CMAKE_SOURCE_DIR}/src/Events
+ ${CMAKE_SOURCE_DIR}/src/Model
${CMAKE_SOURCE_DIR}/src/ModelAPI
${CMAKE_SOURCE_DIR}/src/GeomDataAPI
)
#include <ModelAPI_Feature.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Document.h>
+#include <Model_Events.h>
+
+#include <Events_Loop.h>
#ifdef _DEBUG
#include <QDebug>
{
}
+QString ModuleBase_Operation::id() const
+{
+ return getDescription()->operationId();
+}
+
boost::shared_ptr<ModelAPI_Feature> ModuleBase_Operation::feature() const
{
return myFeature;
}
+bool ModuleBase_Operation::isNestedOperationsEnabled() const
+{
+ return true;
+}
+
void ModuleBase_Operation::storeReal(double theValue)
{
if(!myFeature){
boost::shared_ptr<ModelAPI_Data> aData = myFeature->data();
boost::shared_ptr<ModelAPI_AttributeDouble> aReal = aData->real(anId.toStdString());
aReal->setValue(theValue);
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
}
void ModuleBase_Operation::storeCustomValue()
if (myFeature) myFeature->execute();
}
-boost::shared_ptr<ModelAPI_Feature> ModuleBase_Operation::createFeature()
+void ModuleBase_Operation::flushUpdated()
+{
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
+}
+
+void ModuleBase_Operation::flushCreated()
+{
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_CREATED));
+}
+
+boost::shared_ptr<ModelAPI_Feature> ModuleBase_Operation::createFeature(const bool theFlushMessage)
{
boost::shared_ptr<ModelAPI_Document> aDoc = document();
boost::shared_ptr<ModelAPI_Feature> aFeature = aDoc->addFeature(
getDescription()->operationId().toStdString());
if (aFeature) // TODO: generate an error if feature was not created
aFeature->execute();
+
+ if (theFlushMessage)
+ flushCreated();
return aFeature;
}
/// Destructor
virtual ~ModuleBase_Operation();
+ // Returns operations Id from it's description
+ QString id() const;
/// Returns the operation feature
/// \return the feature
boost::shared_ptr<ModelAPI_Feature> feature() const;
+ /// Returns whether the nested operations are enabled.
+ /// The state can depend on the operation current state.
+ /// \return enabled state
+ virtual bool isNestedOperationsEnabled() const;
+
// Data model methods.
/// Stores a real value in model.
/// \param theValue - to store
/// Virtual method called when operation committed (see commit() method for more description)
virtual void commitOperation();
+ /// Send update message by loop
+ void flushUpdated();
+ /// Send created message by loop
+ void flushCreated();
+
/// Creates an operation new feature
+ /// \param theFlushMessage the flag whether the create message should be flushed
/// \returns the created feature
- virtual boost::shared_ptr<ModelAPI_Feature> createFeature();
+ virtual boost::shared_ptr<ModelAPI_Feature> createFeature(const bool theFlushMessage = true);
/// Returns the operation feature
/// \return the feature
#include <Config_Keywords.h>
+#include <Events_Loop.h>
+#include <Model_Events.h>
+
#include <ModelAPI_Feature.h>
#include <ModelAPI_Data.h>
#include <GeomDataAPI_Point2D.h>
bool isBlocked = this->blockSignals(true);
aPoint->setValue(myXSpin->value(), myYSpin->value());
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
+
this->blockSignals(isBlocked);
return true;
}
if (aType == EVENT_FEATURE_UPDATED ||
aType == EVENT_FEATURE_CREATED)
{
- const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
- boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
- if (myModule->workshop()->displayer()->IsVisible(aFeature) ||
- aType == EVENT_FEATURE_CREATED) {
- myModule->visualizePreview(aFeature, true, false);
- myModule->activateFeature(aFeature, true);
- myModule->workshop()->displayer()->UpdateViewer();
+ const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>
+ (theMessage);
+ std::set<boost::shared_ptr<ModelAPI_Feature> > aFeatures = aUpdMsg->features();
+ std::set<boost::shared_ptr<ModelAPI_Feature> >::const_iterator anIt = aFeatures.begin(),
+ aLast = aFeatures.end();
+ for (; anIt != aLast; anIt++) {
+ boost::shared_ptr<ModelAPI_Feature> aFeature = *anIt;
+ if (myModule->workshop()->displayer()->IsVisible(aFeature) ||
+ aType == EVENT_FEATURE_CREATED) {
+ myModule->visualizePreview(aFeature, true, false);
+ myModule->activateFeature(aFeature, true);
+ }
}
+ myModule->workshop()->displayer()->UpdateViewer();
}
if (aType == EVENT_FEATURE_DELETED)
{
const Model_FeatureDeletedMessage* aDelMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
boost::shared_ptr<ModelAPI_Document> aDoc = aDelMsg->document();
- std::string aGroup = aDelMsg->group();
- if (aDelMsg->group().compare("Sketch") == 0) { // Update only Sketch group
- myModule->workshop()->displayer()->EraseDeletedFeatures();
- myModule->updateCurrentPreview(aGroup);
+ std::set<std::string> aGroups = aDelMsg->groups();
+ std::set<std::string>::const_iterator anIt = aGroups.begin(), aLast = aGroups.end();
+ for (; anIt != aLast; anIt++) {
+ std::string aGroup = *anIt;
+ if (aGroup.compare("Sketch") == 0) { // Update only Sketch group
+ myModule->workshop()->displayer()->EraseDeletedFeatures();
+ myModule->updateCurrentPreview(aGroup);
+ }
}
}
}
}
}
+void PartSet_Module::onContextMenuCommand(const QString& theId, bool isChecked)
+{
+ QFeatureList aFeatures = myWorkshop->selector()->selectedFeatures();
+ if (theId == "EDIT_CMD" && (aFeatures.size() > 0)) {
+ editFeature(aFeatures.first());
+ }
+}
+
void PartSet_Module::onMousePressed(QMouseEvent* theEvent)
{
PartSet_OperationSketchBase* aPreviewOp = dynamic_cast<PartSet_OperationSketchBase*>(
myWorkshop->operationMgr()->currentOperation());
if (aPreviewOp)
{
- std::list<XGUI_ViewerPrs> aPresentations = myWorkshop->displayer()->GetViewerPrs();
- aPreviewOp->mousePressed(theEvent, myWorkshop->viewer()->activeView(), aPresentations);
+ XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+ std::list<XGUI_ViewerPrs> aSelected = aDisplayer->GetSelected();
+ std::list<XGUI_ViewerPrs> aHighlighted = aDisplayer->GetHighlighted();
+
+ aPreviewOp->mousePressed(theEvent, myWorkshop->viewer()->activeView(), aSelected, aHighlighted);
}
}
myWorkshop->operationMgr()->currentOperation());
if (aPreviewOp)
{
- std::list<XGUI_ViewerPrs> aPresentations = myWorkshop->displayer()->GetViewerPrs();
- aPreviewOp->mouseReleased(theEvent, myWorkshop->viewer()->activeView(), aPresentations);
+ XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+ std::list<XGUI_ViewerPrs> aSelected = aDisplayer->GetSelected();
+ std::list<XGUI_ViewerPrs> aHighlighted = aDisplayer->GetHighlighted();
+
+ aPreviewOp->mouseReleased(theEvent, myWorkshop->viewer()->activeView(), aSelected, aHighlighted);
}
}
void PartSet_Module::onPlaneSelected(double theX, double theY, double theZ)
{
myWorkshop->viewer()->setViewProjection(theX, theY, theZ);
- myWorkshop->actionsMgr()->setNestedActionsEnabled(true);
+ myWorkshop->actionsMgr()->update();
}
void PartSet_Module::onLaunchOperation(std::string theName, boost::shared_ptr<ModelAPI_Feature> theFeature)
PartSet_OperationSketchBase* aPreviewOp = dynamic_cast<PartSet_OperationSketchBase*>(anOperation);
if (aPreviewOp)
{
- std::list<XGUI_ViewerPrs> aPresentations = myWorkshop->displayer()->GetViewerPrs();
- aPreviewOp->init(theFeature, aPresentations);
+ XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+ // refill the features list with avoiding of the features, obtained only by vertex shape (TODO)
+ std::list<XGUI_ViewerPrs> aSelected = aDisplayer->GetSelected(TopAbs_VERTEX);
+ std::list<XGUI_ViewerPrs> aHighlighted = aDisplayer->GetHighlighted(TopAbs_VERTEX);
+ aPreviewOp->init(theFeature, aSelected, aHighlighted);
}
- myWorkshop->actionsMgr()->setActionChecked(anOperation->getDescription()->operationId(), true);
+ myWorkshop->actionsMgr()->updateCheckState();
sendOperation(anOperation);
}
}
}
aDisplayer->StopSelection(theFeatures, isStop, false);
+
+ XGUI_ViewerProxy* aViewer = myWorkshop->viewer();
+ aViewer->enableSelection(!isStop);
+
aDisplayer->UpdateViewer();
}
aDisplayer->UpdateViewer();
}
+void PartSet_Module::editFeature(FeaturePtr theFeature)
+{
+ /*if (!theFeature)
+ return;
+
+ if (theFeature->getKind() == "Sketch") {
+ onLaunchOperation(theFeature->getKind(), theFeature);
+ visualizePreview(theFeature, true);
+ }*/
+}
/// SLOT, that is called after the operation is stopped. Switched off the modfications performed
/// by the operation start
void onOperationStopped(ModuleBase_Operation* theOperation);
-
+ /// SLOT, that is called afetr the popup menu action clicked.
+ void onContextMenuCommand(const QString& theId, bool isChecked);
/// SLOT, that is called by mouse press in the viewer.
/// The mouse released point is sent to the current operation to be processed.
/// \param theEvent the mouse event
/// \param theOperation the operation
void sendOperation(ModuleBase_Operation* theOperation);
+protected:
+ //! Edits the feature
+ void editFeature(FeaturePtr theFeature);
+
private:
XGUI_Workshop* myWorkshop;
PartSet_Listener* myListener;
#include <PartSet_OperationSketch.h>
#include <ModuleBase_OperationDescription.h>
+#include <Model_Events.h>
#include <XGUI_ViewerPrs.h>
PartSet_OperationEditLine::PartSet_OperationEditLine(const QString& theId,
QObject* theParent,
boost::shared_ptr<ModelAPI_Feature> theFeature)
-: PartSet_OperationSketchBase(theId, theParent), mySketch(theFeature)
+: PartSet_OperationSketchBase(theId, theParent), mySketch(theFeature), myIsBlockedSelection(false)
{
}
}
void PartSet_OperationEditLine::init(boost::shared_ptr<ModelAPI_Feature> theFeature,
- const std::list<XGUI_ViewerPrs>& thePresentations)
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted)
{
setFeature(theFeature);
- myFeatures = thePresentations;
+
+ if (!theHighlighted.empty()) {
+ // if there is highlighted object, we check whether it is in the list of selected objects
+ // in that case this object is a handle of the moved lines. If there no such object in the selection,
+ // the hightlighted object should moved and the selection is skipped. The skipped selection will be
+ // deselected in the viewer by blockSelection signal in the startOperation method.
+ bool isSelected = false;
+ std::list<XGUI_ViewerPrs>::const_iterator anIt = theSelected.begin(), aLast = theSelected.end();
+ for (; anIt != aLast && !isSelected; anIt++) {
+ isSelected = (*anIt).feature() == feature();
+ }
+ if (!isSelected)
+ myFeatures = theHighlighted;
+ else
+ myFeatures = theSelected;
+ }
+ else
+ myFeatures = theSelected;
}
boost::shared_ptr<ModelAPI_Feature> PartSet_OperationEditLine::sketch() const
return mySketch;
}
-void PartSet_OperationEditLine::mousePressed(QMouseEvent* theEvent, Handle(V3d_View) theView)
+void PartSet_OperationEditLine::mousePressed(QMouseEvent* theEvent, Handle(V3d_View) theView,
+ const std::list<XGUI_ViewerPrs>& /*theSelected*/,
+ const std::list<XGUI_ViewerPrs>& theHighlighted)
{
- if (!(theEvent->buttons() & Qt::LeftButton))
- return;
- gp_Pnt aPoint = PartSet_Tools::ConvertClickToPoint(theEvent->pos(), theView);
- myCurPoint.setPoint(aPoint);
+ if (myFeatures.size() == 1)
+ {
+ boost::shared_ptr<ModelAPI_Feature> aFeature;
+ if (!theHighlighted.empty())
+ aFeature = theHighlighted.front().feature();
+
+ if (aFeature && aFeature == feature()) { // continue the feature edit
+ }
+ else {
+ XGUI_ViewerPrs aFeaturePrs = myFeatures.front();
+ commit();
+ emit featureConstructed(feature(), FM_Deactivation);
+
+ bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
+ if(aHasShift && !theHighlighted.empty()) {
+ std::list<XGUI_ViewerPrs> aSelected;
+ aSelected.push_back(aFeaturePrs);
+ aSelected.push_back(theHighlighted.front());
+ emit setSelection(aSelected);
+ }
+ else if (aFeature) {
+ emit launchOperation(PartSet_OperationEditLine::Type(), aFeature);
+ }
+ }
+ }
}
void PartSet_OperationEditLine::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
gp_Pnt aPoint = PartSet_Tools::ConvertClickToPoint(theEvent->pos(), theView);
+ blockSelection(true);
if (myCurPoint.myIsInitialized) {
double aCurX, aCurY;
PartSet_Tools::ConvertTo2D(myCurPoint.myPoint, sketch(), theView, aCurX, aCurY);
moveLinePoint(aFeature, aDeltaX, aDeltaY, LINE_ATTR_END);
}
}
+ flushUpdated();
sendFeatures();
myCurPoint.setPoint(aPoint);
}
void PartSet_OperationEditLine::mouseReleased(QMouseEvent* theEvent, Handle(V3d_View) theView,
- const std::list<XGUI_ViewerPrs>& theSelected)
+ const std::list<XGUI_ViewerPrs>& /*theSelected*/,
+ const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
{
std::list<XGUI_ViewerPrs> aFeatures = myFeatures;
if (myFeatures.size() == 1) {
- if (theSelected.empty())
- return;
-
- boost::shared_ptr<ModelAPI_Feature> aFeature = theSelected.front().feature();
- commit();
- emit launchOperation(PartSet_OperationEditLine::Type(), aFeature);
+ blockSelection(false);
}
else {
commit();
{
// do nothing in order to do not create a new feature
emit multiSelectionEnabled(false);
- emit setSelection(std::list<XGUI_ViewerPrs>());
- emit stopSelection(myFeatures, true);
+
+ if (myFeatures.size() > 1)
+ blockSelection(true);
+
myCurPoint.clear();
}
void PartSet_OperationEditLine::stopOperation()
{
emit multiSelectionEnabled(true);
- bool isSelectFeatures = myFeatures.size() > 1;
- emit stopSelection(myFeatures, false);
- if (isSelectFeatures)
- emit setSelection(myFeatures);
+
+ blockSelection(false, myFeatures.size() > 1);
myFeatures.clear();
}
-boost::shared_ptr<ModelAPI_Feature> PartSet_OperationEditLine::createFeature()
+void PartSet_OperationEditLine::blockSelection(bool isBlocked, const bool isRestoreSelection)
+{
+ if (myIsBlockedSelection == isBlocked)
+ return;
+
+ myIsBlockedSelection = isBlocked;
+ if (isBlocked) {
+ emit setSelection(std::list<XGUI_ViewerPrs>());
+ emit stopSelection(myFeatures, true);
+ }
+ else {
+ emit stopSelection(myFeatures, false);
+ if (isRestoreSelection)
+ emit setSelection(myFeatures);
+ }
+}
+
+boost::shared_ptr<ModelAPI_Feature> PartSet_OperationEditLine::createFeature(const bool /*theFlushMessage*/)
{
// do nothing in order to do not create a new feature
return boost::shared_ptr<ModelAPI_Feature>();
return;
boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
+ if (!aData->isValid())
+ return;
boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
void PartSet_OperationEditLine::sendFeatures()
{
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_MOVED);
+
std::list<boost::shared_ptr<ModelAPI_Feature> > aFeatures;
std::list<XGUI_ViewerPrs>::const_iterator anIt = myFeatures.begin(), aLast = myFeatures.end();
for (; anIt != aLast; anIt++) {
boost::shared_ptr<ModelAPI_Feature> aFeature = (*anIt).feature();
- if (!aFeature || aFeature == feature())
+ if (!aFeature)
continue;
- }
- static Events_ID aModuleEvent = Events_Loop::eventByName("PartSetEditEvent");
- Model_FeaturesMovedMessage aMessage;
- aMessage.setFeatures(aFeatures);
- Events_Loop::loop()->send(aMessage);
+ Model_FeatureUpdatedMessage aMessage(aFeature, anEvent);
+ Events_Loop::loop()->send(aMessage);
+ }
+ Events_Loop::loop()->flush(anEvent);
}
/// Initializes some fields accorging to the feature
/// \param theFeature the feature
- /// \param thePresentations the list of additional presentations
+ /// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
virtual void init(boost::shared_ptr<ModelAPI_Feature> theFeature,
- const std::list<XGUI_ViewerPrs>& thePresentations);
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted);
/// Returns the operation sketch feature
/// \returns the sketch instance
virtual boost::shared_ptr<ModelAPI_Feature> sketch() const;
/// Processes the mouse pressed in the point
- /// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
- virtual void mousePressed(QMouseEvent* theEvent, Handle_V3d_View theView);
+ /// \param theView a viewer to have the viewer the eye position
+ /// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
+ virtual void mousePressed(QMouseEvent* theEvent, Handle_V3d_View theView,
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted);
/// Gives the current mouse point in the viewer
- /// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
+ /// \param theView a viewer to have the viewer the eye position
virtual void mouseMoved(QMouseEvent* theEvent, Handle_V3d_View theView);
/// Gives the current selected objects to be processed by the operation
/// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
/// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
virtual void mouseReleased(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected);
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted);
protected:
/// \brief Virtual method called when operation is started
/// Virtual method called when operation started (see start() method for more description)
/// Creates an operation new feature
/// Returns NULL feature. This is an operation of edition, not creation.
+ /// \param theFlushMessage the flag whether the create message should be flushed
/// \returns the created feature
- virtual boost::shared_ptr<ModelAPI_Feature> createFeature();
+ virtual boost::shared_ptr<ModelAPI_Feature> createFeature(const bool theFlushMessage = true);
protected:
+ /// Emits a signal about the selection blocking. Emits a signal to change the selection.
+ /// If the block is true, the signal clear selection, otherwise if restore selection flag allows,
+ /// the internal operation features are to be selected
+ /// \param isBlocked the state whether the operation is blocked or unblocked
+ /// \param isRestoreSelection the state whether the selected objects should be reselected
+ void blockSelection(bool isBlocked, const bool isRestoreSelection = true);
+
/// \brief Save the point to the line.
/// \param theFeature the source feature
/// \param theDeltaX the delta for X coordinate is moved
std::list<XGUI_ViewerPrs> myFeatures; ///< the features to apply the edit operation
Point myCurPoint; ///< the current 3D point clicked or moved
gp_Pnt myCurPressed; ///< the current 3D point clicked or moved
+ bool myIsBlockedSelection; ///< the state of the last state of selection blocked signal
};
#endif
PartSet_OperationSketch::PartSet_OperationSketch(const QString& theId,
QObject* theParent)
-: PartSet_OperationSketchBase(theId, theParent), myIsEditMode(false)
+: PartSet_OperationSketchBase(theId, theParent)
{
}
std::list<int> PartSet_OperationSketch::getSelectionModes(boost::shared_ptr<ModelAPI_Feature> theFeature) const
{
std::list<int> aModes;
- if (!myIsEditMode)
+ if (!hasSketchPlane())
aModes.push_back(TopAbs_FACE);
else
aModes = PartSet_OperationSketchBase::getSelectionModes(theFeature);
return aModes;
}
-boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketch::sketch() const
+void PartSet_OperationSketch::init(boost::shared_ptr<ModelAPI_Feature> theFeature,
+ const std::list<XGUI_ViewerPrs>& thePresentations)
{
- return feature();
+ setFeature(theFeature);
}
-void PartSet_OperationSketch::mousePressed(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected)
+boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketch::sketch() const
{
- myFeatures = theSelected;
+ return feature();
}
-void PartSet_OperationSketch::mouseReleased(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected)
+void PartSet_OperationSketch::mousePressed(QMouseEvent* theEvent, Handle_V3d_View theView,
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted)
{
- if (theSelected.empty())
- return;
-
- if (!myIsEditMode) {
- XGUI_ViewerPrs aPrs = theSelected.front();
- const TopoDS_Shape& aShape = aPrs.shape();
- if (!aShape.IsNull()) {
- setSketchPlane(aShape);
- myIsEditMode = true;
+ if (!hasSketchPlane()) {
+ if (!theHighlighted.empty()) {
+ XGUI_ViewerPrs aPrs = theHighlighted.front();
+ const TopoDS_Shape& aShape = aPrs.shape();
+ if (!aShape.IsNull())
+ setSketchPlane(aShape);
}
}
else {
- if (theSelected.size() == 1) {
- boost::shared_ptr<ModelAPI_Feature> aFeature = theSelected.front().feature();
+ // if shift button is pressed and there are some already selected objects, the operation should
+ // not be started. We just want to combine some selected objects.
+ bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
+ if (aHasShift && theSelected.size() > 0)
+ return;
+
+ if (theHighlighted.size() == 1) {
+ boost::shared_ptr<ModelAPI_Feature> aFeature = theHighlighted.front().feature();
if (aFeature)
emit launchOperation(PartSet_OperationEditLine::Type(), aFeature);
}
+ else
+ myFeatures = theHighlighted;
}
- myFeatures.clear();
}
void PartSet_OperationSketch::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
{
- if (!myIsEditMode || !(theEvent->buttons() & Qt::LeftButton) || myFeatures.empty())
+ if (!hasSketchPlane() || !(theEvent->buttons() & Qt::LeftButton) || myFeatures.empty())
return;
if (myFeatures.size() != 1) {
boost::shared_ptr<SketchPlugin_Feature> aFeature;
boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
+ if (!aData->isValid())
+ return aPreviewMap;
boost::shared_ptr<ModelAPI_AttributeRefList> aRefList =
boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(aData->attribute(SKETCH_ATTR_FEATURES));
emit closeLocalContext();
}
+bool PartSet_OperationSketch::isNestedOperationsEnabled() const
+{
+ return hasSketchPlane();
+}
+
+bool PartSet_OperationSketch::hasSketchPlane() const
+{
+ bool aHasPlane = false;
+
+ if (feature()) {
+ // set plane parameters to feature
+ boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
+
+ boost::shared_ptr<ModelAPI_AttributeDouble> anAttr;
+ // temporary solution for main planes only
+ boost::shared_ptr<GeomDataAPI_Dir> aNormal =
+ boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_NORM));
+ double aX = aNormal->x(), anY = aNormal->y(), aZ = aNormal->z();
+
+ aHasPlane = aNormal && !(aNormal->x() == 0 && aNormal->y() == 0 && aNormal->z() == 0);
+ }
+ return aHasPlane;
+}
+
void PartSet_OperationSketch::setSketchPlane(const TopoDS_Shape& theShape)
{
if (theShape.IsNull())
aPlane->coefficients(anA, aB, aC, aD);
boost::shared_ptr<ModelAPI_AttributeDouble> anAttr;
- /*
- aData->real(SKETCH_ATTR_PLANE_A)->setValue(anA);
- aData->real(SKETCH_ATTR_PLANE_B)->setValue(aB);
- aData->real(SKETCH_ATTR_PLANE_C)->setValue(aC);
- aData->real(SKETCH_ATTR_PLANE_D)->setValue(aD);
- */
// temporary solution for main planes only
boost::shared_ptr<GeomDataAPI_Point> anOrigin =
boost::dynamic_pointer_cast<GeomDataAPI_Point>(aData->attribute(SKETCH_ATTR_ORIGIN));
boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_DIRY));
aDirY->setValue(aC, anA, aB);
boost::shared_ptr<GeomAPI_Dir> aDir = aPlane->direction();
+
+ flushUpdated();
+
emit featureConstructed(feature(), FM_Hide);
emit closeLocalContext();
emit planeSelected(aDir->x(), aDir->y(), aDir->z());
/// \return the selection mode
virtual std::list<int> getSelectionModes(boost::shared_ptr<ModelAPI_Feature> theFeature) const;
+ /// Initializes some fields accorging to the feature
+ /// \param theFeature the feature
+ /// \param thePresentations the list of additional presentations
+ virtual void init(boost::shared_ptr<ModelAPI_Feature> theFeature,
+ const std::list<XGUI_ViewerPrs>& thePresentations);
+
/// Returns the operation sketch feature
/// \returns the sketch instance
virtual boost::shared_ptr<ModelAPI_Feature> sketch() const;
/// Processes the mouse pressed in the point
- /// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
+ /// \param theView a viewer to have the viewer the eye position
/// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
virtual void mousePressed(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected);
- /// Processes the mouse release in the point
- /// \param thePoint a point clicked in the viewer
- /// \param theEvent the mouse event
- /// \param theSelected the list of selected presentations
- virtual void mouseReleased(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected);
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted);
/// Gives the current mouse point in the viewer
/// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
/// Emits a signal to hide the preview of the operation
virtual void stopOperation();
+ /// Returns whether the nested operations are enabled.
+ /// The state can depend on the operation current state.
+ /// It returns true after the sketch plane is choosen.
+ /// \return enabled state
+ virtual bool isNestedOperationsEnabled() const;
+
signals:
/// signal about the sketch plane is selected
/// \param theX the value in the X direction of the plane
void planeSelected(double theX, double theY, double theZ);
protected:
+ /// Returns whether the sketch plane is set
+ /// \return the boolean value whether the sketch is set
+ bool hasSketchPlane() const;
+
/// Set the plane to the current sketch
/// \param theShape the shape
void setSketchPlane(const TopoDS_Shape& theShape);
private:
- bool myIsEditMode; /// the edit mode of this operation
std::list<XGUI_ViewerPrs> myFeatures; ///< the features to apply the edit operation
};
aModes.push_back(TopAbs_EDGE);
return aModes;
}
-boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchBase::createFeature()
+boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchBase::createFeature(const bool theFlushMessage)
{
- boost::shared_ptr<ModelAPI_Feature> aFeature = ModuleBase_Operation::createFeature();
+ boost::shared_ptr<ModelAPI_Feature> aFeature = ModuleBase_Operation::createFeature(theFlushMessage);
if (aFeature)
emit featureConstructed(aFeature, FM_Activation);
return aFeature;
void PartSet_OperationSketchBase::mousePressed(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected)
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted)
{
}
void PartSet_OperationSketchBase::mouseReleased(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected)
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted)
{
}
void PartSet_OperationSketchBase::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
virtual std::list<int> getSelectionModes(boost::shared_ptr<ModelAPI_Feature> theFeature) const = 0;
/// Initializes some fields accorging to the feature
- /// \param theFeature the feature
- /// \param thePresentations the list of additional presentations
+ /// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
virtual void init(boost::shared_ptr<ModelAPI_Feature> theFeature,
- const std::list<XGUI_ViewerPrs>& thePresentations) {}
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted) {}
/// Returns the operation sketch feature
/// \returns the sketch instance
virtual boost::shared_ptr<ModelAPI_Feature> sketch() const = 0;
/// Processes the mouse pressed in the point
- /// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
+ /// \param theView a viewer to have the viewer the eye position
/// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
virtual void mousePressed(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected);
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted);
/// Processes the mouse release in the point
- /// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
+ /// \param theView a viewer to have the viewer the eye position
/// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
virtual void mouseReleased(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected);
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted);
/// Processes the mouse move in the point
- /// \param thePoint a 3D point clicked in the viewer
/// \param theEvent the mouse event
+ /// \param theView a viewer to have the viewer the eye position
virtual void mouseMoved(QMouseEvent* theEvent, Handle_V3d_View theView);
/// Processes the key pressed in the view
/// Creates an operation new feature
/// In addition to the default realization it appends the created line feature to
/// the sketch feature
+ /// \param theFlushMessage the flag whether the create message should be flushed
/// \returns the created feature
- virtual boost::shared_ptr<ModelAPI_Feature> createFeature();
+ virtual boost::shared_ptr<ModelAPI_Feature> createFeature(const bool theFlushMessage = true);
};
#endif
}
void PartSet_OperationSketchLine::init(boost::shared_ptr<ModelAPI_Feature> theFeature,
- const std::list<XGUI_ViewerPrs>& /*thePresentations*/)
+ const std::list<XGUI_ViewerPrs>& /*theSelected*/,
+ const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
{
if (!theFeature || theFeature->getKind() != "SketchLine")
return;
}
void PartSet_OperationSketchLine::mouseReleased(QMouseEvent* theEvent, Handle(V3d_View) theView,
- const std::list<XGUI_ViewerPrs>& theSelected)
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
{
double aX, anY;
case SM_FirstPoint: {
setLinePoint(feature(), aX, anY, LINE_ATTR_START);
setLinePoint(feature(), aX, anY, LINE_ATTR_END);
+ flushUpdated();
+
myPointSelectionMode = SM_SecondPoint;
}
break;
case SM_SecondPoint: {
setLinePoint(feature(), aX, anY, LINE_ATTR_END);
+ flushUpdated();
+
myPointSelectionMode = SM_DonePoint;
}
break;
PartSet_Tools::ConvertTo2D(aPoint, sketch(), theView, aX, anY);
setLinePoint(feature(), aX, anY, LINE_ATTR_START);
setLinePoint(feature(), aX, anY, LINE_ATTR_END);
+ flushUpdated();
}
break;
case SM_SecondPoint:
{
gp_Pnt aPoint = PartSet_Tools::ConvertClickToPoint(theEvent->pos(), theView);
setLinePoint(aPoint, theView, LINE_ATTR_END);
+ flushUpdated();
}
break;
case SM_DonePoint:
emit launchOperation(PartSet_OperationSketchLine::Type(), boost::shared_ptr<ModelAPI_Feature>());
}
break;
+ case Qt::Key_Escape: {
+ if (myPointSelectionMode == SM_DonePoint)
+ {
+ commit();
+ emit featureConstructed(feature(), FM_Deactivation);
+ }
+ else
+ abort();
+ }
default:
- PartSet_OperationSketchBase::keyReleased(theKey);
break;
}
}
emit multiSelectionEnabled(true);
}
-boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchLine::createFeature()
+boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchLine::createFeature(const bool theFlushMessage)
{
- boost::shared_ptr<ModelAPI_Feature> aNewFeature = ModuleBase_Operation::createFeature();
+ boost::shared_ptr<ModelAPI_Feature> aNewFeature = ModuleBase_Operation::createFeature(false);
if (sketch()) {
boost::shared_ptr<SketchPlugin_Feature> aFeature =
boost::dynamic_pointer_cast<SketchPlugin_Feature>(sketch());
}
emit featureConstructed(aNewFeature, FM_Activation);
+ if (theFlushMessage)
+ flushCreated();
return aNewFeature;
}
virtual std::list<int> getSelectionModes(boost::shared_ptr<ModelAPI_Feature> theFeature) const;
/// Initializes some fields accorging to the feature
- /// \param theFeature the feature
- /// \param thePresentations the list of additional presentations
+ /// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
virtual void init(boost::shared_ptr<ModelAPI_Feature> theFeature,
- const std::list<XGUI_ViewerPrs>& thePresentations);
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted);
/// Returns the operation sketch feature
/// \returns the sketch instance
virtual boost::shared_ptr<ModelAPI_Feature> sketch() const;
/// Gives the current selected objects to be processed by the operation
- /// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
+ /// \param theView a viewer to have the viewer the eye position
/// \param theSelected the list of selected presentations
+ /// \param theHighlighted the list of highlighted presentations
virtual void mouseReleased(QMouseEvent* theEvent, Handle_V3d_View theView,
- const std::list<XGUI_ViewerPrs>& theSelected);
+ const std::list<XGUI_ViewerPrs>& theSelected,
+ const std::list<XGUI_ViewerPrs>& theHighlighted);
/// Gives the current mouse point in the viewer
/// \param thePoint a point clicked in the viewer
/// \param theEvent the mouse event
/// Creates an operation new feature
/// In addition to the default realization it appends the created line feature to
/// the sketch feature
+ /// \param theFlushMessage the flag whether the create message should be flushed
/// \returns the created feature
- virtual boost::shared_ptr<ModelAPI_Feature> createFeature();
+ virtual boost::shared_ptr<ModelAPI_Feature> createFeature(const bool theFlushMessage = true);
/// Creates a constraint on two points
/// \param thePoint1 the first point
<plugin>
<workbench id="Part">
<group id="Operations">
- <feature id="Part" text="New part" tooltip="Creates a new part" icon=":pictures/part_ico.png"/>
- <feature id="duplicate" text="Duplicate" tooltip="Duplicate selected object" icon=":icons/duplicate.png"/>
- <feature id="remove" text="Remove" tooltip="Remove selected object" icon=":icons/remove.png"/>
+ <feature id="Part" title="New part" tooltip="Creates a new part" icon=":pictures/part_ico.png"/>
+ <feature id="duplicate" title="Duplicate" tooltip="Duplicate selected object" icon=":icons/duplicate.png"/>
+ <feature id="remove" title="Remove" tooltip="Remove selected object" icon=":icons/remove.png"/>
</group>
</workbench>
</plugin>
<plugin>
<workbench id="Sketch">
<group id="Basic">
- <feature id="Sketch" nested="SketchLine" text="New sketch" tooltip="Create a new sketch or edit an existing sketch" icon=":icons/sketch.png">
- <label text="Select a plane on which to create a sketch" tooltip="Select a plane on which to create a sketch"/>
+ <feature id="Sketch" nested="SketchLine" title="New sketch" tooltip="Create a new sketch or edit an existing sketch" icon=":icons/sketch.png">
+ <label title="Select a plane on which to create a sketch" tooltip="Select a plane on which to create a sketch"/>
<!--icon=":pictures/x_point.png"-->
</feature>
- <feature id="SketchPoint" text="Point" tooltip="Create a new point" icon=":icons/point.png" />
- <feature id="SketchLine" text="Line" tooltip="Create a new line" icon=":icons/line.png">
+ <feature id="SketchPoint" title="Point" tooltip="Create a new point" icon=":icons/point.png" internal="1"/>
+ <feature id="SketchLine" title="Line" tooltip="Create a new line" icon=":icons/line.png">
<point_selector id="StartPoint" title="Start point" tooltip="Start point of the line"/>
<point_selector id="EndPoint" title="End point" tooltip="End point of the line"/>
</feature>
- <feature id="SketchConstraintCoincidence" text="Points coincidence" tooltip="Create constraint for the coincidence of two points" icon="" />
+ <feature id="SketchConstraintCoincidence" title="Points coincidence" tooltip="Create constraint for the coincidence of two points" internal="1"/>
</group>
</workbench>
</plugin>
Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_CREATED));
Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_DELETED));
- Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURES_MOVED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_MOVED));
}
SketchSolver_ConstraintManager::~SketchSolver_ConstraintManager()
void SketchSolver_ConstraintManager::processEvent(const Events_Message* theMessage)
{
if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_CREATED) ||
- theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_UPDATED))
+ theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_UPDATED) ||
+ theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_MOVED))
{
- const Model_FeatureUpdatedMessage* aUpdateMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
+ const Model_FeatureUpdatedMessage* anUpdateMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
+ std::set< boost::shared_ptr<ModelAPI_Feature> > aFeatures = anUpdateMsg->features();
- // Only sketches and constraints can be added by Create event
- const std::string& aFeatureKind = aUpdateMsg->feature()->getKind();
- if (aFeatureKind.compare("Sketch") == 0)
+ bool isModifiedEvt = theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_MOVED);
+ if (!isModifiedEvt)
{
- boost::shared_ptr<SketchPlugin_Feature> aSketch =
- boost::dynamic_pointer_cast<SketchPlugin_Feature>(aUpdateMsg->feature());
- changeWorkplane(aSketch);
- return ;
- }
- boost::shared_ptr<SketchPlugin_Constraint> aConstraint =
- boost::dynamic_pointer_cast<SketchPlugin_Constraint>(aUpdateMsg->feature());
- if (aConstraint)
- changeConstraint(aConstraint);
- else
- {
- // Sketch plugin features can be only updated
- boost::shared_ptr<SketchPlugin_Feature> aFeature =
- boost::dynamic_pointer_cast<SketchPlugin_Feature>(aUpdateMsg->feature());
- if (aFeature)
- updateEntity(aFeature);
+ std::set< boost::shared_ptr<ModelAPI_Feature> >::iterator aFeatIter;
+ for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++)
+ {
+ // Only sketches and constraints can be added by Create event
+ const std::string& aFeatureKind = (*aFeatIter)->getKind();
+ if (aFeatureKind.compare("Sketch") == 0)
+ {
+ boost::shared_ptr<SketchPlugin_Feature> aSketch =
+ boost::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+ if (aSketch)
+ changeWorkplane(aSketch);
+ continue;
+ }
+ boost::shared_ptr<SketchPlugin_Constraint> aConstraint =
+ boost::dynamic_pointer_cast<SketchPlugin_Constraint>(*aFeatIter);
+ if (aConstraint)
+ changeConstraint(aConstraint);
+ else
+ {
+ // Sketch plugin features can be only updated
+ boost::shared_ptr<SketchPlugin_Feature> aFeature =
+ boost::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+ if (aFeature)
+ updateEntity(aFeature);
+ }
+ }
}
+
+ // Solve the set of constraints
+ resolveConstraints();
}
else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_DELETED))
{
const Model_FeatureDeletedMessage* aDeleteMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
+ const std::set<std::string>& aFeatureGroups = aDeleteMsg->groups();
- if (aDeleteMsg->group().compare("Sketch") == 0)
+ // Find "Sketch" in groups. The constraint groups should be updated when an object removed from Sketch
+ std::set<std::string>::const_iterator aFGrIter;
+ for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++)
+ if (aFGrIter->compare("Sketch") == 0)
+ break;
+
+ if (aFGrIter != aFeatureGroups.end())
{
std::vector<SketchSolver_ConstraintGroup*>::iterator aGroupIter = myGroups.begin();
while (aGroupIter != myGroups.end())
}
}
}
- else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURES_MOVED))
- {
- // Solve the set of constraints
- resolveConstraints();
- }
}
bool SketchSolver_ConstraintManager::changeWorkplane(boost::shared_ptr<SketchPlugin_Feature> theSketch)
std::vector<SketchSolver_ConstraintGroup*>::iterator aGroupIter;
for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
(*aGroupIter)->resolveConstraints();
+
+ // Features may be updated => send events
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
}
// Initialize workplane
myWorkplane.h = SLVS_E_UNKNOWN;
+#ifndef NDEBUG
assert(addWorkplane(theWorkplane));
+#else
+ addWorkplane(theWorkplane);
+#endif
}
SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::~SketchSolver_ConstraintGroup()
#include "XGUI_ActionsMgr.h"
#include "XGUI_Command.h"
#include "XGUI_Workshop.h"
-#include "XGUI_SalomeConnector.h"
+#include "XGUI_OperationMgr.h"
+
+#include <ModuleBase_Operation.h>
#include <QAction>
+#ifdef _DEBUG
+#include <QDebug>
+#endif
+
XGUI_ActionsMgr::XGUI_ActionsMgr(XGUI_Workshop* theParent)
- : QObject(theParent), myWorkshop(theParent)
+ : QObject(theParent), myOperationMgr(theParent->operationMgr())
{
-
+
}
XGUI_ActionsMgr::~XGUI_ActionsMgr()
void XGUI_ActionsMgr::addCommand(QAction* theCmd)
{
QString aId = theCmd->data().toString();
+ if(aId.isEmpty()) {
+ return;
+ }
myActions.insert(aId, theCmd);
- myActionsState.insert(aId, theCmd->isEnabled());
- connect(theCmd, SIGNAL(triggered(bool)), this, SLOT(setActionsDisabled(bool)));
+ XGUI_Command* aXCmd = dynamic_cast<XGUI_Command*>(theCmd);
+ if (aXCmd) {
+ myNestedActions[aId] = aXCmd->nestedCommands();
+ }
}
-void XGUI_ActionsMgr::setActionsDisabled(bool isDisabled)
+void XGUI_ActionsMgr::addNestedCommands(const QString& theId, const QStringList& theCommands)
{
- //Re-enable actions (just restore their state)
- if (!isDisabled) {
- myNestedActions.clear();
- restoreCommandState();
- return;
- }
- //Disable all actions, but caller and unblockable (defined in a xml)
- saveCommandsState();
-
- QString aSkippedId;
- QAction* aToggledFeature = dynamic_cast<QAction*>(sender());
- aSkippedId = aToggledFeature->data().toString();
+ myNestedActions[theId] = theCommands;
+}
- QStringList anActionIdsList = myActions.keys();
- foreach(QString eachKey, anActionIdsList) {
- if (eachKey == aSkippedId) {
- continue;
- }
- myActions[eachKey]->setEnabled(false);
- }
- if (myWorkshop->isSalomeMode()) {
- myNestedActions = myWorkshop->salomeConnector()->nestedActions(aSkippedId);
+void XGUI_ActionsMgr::update()
+{
+ if(myOperationMgr->hasOperation()) {
+ setAllEnabled(false);
+ ModuleBase_Operation* anOperation = myOperationMgr->currentOperation();
+ QString anOperationId = anOperation->id();
+ setActionEnabled(anOperationId, true);
+ bool isNestedEnabled = anOperation->isNestedOperationsEnabled();
+ setNestedCommandsEnabled(isNestedEnabled, anOperationId);
} else {
- XGUI_Command* aToggledFeature = dynamic_cast<XGUI_Command*>(sender());
- myNestedActions = aToggledFeature->unblockableCommands();
+ setAllEnabled(true);
+ setNestedCommandsEnabled(false);
}
+ updateCheckState();
}
-void XGUI_ActionsMgr::saveCommandsState()
+void XGUI_ActionsMgr::setAllEnabled(bool isEnabled)
{
- myActionsState.clear();
- QStringList anActionIdsList = myActions.keys();
- foreach(QString eachKey, anActionIdsList) {
- myActionsState.insert(eachKey, myActions[eachKey]->isEnabled());
+ foreach(QString eachAction, myActions.keys()) {
+ setActionEnabled(eachAction, isEnabled);
}
-
}
-void XGUI_ActionsMgr::restoreCommandState()
+//!
+void XGUI_ActionsMgr::setNestedCommandsEnabled(bool theEnabled, const QString& theParent)
{
- QStringList anActionIdsList = myActions.keys();
- foreach(QString eachKey, anActionIdsList) {
- myActions[eachKey]->setEnabled(myActionsState[eachKey]);
- myActions[eachKey]->setChecked(false);
+ QStringList ltNestedActions;
+ if(theParent.isEmpty()) { //Disable ALL nested
+ foreach(QString eachParent, myNestedActions.keys()) {
+ ltNestedActions << myNestedActions[eachParent];
+ }
+ } else {
+ ltNestedActions << myNestedActions[theParent];
+ }
+ foreach(QString eachNested, ltNestedActions) {
+ setActionEnabled(eachNested, theEnabled);
}
}
void XGUI_ActionsMgr::setActionChecked(const QString& theId, const bool theChecked)
{
- if(myActions.contains(theId)) {
- myActions[theId]->setChecked(theChecked);
+ QAction* anAction = myActions[theId];
+ if(anAction && anAction->isCheckable()) {
+ anAction->setChecked(theChecked);
}
}
-void XGUI_ActionsMgr::updateAction(const QString& theId)
+
+void XGUI_ActionsMgr::setActionEnabled(const QString& theId, const bool theEnabled)
{
- if(myActions.contains(theId)){
- myActions[theId]->setEnabled(myActionsState[theId]);
- myActions[theId]->setChecked(false);
+ QAction* anAction = myActions[theId];
+ if(anAction) {
+ anAction->setEnabled(theEnabled);
}
}
-void XGUI_ActionsMgr::setNestedActionsEnabled(bool isEnabled)
+void XGUI_ActionsMgr::updateCheckState()
{
- foreach(QString eachKey, myNestedActions) {
- if (myActions.contains(eachKey))
- myActions[eachKey]->setEnabled(isEnabled);
+ QString eachCommand = QString();
+ foreach(eachCommand, myActions.keys()) {
+ setActionChecked(eachCommand, false);
+ }
+ QStringList ltActiveCommands = myOperationMgr->operationList();
+ foreach(eachCommand, ltActiveCommands) {
+ setActionChecked(eachCommand, true);
}
}
class XGUI_Command;
class XGUI_Workshop;
+class XGUI_OperationMgr;
class QAction;
class XGUI_EXPORT XGUI_ActionsMgr: public QObject
Q_OBJECT
public:
- XGUI_ActionsMgr(XGUI_Workshop* theParent);
+ XGUI_ActionsMgr(XGUI_Workshop* theWorkshop);
virtual ~XGUI_ActionsMgr();
-
+ //! Add a command in the manager.
+ //! Please note that nested commands in the Salome mode (No XGUI_Command, pure QActions)
+ //! won't be extracted and should be added manually using the addNestedCommands method.
void addCommand(QAction* theCmd);
-
- void saveCommandsState();
- void restoreCommandState();
-
- /// Set the action is checked
- /// \param theId - string ID of the command
- /// \praram theChecked - the new checked state
- void setActionChecked(const QString& theId, const bool theChecked);
-
- void updateAction(const QString&);
- void setNestedActionsEnabled(bool);
+ //! Sets relation between the command (with given Id) and it's nested actions.
+ void addNestedCommands(const QString& theId, const QStringList& theCommands);
public slots:
- void setActionsDisabled(bool isEnabled);
+ //! Update workbench actions according to OperationMgr state:
+ //! No active operations: all actions but nested are available
+ //! There is active operation: current operation + it's nested
+ //! are enabled, all the rest is disabled. All active commands is checked.
+ void update();
+ //! Sets all commands checked if it's operation is active.
+ void updateCheckState();
+
+protected:
+ //! Sets all actions to isEnabled state.
+ void setAllEnabled(bool isEnabled);
+ //! Sets all nested actions to isEnabled state for the command with given ID.
+ //! If ID is empty - all nested actions will be affected.
+ void setNestedCommandsEnabled(bool isEnabled, const QString& theParent = QString());
+ //! Sets the action with theId to theChecked state.
+ void setActionChecked(const QString& theId, const bool theChecked);
+ //! Sets the action with theId to theEnabled state.
+ void setActionEnabled(const QString& theId, const bool theEnabled);
private:
- QStringList myNestedActions;
QMap<QString, QAction*> myActions;
- QMap<QString, bool> myActionsState;
+ QMap<QString, QStringList> myNestedActions;
- XGUI_Workshop* myWorkshop;
+ XGUI_OperationMgr* myOperationMgr;
};
#endif /* XGUI_ACTIONSMGR_H_ */
+
aButton->addAction(this);
connect(aButton, SIGNAL(clicked()), this, SLOT(trigger()));
connect(this, SIGNAL(toggled(bool)), aButton, SLOT(setChecked(bool)));
+ connect(this, SIGNAL(toggled(bool)), aButton, SLOT(setChecked(bool)));
aButton->setFlat(true);
aButton->setCheckable(myCheckable);
this->setCheckable(myCheckable);
connect(this, SIGNAL(triggered(bool)), theResiver, theSlot);
}
-const QStringList& XGUI_Command::unblockableCommands() const
+const QStringList& XGUI_Command::nestedCommands() const
{
- return myUnblockableCommands;
+ return myNestedCommands;
}
-void XGUI_Command::setUnblockableCommands(const QStringList& myUnblockableCommands)
+void XGUI_Command::setNestedCommands(const QStringList& myUnblockableCommands)
{
- this->myUnblockableCommands = myUnblockableCommands;
+ this->myNestedCommands = myUnblockableCommands;
}
return data().toString();
}*/
- const QStringList& unblockableCommands() const;
- void setUnblockableCommands(const QStringList& myUnblockableCommands);
+ const QStringList& nestedCommands() const;
+ void setNestedCommands(const QStringList& myUnblockableCommands);
//! Connect the command to a slot
virtual void connectTo(const QObject* theResiver, const char* theSlot);
private:
bool myCheckable;
//! List of Ids of commands which WILL NOT be blocked when the command is on.
- QStringList myUnblockableCommands;
+ QStringList myNestedCommands;
};
#endif
#include <ModelAPI_Data.h>
#include <ModelAPI_AttributeDocRef.h>
+#include <ModelAPI_Object.h>
#include <QAction>
#include <QContextMenuEvent>
//Process Feature
if (aFeature) {
if (aFeature->getKind() == "Part") {
- boost::shared_ptr<ModelAPI_Document> aFeaDoc = aFeature->data()->docRef("PartDocument")->value();
+ ObjectPtr aObject = boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature);
+ DocumentPtr aFeaDoc = aObject->featureRef()->data()->docRef("PartDocument")->value();
if (aMgr->currentDocument() == aFeaDoc)
aActions.append(action("DEACTIVATE_PART_CMD"));
else
} else {
aActions.append(action("EDIT_CMD"));
}
- aActions.append(action("DELETE_CMD"));
+ aActions.append(action("DELETE_CMD"));
// Process Root object (document)
} else { // If feature is 0 the it means that selected root object (document)
#include <ModelAPI_Data.h>
#include <AIS_InteractiveContext.hxx>
+#include <AIS_LocalContext.hxx>
#include <AIS_ListOfInteractive.hxx>
#include <AIS_ListIteratorOfListOfInteractive.hxx>
#include <set>
+const int MOUSE_SENSITIVITY_IN_PIXEL = 10; ///< defines the local context mouse selection sensitivity
+
XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop)
{
myWorkshop = theWorkshop;
}*/
-std::list<XGUI_ViewerPrs> XGUI_Displayer::GetViewerPrs()
+std::list<XGUI_ViewerPrs> XGUI_Displayer::GetSelected(const int theShapeTypeToSkip)
{
std::set<boost::shared_ptr<ModelAPI_Feature> > aPrsFeatures;
std::list<XGUI_ViewerPrs> aPresentations;
for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) {
Handle(AIS_InteractiveObject) anIO = aContext->SelectedInteractive();
TopoDS_Shape aShape = aContext->SelectedShape();
+ if (theShapeTypeToSkip >= 0 && !aShape.IsNull() && aShape.ShapeType() == theShapeTypeToSkip)
+ continue;
- boost::shared_ptr<ModelAPI_Feature> aFeature;
- FeatureToAISMap::const_iterator aFIt = myFeature2AISObjectMap.begin(),
- aFLast = myFeature2AISObjectMap.end();
- for (; aFIt != aFLast && !aFeature; aFIt++) {
- Handle(AIS_InteractiveObject) anAIS = (*aFIt).second;
- if (anAIS != anIO)
- continue;
- aFeature = (*aFIt).first;
- }
+ boost::shared_ptr<ModelAPI_Feature> aFeature = GetFeature(anIO);
+ if (aPrsFeatures.find(aFeature) != aPrsFeatures.end())
+ continue;
+ aPresentations.push_back(XGUI_ViewerPrs(aFeature, aShape));
+ aPrsFeatures.insert(aFeature);
+ }
+ return aPresentations;
+}
+
+std::list<XGUI_ViewerPrs> XGUI_Displayer::GetHighlighted(const int theShapeTypeToSkip)
+{
+ std::set<boost::shared_ptr<ModelAPI_Feature> > aPrsFeatures;
+ std::list<XGUI_ViewerPrs> aPresentations;
+
+ Handle(AIS_InteractiveContext) aContext = AISContext();
+ for (aContext->InitDetected(); aContext->MoreDetected(); aContext->NextDetected()) {
+ Handle(AIS_InteractiveObject) anIO = aContext->DetectedInteractive();
+ TopoDS_Shape aShape = aContext->DetectedShape();
+ if (theShapeTypeToSkip >= 0 && !aShape.IsNull() && aShape.ShapeType() == theShapeTypeToSkip)
+ continue;
+
+ boost::shared_ptr<ModelAPI_Feature> aFeature = GetFeature(anIO);
if (aPrsFeatures.find(aFeature) != aPrsFeatures.end())
continue;
aPresentations.push_back(XGUI_ViewerPrs(aFeature, aShape));
if (!aContext->HasOpenedContext()) {
aContext->ClearCurrents(false);
aContext->OpenLocalContext(false/*use displayed objects*/, true/*allow shape decomposition*/);
+ // set mouse sensitivity
+ //aContext->SetSensitivityMode(StdSelect_SM_WINDOW);
+ //aContext->SetPixelTolerance(MOUSE_SENSITIVITY_IN_PIXEL);
}
// display or redisplay presentation
Handle(AIS_Shape) anAIS;
boost::shared_ptr<ModelAPI_Feature> aFeature;
Handle(AIS_Shape) anAIS;
- aContext->ClearSelected();
+ // we need to unhighligth objects manually in the current local context
+ // in couple with the selection clear (TODO)
+ Handle(AIS_LocalContext) aLocalContext = aContext->LocalContext();
+ if (!aLocalContext.IsNull())
+ aLocalContext->UnhilightLastDetected(myWorkshop->viewer()->activeView());
+ aContext->ClearSelected(false);
for (; anIt != aLast; anIt++) {
aFeature = (*anIt).feature();
continue;
aContext->AddOrRemoveSelected(anAIS, false);
}
+
if (isUpdateViewer)
aContext->UpdateCurrentViewer();
}
void XGUI_Displayer::CloseLocalContexts(const bool isUpdateViewer)
{
- closeAllContexts(true);
+ CloseAllContexts(true);
+}
+
+boost::shared_ptr<ModelAPI_Feature> XGUI_Displayer::GetFeature(Handle(AIS_InteractiveObject) theIO)
+{
+ boost::shared_ptr<ModelAPI_Feature> aFeature;
+ FeatureToAISMap::const_iterator aFIt = myFeature2AISObjectMap.begin(),
+ aFLast = myFeature2AISObjectMap.end();
+ for (; aFIt != aFLast && !aFeature; aFIt++) {
+ Handle(AIS_InteractiveObject) anAIS = (*aFIt).second;
+ if (anAIS != theIO)
+ continue;
+ aFeature = (*aFIt).first;
+ }
+ return aFeature;
}
-void XGUI_Displayer::closeAllContexts(const bool isUpdateViewer)
+void XGUI_Displayer::CloseAllContexts(const bool isUpdateViewer)
{
Handle(AIS_InteractiveContext) ic = AISContext();
if (!ic.IsNull()) {
//void Display(boost::shared_ptr<ModelAPI_Feature> theFeature, const TopoDS_Shape& theShape,
// const bool isUpdateViewer = true);
- /// Returns a list of viewer presentations
+ /// Returns a list of viewer selected presentations
+ /// \param theShapeTypeToSkip the shapes with this type will be skipped during the result list build
/// \return list of presentations
- std::list<XGUI_ViewerPrs> GetViewerPrs();
+ std::list<XGUI_ViewerPrs> GetSelected(const int theShapeTypeToSkip = -1);
+
+ /// Returns a list of viewer highlited presentations
+ /// \param theShapeTypeToSkip the shapes with this type will be skipped during the result list build
+ /// \return list of presentations
+ std::list<XGUI_ViewerPrs> GetHighlighted(const int theShapeTypeToSkip = -1);
/// Display the shape and activate selection of sub-shapes
/// \param theFeature a feature instance
void UpdateViewer();
protected:
+ /// Searches the feature by interactive object
+ /// \param theIO an interactive object
+ /// \return feature the feature or NULL if it not visualized
+ boost::shared_ptr<ModelAPI_Feature> GetFeature(Handle(AIS_InteractiveObject) theIO);
/// Deactivate local selection
/// \param isUpdateViewer the state wether the viewer should be updated immediatelly
- void closeAllContexts(const bool isUpdateViewer);
+ void CloseAllContexts(const bool isUpdateViewer);
/// Returns currently installed AIS_InteractiveContext
Handle(AIS_InteractiveContext) AISContext() const;
// Created object event *******************
if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_CREATED)) {
const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
- FeaturePtr aFeature = aUpdMsg->feature();
- DocumentPtr aDoc = aFeature->document();
-
- if (aDoc == myDocument) { // If root objects
- if (aFeature->getGroup().compare(PARTS_GROUP) == 0) { // Update only Parts group
- // Add a new part
- int aStart = myPartModels.size() + 1;
- XGUI_PartDataModel* aModel = new XGUI_PartDataModel(myDocument, this);
- aModel->setPartId(myPartModels.count());
- myPartModels.append(aModel);
- insertRow(aStart, partFolderNode());
- } else { // Update top groups (other except parts
- QModelIndex aIndex = myModel->findParent(aFeature);
- int aStart = myModel->rowCount(aIndex) - 1;
- aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
- insertRow(aStart, aIndex);
- }
- } else { // if sub-objects of first level nodes
- XGUI_PartModel* aPartModel = 0;
- QList<XGUI_PartModel*>::const_iterator aIt;
- for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
- if ((*aIt)->hasDocument(aDoc)) {
- aPartModel = (*aIt);
- break;
+ std::set<FeaturePtr> aFeatures = aUpdMsg->features();
+
+ std::set<FeaturePtr>::const_iterator aIt;
+ for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) {
+ FeaturePtr aFeature = (*aIt);
+ DocumentPtr aDoc = aFeature->document();
+ if (aDoc == myDocument) { // If root objects
+ if (aFeature->getGroup().compare(PARTS_GROUP) == 0) { // Update only Parts group
+ // Add a new part
+ int aStart = myPartModels.size() + 1;
+ XGUI_PartDataModel* aModel = new XGUI_PartDataModel(myDocument, this);
+ aModel->setPartId(myPartModels.count());
+ myPartModels.append(aModel);
+ insertRow(aStart, partFolderNode());
+ } else { // Update top groups (other except parts
+ QModelIndex aIndex = myModel->findParent(aFeature);
+ int aStart = myModel->rowCount(aIndex) - 1;
+ aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
+ insertRow(aStart, aIndex);
+ }
+ } else { // if sub-objects of first level nodes
+ XGUI_PartModel* aPartModel = 0;
+ QList<XGUI_PartModel*>::const_iterator aIt;
+ for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
+ if ((*aIt)->hasDocument(aDoc)) {
+ aPartModel = (*aIt);
+ break;
+ }
+ }
+ if (aPartModel) {
+ QModelIndex aIndex = aPartModel->findParent(aFeature);
+ int aStart = aPartModel->rowCount(aIndex) - 1;
+ aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
+ insertRow(aStart, aIndex);
}
- }
- if (aPartModel) {
- QModelIndex aIndex = aPartModel->findParent(aFeature);
- int aStart = aPartModel->rowCount(aIndex) - 1;
- aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
- insertRow(aStart, aIndex);
}
}
-
// Deleted object event ***********************
} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_DELETED)) {
const Model_FeatureDeletedMessage* aUpdMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
DocumentPtr aDoc = aUpdMsg->document();
-
- if (aDoc == myDocument) { // If root objects
- if (aUpdMsg->group().compare(PARTS_GROUP) == 0) { // Updsate only Parts group
- int aStart = myPartModels.size();
- removeSubModel(myPartModels.size() - 1);
- removeRow(aStart, partFolderNode());
- } else { // Update top groups (other except parts
- QModelIndex aIndex = myModel->findGroup(aUpdMsg->group());
- int aStart = myModel->rowCount(aIndex);
- aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
- removeRow(aStart, aIndex);
- }
- } else {
- XGUI_PartModel* aPartModel = 0;
- QList<XGUI_PartModel*>::const_iterator aIt;
- for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
- if ((*aIt)->hasDocument(aDoc)) {
- aPartModel = (*aIt);
- break;
+ std::set<std::string> aGroups = aUpdMsg->groups();
+
+ std::set<std::string>::const_iterator aIt;
+ for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
+ std::string aGroup = (*aIt);
+ if (aDoc == myDocument) { // If root objects
+ if (aGroup.compare(PARTS_GROUP) == 0) { // Updsate only Parts group
+ int aStart = myPartModels.size() - 1;
+ removeSubModel(aStart);
+ removeRow(aStart, partFolderNode());
+ } else { // Update top groups (other except parts
+ QModelIndex aIndex = myModel->findGroup(aGroup);
+ int aStart = myModel->rowCount(aIndex);
+ aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
+ removeRow(aStart, aIndex);
+ }
+ } else {
+ XGUI_PartModel* aPartModel = 0;
+ QList<XGUI_PartModel*>::const_iterator aIt;
+ for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
+ if ((*aIt)->hasDocument(aDoc)) {
+ aPartModel = (*aIt);
+ break;
+ }
+ }
+ if (aPartModel) {
+ QModelIndex aIndex = aPartModel->findGroup(aGroup);
+ int aStart = aPartModel->rowCount(aIndex);
+ aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
+ removeRow(aStart, aIndex);
}
- }
- if (aPartModel) {
- QModelIndex aIndex = aPartModel->findGroup(aUpdMsg->group());
- int aStart = aPartModel->rowCount(aIndex);
- aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
- removeRow(aStart, aIndex);
}
}
-
// Deleted object event ***********************
} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_UPDATED)) {
//const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
#include <QDockWidget>
#include <QApplication>
#include <QTimer>
+#include <QCloseEvent>
XGUI_MainWindow::XGUI_MainWindow(QWidget* parent)
: QMainWindow(parent),
if (aAct->isCheckable())
aAct->setChecked(aAct->text() == aWndTitle);
}
-}
\ No newline at end of file
+}
+
+void XGUI_MainWindow::closeEvent(QCloseEvent * event)
+{
+ emit exitKeySequence();
+ event->ignore();
+}
class QMdiArea;
class QMdiSubWindow;
class PyConsole_EnhConsole;
+class QCloseEvent;
/**\class XGUI_MainWindow
* \ingroup GUI
void activateView();
void onViewActivated(QMdiSubWindow* theSubWnd);
+signals:
+ void exitKeySequence();
+
+protected:
+ void closeEvent(QCloseEvent* event);
+
private:
XGUI_MainMenu* myMenuBar;
XGUI_Viewer* myViewer;
#include <ModelAPI_Data.h>
#include <ModelAPI_PluginManager.h>
#include <ModelAPI_Document.h>
+#include <ModelAPI_Object.h>
#include <QLayout>
#include <QLabel>
if (aEditor) {
QString aRes = aEditor->text();
FeaturePtr aFeature = mySelectedData.first();
- aFeature->data()->setName(qPrintable(aRes));
+ aFeature->document()->startOperation();
+ if (aFeature->data())
+ aFeature->data()->setName(qPrintable(aRes));
+ else
+ boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature)->setName(qPrintable(aRes));
+ aFeature->document()->finishOperation();
}
}
// Find index which corresponds the feature
QModelIndex aIndex;
foreach(QModelIndex aIdx, selectedIndexes()) {
- if (dataModel()->feature(aIdx) == aFeature) {
+ FeaturePtr aFea = dataModel()->feature(aIdx);
+ if (dataModel()->feature(aIdx)->isSame(aFeature)) {
aIndex = aIdx;
break;
}
return true;
}
+QStringList XGUI_OperationMgr::operationList()
+{
+ QStringList result;
+ foreach(ModuleBase_Operation* eachOperation, myOperations) {
+ result << eachOperation->id();
+ }
+ return result;
+}
+
void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
{
theOperation->resume();
if (!aSenderOperation || !anOperation || aSenderOperation != anOperation )
return;
- emit operationStopped(anOperation);
-
myOperations.removeAll(anOperation);
anOperation->deleteLater();
+ emit operationStopped(anOperation);
+
// get last operation which can be resumed
ModuleBase_Operation* aResultOp = 0;
QListIterator<ModuleBase_Operation*> anIt(myOperations);
#include <QList>
#include <QObject>
+#include <QStringList>
/**\class XGUI_OperationMgr
* \ingroup GUI
/// Abort the operation and append it to the stack of operations
/// \return the state whether the current operation is aborted
bool abortOperation();
+ ///Returns list of all operations IDs
+ QStringList operationList();
signals:
/// Signal about an operation is started. It is emitted after the start() of operation is done.
return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
case ParamObject:
{
- FeaturePtr aFeature = myDocument->feature(PARAMETERS_GROUP, theIndex.row(), true);
+ FeaturePtr aFeature = myDocument->feature(PARAMETERS_GROUP, theIndex.row());
if (aFeature)
- return aFeature->data()->getName().c_str();
+ return boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature)->getName().c_str();
}
case ConstructFolder:
return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
case ConstructObject:
{
- FeaturePtr aFeature = myDocument->feature(CONSTRUCTIONS_GROUP, theIndex.row(), true);
+ FeaturePtr aFeature = myDocument->feature(CONSTRUCTIONS_GROUP, theIndex.row());
if (aFeature)
- return aFeature->data()->getName().c_str();
+ return boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature)->getName().c_str();
}
}
break;
return QIcon(":pictures/constr_folder.png");
case ConstructObject:
{
- FeaturePtr aFeature = myDocument->feature(CONSTRUCTIONS_GROUP, theIndex.row(), true);
+ FeaturePtr aFeature = myDocument->feature(CONSTRUCTIONS_GROUP, theIndex.row());
if (aFeature)
return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind()));
}
case ConstructFolder:
return FeaturePtr();
case ParamObject:
- return myDocument->feature(PARAMETERS_GROUP, theIndex.row(), true);
+ return myDocument->feature(PARAMETERS_GROUP, theIndex.row());
case ConstructObject:
- return myDocument->feature(CONSTRUCTIONS_GROUP, theIndex.row(), true);
+ return myDocument->feature(CONSTRUCTIONS_GROUP, theIndex.row());
}
return FeaturePtr();
}
int aNb = myDocument->size(aGroup);
int aRow = -1;
for (int i = 0; i < aNb; i++) {
- if (myDocument->feature(aGroup, i, true) == theFeature) {
+ if (myDocument->feature(aGroup, i) == theFeature) {
aRow = i;
break;
}
switch (theIndex.internalId()) {
case MyRoot:
{
- FeaturePtr aFeature = myDocument->feature(PARTS_GROUP, myId, true);
+ FeaturePtr aFeature = myDocument->feature(PARTS_GROUP, myId);
if (aFeature)
- return aFeature->data()->getName().c_str();
+ return boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature)->getName().c_str();
}
case ParamsFolder:
return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
return tr("Bodies") + QString(" (%1)").arg(rowCount(theIndex));
case ParamObject:
{
- FeaturePtr aFeature = featureDocument()->feature(PARAMETERS_GROUP, theIndex.row(), true);
+ FeaturePtr aFeature = featureDocument()->feature(PARAMETERS_GROUP, theIndex.row());
if (aFeature)
- return aFeature->data()->getName().c_str();
+ return boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature)->getName().c_str();
}
case ConstructObject:
{
- FeaturePtr aFeature = featureDocument()->feature(CONSTRUCTIONS_GROUP, theIndex.row(), true);
+ FeaturePtr aFeature = featureDocument()->feature(CONSTRUCTIONS_GROUP, theIndex.row());
if (aFeature)
- return aFeature->data()->getName().c_str();
+ return boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature)->getName().c_str();
}
case HistoryObject:
{
- FeaturePtr aFeature = featureDocument()->feature(FEATURES_GROUP, theIndex.row() - 3, true);
+ FeaturePtr aFeature = featureDocument()->feature(FEATURES_GROUP, theIndex.row() - 3);
if (aFeature)
return aFeature->data()->getName().c_str();
}
return QIcon(":pictures/constr_folder.png");
case ConstructObject:
{
- FeaturePtr aFeature = featureDocument()->feature(CONSTRUCTIONS_GROUP, theIndex.row(), true);
+ FeaturePtr aFeature = featureDocument()->feature(CONSTRUCTIONS_GROUP, theIndex.row());
if (aFeature)
return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind()));
}
case HistoryObject:
{
- FeaturePtr aFeature = featureDocument()->feature(FEATURES_GROUP, theIndex.row() - 3, true);
+ FeaturePtr aFeature = featureDocument()->feature(FEATURES_GROUP, theIndex.row() - 3);
if (aFeature)
return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind()));
}
int XGUI_PartDataModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid())
- if (myDocument->feature(PARTS_GROUP, myId, true))
+ if (myDocument->feature(PARTS_GROUP, myId))
return 1;
else
return 0;
{
switch (theIndex.internalId()) {
case MyRoot:
- if (theIndex.row() < 3) {
- return myDocument->feature(PARTS_GROUP, myId, true);
- } else
- return featureDocument()->feature(FEATURES_GROUP, theIndex.row() - 3, true);
+ return myDocument->feature(PARTS_GROUP, myId);
case ParamsFolder:
case ConstructFolder:
case BodiesFolder:
return FeaturePtr();
case ParamObject:
- return featureDocument()->feature(PARAMETERS_GROUP, theIndex.row(), true);
+ return featureDocument()->feature(PARAMETERS_GROUP, theIndex.row());
case ConstructObject:
- return featureDocument()->feature(CONSTRUCTIONS_GROUP, theIndex.row(), true);
+ return featureDocument()->feature(CONSTRUCTIONS_GROUP, theIndex.row());
//case BodiesObject:
- // return featureDocument()->feature(CONSTRUCTIONS_GROUP, theIndex.row(), true);
+ // return featureDocument()->feature(CONSTRUCTIONS_GROUP, theIndex.row());
+ case HistoryObject:
+ return featureDocument()->feature(FEATURES_GROUP, theIndex.row() - 3);
}
return FeaturePtr();
}
int aNb = myDocument->size(aGroup);
int aRow = -1;
for (int i = 0; i < aNb; i++) {
- if (myDocument->feature(aGroup, i, true) == theFeature) {
+ if (myDocument->feature(aGroup, i) == theFeature) {
aRow = i;
break;
}
this->setWindowTitle(tr("Property Panel"));
QAction* aViewAct = this->toggleViewAction();
this->setObjectName(XGUI::PROP_PANEL);
+ setStyleSheet("::title { position: relative; padding-left: 5px; text-align: left center }");
QWidget* aContent = new QWidget(this);
QVBoxLayout* aMainLay = new QVBoxLayout(aContent);
*/
void XGUI_Viewer::onMouseMove(XGUI_ViewWindow* theWindow, QMouseEvent* theEvent)
{
+ myCurPnt.setX(theEvent->x()); myCurPnt.setY(theEvent->y());
if (!mySelectionEnabled) return;
- myCurPnt.setX(theEvent->x()); myCurPnt.setY(theEvent->y());
Handle(V3d_View) aView3d = theWindow->viewPort()->getView();
if ( !aView3d.IsNull() ) {
myAISContext->MoveTo(theEvent->x(), theEvent->y(), aView3d);
XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
: QObject(),
- myCurrentFile(QString()),
+ myCurrentDir(QString()),
myPartSetModule(NULL),
mySalomeConnector(theConnector),
myPropertyPanel(0),
myViewerProxy = new XGUI_ViewerProxy(this);
- connect(myOperationMgr, SIGNAL(operationStarted()), this, SLOT(onOperationStarted()));
- connect(myOperationMgr, SIGNAL(operationResumed()), this, SLOT(onOperationStarted()));
- connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
- this, SLOT(onOperationStopped(ModuleBase_Operation*)));
+ connect(myOperationMgr, SIGNAL(operationStarted()), SLOT(onOperationStarted()));
+ connect(myOperationMgr, SIGNAL(operationResumed()), SLOT(onOperationStarted()));
+ connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), SLOT(onOperationStopped(ModuleBase_Operation*)));
+ connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
+ connect(myOperationMgr, SIGNAL(operationStarted()), myActionsMgr, SLOT(update()));
+ connect(myOperationMgr, SIGNAL(operationStopped()), myActionsMgr, SLOT(update()));
connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&)));
}
aCommand = aGroup->addFeature("EXIT_CMD", tr("Exit"), tr("Exit application"),
QIcon(":pictures/close.png"), QKeySequence::Close);
aCommand->connectTo(this, SLOT(onExit()));
+ //FIXME: SBH's test action. Can be used for some GUI tests.
+ //#ifdef _DEBUG
+ // aCommand = aGroup->addFeature("TEST_CMD", "Test!", "Private debug button",
+ // QIcon(":pictures/close.png"));
+ // aCommand->connectTo(myActionsMgr, SLOT(update()));
+ //#endif
}
//******************************************************
static Events_ID aFeatureLoadedId = Events_Loop::loop()->eventByName(EVENT_FEATURE_LOADED);
if (theMessage->eventID() == aFeatureLoadedId) {
const Config_FeatureMessage* aFeatureMsg = dynamic_cast<const Config_FeatureMessage*>(theMessage);
- addFeature(aFeatureMsg);
+ if(!aFeatureMsg->isInternal()) {
+ addFeature(aFeatureMsg);
+ }
return;
}
// Process creation of Part
if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_CREATED)) {
const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
- FeaturePtr aFeature = aUpdMsg->feature();
- if (aFeature->getKind() == "Part") {
+ std::set<FeaturePtr> aFeatures = aUpdMsg->features();
+
+ std::set<FeaturePtr>::const_iterator aIt;
+ bool aHasPart = false;
+ for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) {
+ FeaturePtr aFeature = (*aIt);
+ if (aFeature->getKind() == "Part") {
+ aHasPart = true;
+ break;
+ }
+ }
+ if (aHasPart) {
//The created part will be created in Object Browser later and we have to activate it
// only when it is created everywere
QTimer::singleShot(50, this, SLOT(activateLastPart()));
{
const Model_FeatureUpdatedMessage* anUpdateMsg =
dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
- FeaturePtr aNewFeature = anUpdateMsg->feature();
+ std::set<FeaturePtr> aFeatures = anUpdateMsg->features();
+
FeaturePtr aCurrentFeature = myOperationMgr->currentOperation()->feature();
- if(aNewFeature == aCurrentFeature) {
- myPropertyPanel->updateContentWidget(aCurrentFeature);
+ std::set<FeaturePtr>::const_iterator aIt;
+ for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) {
+ FeaturePtr aNewFeature = (*aIt);
+ if(aNewFeature == aCurrentFeature) {
+ myPropertyPanel->updateContentWidget(aCurrentFeature);
+ break;
+ }
}
}
//An operation passed by message. Start it, process and commit.
//******************************************************
void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
{
- ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-
//!< No need for property panel
updateCommandStatus();
hidePropertyPanel();
- if(myOperationMgr->operationsCount() > 1) {
- myActionsMgr->updateAction(theOperation->getDescription()->operationId());
- return;
- }
- if(!aOperation->getDescription()->xmlRepresentation().isEmpty()) {
- myActionsMgr->restoreCommandState();
- }
}
/*
QString aWchName = QString::fromStdString(theMessage->workbenchId());
QString aNestedFeatures = QString::fromStdString(theMessage->nestedFeatures());
bool isUsePropPanel = theMessage->isUseInput();
+ QString aId = QString::fromStdString(theMessage->id());
if (isSalomeMode()) {
- QString aId = QString::fromStdString(theMessage->id());
QAction* aAction = salomeConnector()->addFeature(aWchName,
aId,
QString::fromStdString(theMessage->text()),
aGroup = aPage->addGroup(aGroupName);
}
//Create feature...
- XGUI_Command* aCommand = aGroup->addFeature(QString::fromStdString(theMessage->id()),
+ XGUI_Command* aCommand = aGroup->addFeature(aId,
QString::fromStdString(theMessage->text()),
QString::fromStdString(theMessage->tooltip()),
QIcon(theMessage->icon().c_str()),
QKeySequence(), isUsePropPanel);
- aCommand->setUnblockableCommands(aNestedFeatures.split(" "));
+ aCommand->setNestedCommands(aNestedFeatures.split(" ", QString::SkipEmptyParts));
myActionsMgr->addCommand(aCommand);
myPartSetModule->featureCreated(aCommand);
}
tr("The document is modified, save before exit?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
if(anAnswer == QMessageBox::Save) {
- onSave();
+ bool saved = onSave();
+ if(!saved) {
+ return;
+ }
} else if (anAnswer == QMessageBox::Cancel) {
return;
}
return;
}
aDoc->close();
- myCurrentFile = "";
+ myCurrentDir = "";
}
//show file dialog, check if readable and open
- myCurrentFile = QFileDialog::getExistingDirectory(mainWindow());
- if(myCurrentFile.isEmpty())
+ myCurrentDir = QFileDialog::getExistingDirectory(mainWindow());
+ if(myCurrentDir.isEmpty())
return;
- QFileInfo aFileInfo(myCurrentFile);
+ QFileInfo aFileInfo(myCurrentDir);
if(!aFileInfo.exists() || !aFileInfo.isReadable()) {
QMessageBox::critical(myMainWindow, tr("Warning"), tr("Unable to open the file."));
- myCurrentFile = "";
+ myCurrentDir = "";
return;
}
QApplication::setOverrideCursor(Qt::WaitCursor);
- aDoc->load(myCurrentFile.toLatin1().constData());
+ aDoc->load(myCurrentDir.toLatin1().constData());
QApplication::restoreOverrideCursor();
updateCommandStatus();
}
//******************************************************
-void XGUI_Workshop::onSave()
+bool XGUI_Workshop::onSave()
{
- if(myCurrentFile.isEmpty()) {
- onSaveAs();
- return;
+ if(myCurrentDir.isEmpty()) {
+ return onSaveAs();
}
- saveDocument(myCurrentFile);
+ saveDocument(myCurrentDir);
updateCommandStatus();
+ return true;
}
//******************************************************
-void XGUI_Workshop::onSaveAs()
+bool XGUI_Workshop::onSaveAs()
{
- QString aTemp = myCurrentFile;
- myCurrentFile = QFileDialog::getSaveFileName(mainWindow());
- if(myCurrentFile.isEmpty()) {
- myCurrentFile = aTemp;
- return;
+ QFileDialog dialog(mainWindow());
+ dialog.setWindowTitle(tr("Select directory to save files..."));
+ dialog.setFileMode(QFileDialog::Directory);
+ dialog.setFilter(tr("Folders (*)"));
+ dialog.setOptions(QFileDialog::HideNameFilterDetails | QFileDialog::ShowDirsOnly);
+ dialog.setViewMode(QFileDialog::Detail);
+
+ if(!dialog.exec()) {
+ return false;
}
- QFileInfo aFileInfo(myCurrentFile);
- if(aFileInfo.exists() && !aFileInfo.isWritable()) {
- QMessageBox::critical(myMainWindow, tr("Warning"), tr("Unable to save the file."));
- return;
+ QString aTempDir = dialog.selectedFiles().first();
+ QDir aDir(aTempDir);
+ if(aDir.exists() && !aDir.entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries).isEmpty()) {
+ int answer = QMessageBox::question(myMainWindow,
+ //: Title of the dialog which asks user if he wants to save study in existing non-empty folder
+ tr("Save"),
+ tr("The folder already contains some files, save anyway?"),
+ QMessageBox::Save|QMessageBox::Cancel);
+ if(answer == QMessageBox::Cancel) {
+ return false;
+ }
}
- onSave();
+ myCurrentDir = aTempDir;
+ return onSave();
}
//******************************************************
if (!myPartSetModule)
return false;
myPartSetModule->createFeatures();
+ myActionsMgr->update();
return true;
}
aCmd->setEnabled(false);
}
}
+ myActionsMgr->update();
}
//******************************************************
QDockWidget* aObjDock = new QDockWidget(theParent);
aObjDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
aObjDock->setWindowTitle(tr("Object browser"));
+ aObjDock->setStyleSheet("::title { position: relative; padding-left: 5px; text-align: left center }");
myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock);
connect(myObjectBrowser, SIGNAL(activePartChanged(FeaturePtr)), this, SLOT(changeCurrentDocument(FeaturePtr)));
aObjDock->setWidget(myObjectBrowser);
{
PluginManagerPtr aMgr = ModelAPI_PluginManager::get();
if (thePart) {
- boost::shared_ptr<ModelAPI_AttributeDocRef> aDocRef = thePart->data()->docRef("PartDocument");
- if (aDocRef)
- aMgr->setCurrentDocument(aDocRef->value());
+ DocumentPtr aFeaDoc;
+ if (thePart->data()) {
+ aFeaDoc = thePart->data()->docRef("PartDocument")->value();
+ } else {
+ ObjectPtr aObject = boost::dynamic_pointer_cast<ModelAPI_Object>(thePart);
+ aFeaDoc = aObject->featureRef()->data()->docRef("PartDocument")->value();
+ }
+ if (aFeaDoc)
+ aMgr->setCurrentDocument(aFeaDoc);
} else {
aMgr->setCurrentDocument(aMgr->rootDocument());
}
tr("Seleted features will be deleted. Continue?"),
QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
if (aRes == QMessageBox::Yes) {
+ PluginManagerPtr aMgr = ModelAPI_PluginManager::get();
+ aMgr->rootDocument()->startOperation();
foreach (FeaturePtr aFeature, theList) {
- DocumentPtr aDoc = aFeature->data()->docRef("PartDocument")->value();
- aDoc->removeFeature(aFeature);
+ if (aFeature->getKind() == "Part") {
+ DocumentPtr aDoc;
+ if (aFeature->data()) {
+ aDoc = aFeature->data()->docRef("PartDocument")->value();
+ } else {
+ ObjectPtr aObject = boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature);
+ aDoc = aObject->featureRef()->data()->docRef("PartDocument")->value();
+ aFeature = aObject->featureRef();
+ }
+ if (aDoc == aMgr->currentDocument()) {
+ aDoc->close();
+ }
+ } else {
+ if (!aFeature->data()) {
+ ObjectPtr aObject = boost::dynamic_pointer_cast<ModelAPI_Object>(aFeature);
+ aFeature = aObject->featureRef();
+ }
+ }
+ aFeature->document()->removeFeature(aFeature);
}
+ aMgr->rootDocument()->finishOperation();
}
}
void onNew();
void onOpen();
- void onSave();
- void onSaveAs();
+ bool onSave();
+ bool onSaveAs();
void onExit();
void onUndo();
void onRedo();
// Creates Dock widgets: Object browser and Property panel
void createDockWidgets();
- QString myCurrentFile;
XGUI_MainWindow* myMainWindow;
XGUI_Module* myPartSetModule;
XGUI_ObjectsBrowser* myObjectBrowser;
XGUI_ViewerProxy* myViewerProxy;
XGUI_ContextMenuMgr* myContextMenuMgr;
+ QString myCurrentDir;
static QMap<QString, QString> myIcons;
};