--- /dev/null
+#include <HYDROData_Document.h>
+#include <HYDROData_Application.h>
+#include <HYDROData_Iterator.h>
+
+#include <TDataStd_Integer.hxx>
+
+IMPLEMENT_STANDARD_HANDLE(HYDROData_Document,MMgt_TShared)
+IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Document,MMgt_TShared)
+
+static const int UNDO_LIMIT = 10; // number of possible undo operations in the module
+
+static const int TAG_PROPS = 1; // general properties tag
+static const int TAG_PROPS_NEW_ID = 1; // general properties: tag for storage of the new object ID
+static const int TAG_OBJECTS = 2; // tag of the objects sub-tree
+static const int TAG_HISTORY = 3; // tag of the history sub-tree (Root for History)
+
+using namespace std;
+
+Handle(HYDROData_Document) HYDROData_Document::Document(const int theStudyID)
+{
+ Handle(HYDROData_Document) aResult =
+ HYDROData_Application::GetApplication()->GetDocument(theStudyID);
+ if (aResult.IsNull()) {
+ aResult = new HYDROData_Document();
+ HYDROData_Application::GetApplication()->AddDocument(theStudyID, aResult);
+ }
+ return aResult;
+}
+
+bool HYDROData_Document::HasDocument(const int theStudyID)
+{
+ Handle(HYDROData_Document) aResult =
+ HYDROData_Application::GetApplication()->GetDocument(theStudyID);
+ return !aResult.IsNull();
+}
+
+Data_DocError HYDROData_Document::Load(const char* theFileName, const int theStudyID)
+{
+ Handle(TDocStd_Document) aResult;
+ TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
+ PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
+ try
+ {
+ aStatus = HYDROData_Application::GetApplication()->Open (aPath, aResult);
+ }
+ catch (Standard_Failure)
+ {}
+ if (!aResult.IsNull()) {
+ aResult->SetUndoLimit(UNDO_LIMIT);
+ HYDROData_Application::GetApplication()->AddDocument(theStudyID, new HYDROData_Document(aResult));
+ }
+ // recognize error
+ Data_DocError anError;
+ switch(aStatus) {
+ case PCDM_RS_OK:
+ anError = DocError_OK;
+ break;
+ case PCDM_RS_NoDriver:
+ case PCDM_RS_UnknownFileDriver:
+ case PCDM_RS_NoSchema:
+ case PCDM_RS_DriverFailure:
+ case PCDM_RS_WrongResource:
+ anError = DocError_ResourcesProblem;
+ break;
+ case PCDM_RS_OpenError:
+ case PCDM_RS_NoDocument:
+ case PCDM_RS_WrongStreamMode:
+ case PCDM_RS_PermissionDenied:
+ anError = DocError_CanNotOpen;
+ break;
+ case PCDM_RS_NoVersion:
+ anError = DocError_InvalidVersion;
+ break;
+ case PCDM_RS_ExtensionFailure:
+ case PCDM_RS_FormatFailure:
+ case PCDM_RS_TypeFailure:
+ case PCDM_RS_TypeNotFoundInSchema:
+ case PCDM_RS_UnrecognizedFileFormat:
+ anError = DocError_InvalidFormat;
+ break;
+ case PCDM_RS_MakeFailure:
+ default:
+ anError = DocError_UnknownProblem;
+ break;
+ }
+ return anError;
+}
+
+Data_DocError HYDROData_Document::Save(const char* theFileName)
+{
+ TCollection_ExtendedString aPath ((const Standard_CString)theFileName);
+ PCDM_StoreStatus aStatus;
+ try {
+ aStatus = HYDROData_Application::GetApplication()->SaveAs (myDoc, aPath);
+ }
+ catch (Standard_Failure) {}
+ myTransactionsAfterSave = 0;
+ Standard::Purge(); // Release free memory
+
+ // recognize error
+ Data_DocError anError;
+ switch(aStatus) {
+ case PCDM_SS_OK:
+ anError = DocError_OK;
+ break;
+ case PCDM_SS_DriverFailure:
+ anError = DocError_ResourcesProblem;
+ break;
+ case PCDM_SS_WriteFailure:
+ case PCDM_SS_DiskWritingFailure:
+ case PCDM_SS_UserRightsFailure:
+ anError = DocError_CanNotOpen;
+ break;
+ default:
+ anError = DocError_UnknownProblem;
+ break;
+ }
+ return anError;
+}
+
+void HYDROData_Document::Close()
+{
+ myDoc->Close();
+ HYDROData_Application::GetApplication()->RemoveDocument(this);
+}
+
+void HYDROData_Document::StartOperation()
+{
+ myDoc->NewCommand();
+}
+
+void HYDROData_Document::CommitOperation()
+{
+ myDoc->CommitCommand();
+ myTransactionsAfterSave++;
+}
+
+void HYDROData_Document::AbortOperation()
+{
+ myDoc->AbortCommand();
+}
+
+bool HYDROData_Document::IsOperation()
+{
+ return myDoc->HasOpenCommand() != 0;
+}
+
+bool HYDROData_Document::IsModified()
+{
+ return myTransactionsAfterSave != 0;
+}
+
+bool HYDROData_Document::CanUndo()
+{
+ return myDoc->GetAvailableUndos() > 0;
+}
+
+void HYDROData_Document::Undo()
+{
+ myDoc->Undo();
+ myTransactionsAfterSave--;
+}
+
+bool HYDROData_Document::CanRedo()
+{
+ return myDoc->GetAvailableRedos() > 0;
+}
+
+void HYDROData_Document::Redo()
+{
+ myDoc->Redo();
+ myTransactionsAfterSave++;
+}
+
+Handle_HYDROData_Object HYDROData_Document::CreateObject(const ObjectKind theKind)
+{
+ return HYDROData_Iterator::CreateObject(this, theKind);
+}
+
+HYDROData_Document::HYDROData_Document()
+{
+ HYDROData_Application::GetApplication()->NewDocument("BinOcaf", myDoc);
+ myDoc->SetUndoLimit(UNDO_LIMIT);
+ NewID(); // needed to have at least one attribute in initial document to avoid errors
+ myTransactionsAfterSave = 0;
+}
+
+HYDROData_Document::HYDROData_Document(const Handle(TDocStd_Document)& theDoc)
+{
+ myDoc = theDoc;
+ myTransactionsAfterSave = 0;
+}
+
+HYDROData_Document::~HYDROData_Document()
+{
+}
+
+int HYDROData_Document::NewID()
+{
+ TDF_Label anIDLab = myDoc->Main().FindChild(TAG_PROPS).
+ FindChild(TAG_PROPS_NEW_ID);
+ Handle(TDataStd_Integer) anInt;
+ if (!anIDLab.FindAttribute(TDataStd_Integer::GetID(), anInt)) {
+ anInt = TDataStd_Integer::Set(anIDLab, 0);
+ }
+ // just increment value and return
+ anInt->Set(anInt->Get() + 1);
+ return anInt->Get();
+}
+
+TDF_Label HYDROData_Document::LabelOfObjects()
+{
+ return myDoc->Main().FindChild(TAG_OBJECTS);
+}
--- /dev/null
+#ifndef HYDROData_Document_HeaderFile
+#define HYDROData_Document_HeaderFile
+
+#include <HYDROData.h>
+#include <HYDROData_Object.h>
+
+#include <TDocStd_Document.hxx>
+
+/**
+ * Errors that could appear on document open/save actions.
+ * If there is no error, it is "OK".
+ */
+enum Data_DocError {
+ DocError_OK = 0, ///< success
+ DocError_ResourcesProblem, ///< resources files are invalid or not found
+ DocError_CanNotOpen, ///< can not open file for reading or writing
+ DocError_InvalidVersion, ///< version of document is different than expected
+ DocError_InvalidFormat, ///< format of the document is bad
+ DocError_UnknownProblem ///< problem has unknown nature
+};
+
+DEFINE_STANDARD_HANDLE(HYDROData_Document, MMgt_TShared)
+
+/**\class HYDROData_Document
+ *
+ * \brief Document for internal data structure of any object storage. Corresponds to the SALOME study.
+ *
+ * Document contains all data of the Study specific to this module.
+ * Also it provides acces to this data: open/save, transactions management etc.
+ * to provide access to all stored data.
+ */
+
+class HYDROData_Document : public MMgt_TShared
+{
+public:
+
+ DEFINE_STANDARD_RTTI(HYDROData_Document);
+
+ //! Returns the existing document or creates new if it is not exist
+ HYDRODATA_EXPORT static Handle(HYDROData_Document) Document(const int theStudyID);
+
+ //! Returns true if data model contains document for this study
+ HYDRODATA_EXPORT static bool HasDocument(const int theStudyID);
+
+ //! Loads the OCAF document from the file.
+ //! \param theFileName full name of the file to load
+ //! \param theStudyID identifier of the SALOME study to associate with loaded file
+ //! \returns error status (OK in case of success)
+ HYDRODATA_EXPORT static Data_DocError Load(const char* theFileName, const int theStudyID);
+
+ //! Saves the OCAF document to the file.
+ //! \param theFileName full name of the file to store
+ //! \returns error status (OK in case of success)
+ HYDRODATA_EXPORT Data_DocError Save(const char* theFileName);
+
+ //! Removes document data
+ HYDRODATA_EXPORT void Close();
+
+ //! Starts a new operation (opens a tansaction)
+ HYDRODATA_EXPORT void StartOperation();
+ //! Finishes the previously started operation (closes the transaction)
+ HYDRODATA_EXPORT void CommitOperation();
+ //! Aborts the operation
+ HYDRODATA_EXPORT void AbortOperation();
+ //! Returns true if operation has been started, but not yet finished or aborted
+ HYDRODATA_EXPORT bool IsOperation();
+ //! Returns true if document was modified (since creation/opening)
+ HYDRODATA_EXPORT bool IsModified();
+
+ //! Returns True if there are available Undos
+ HYDRODATA_EXPORT bool CanUndo();
+ //! Undoes last operation
+ HYDRODATA_EXPORT void Undo();
+ //! Returns True if there are available Redos
+ HYDRODATA_EXPORT bool CanRedo();
+ //! Redoes last operation
+ HYDRODATA_EXPORT void Redo();
+
+ //! Creates and locates in the document a new object
+ //! \param theKind kind of the created object, can not be UNKNOWN
+ //! \returns the created object
+ HYDRODATA_EXPORT Handle_HYDROData_Object CreateObject(const ObjectKind theKind);
+
+protected:
+
+ friend class HYDROData_Iterator;
+ friend class test_HYDROData_Document;
+
+ //! Creates new document: private because "Document" method must be used instead of direct creation.
+ HYDROData_Document();
+ //! Creates new document by existing OCAF structure
+ HYDROData_Document(const Handle(TDocStd_Document)& theDoc);
+ //! Deletes all high-level data, managed this document
+ ~HYDROData_Document();
+
+ //! Returns the new identifier of the new object (may be used for correct ordering of objects)
+ HYDRODATA_EXPORT int NewID();
+
+ //! Returns the label where the objects are located (used by Iterator)
+ TDF_Label LabelOfObjects();
+
+private:
+ Handle(TDocStd_Document) myDoc; ///< OCAF document instance corresponding for keeping all persistent data
+ int myTransactionsAfterSave; ///< number of transactions after the last "save" call, used for "IsModified" method
+};
+
+#endif
--- /dev/null
+#ifndef HYDROData_Image_HeaderFile
+#define HYDROData_Image_HeaderFile
+
+#include <HYDROData_Object.h>
+
+#include <QImage>
+#include <QTransform>
+
+DEFINE_STANDARD_HANDLE(HYDROData_Image, HYDROData_Object)
+
+/**\class HYDROData_Image
+ * \brief Class that stores/retreives information about the image.
+ *
+ * Keeps image as binary array, transformation and other properties
+ * of image with correspondent API for forkind wit hthese properties.
+ */
+class HYDROData_Image : public HYDROData_Object
+{
+public:
+ DEFINE_STANDARD_RTTI(HYDROData_Image);
+
+ /**
+ * Returns the kind of this object. Must be redefined in all objects of known type.
+ */
+ HYDRODATA_EXPORT virtual const ObjectKind GetKind() const {return KIND_IMAGE;}
+
+ /**
+ * Stores the image
+ * \param theImage new image
+ */
+ HYDRODATA_EXPORT void SetImage(const QImage& theImage);
+
+ /**
+ * Returns the kept image
+ */
+ HYDRODATA_EXPORT QImage Image();
+
+ /**
+ * Stores the image transformation
+ * \param theTrsf new transformation
+ */
+ HYDRODATA_EXPORT void SetTrsf(const QTransform& theTrsf);
+
+ /**
+ * Returns the kept transformation, or "identity" if not yet stored
+ */
+ HYDRODATA_EXPORT QTransform Trsf();
+
+ /**
+ * Appends reference to other image.
+ * \param theReferenced the image referenced by this
+ */
+ HYDRODATA_EXPORT void AppendReference(Handle(HYDROData_Image) theReferenced);
+
+ /**
+ * Returns the number of referenced images
+ * \return zero if there is no references
+ */
+ HYDRODATA_EXPORT int NbReferences();
+
+ /**
+ * Returns reference by index.
+ * \param theIndex number of reference [0; NbReference)
+ * \returns the referenced image, or Null if index is invalid
+ */
+ HYDRODATA_EXPORT Handle(HYDROData_Image) Reference(const int theIndex) const;
+
+ /**
+ * Updates reference by index. If index is one-bigger than \a NbReferences,
+ * this method appends it to the end (NbReferences is incremented).
+ * \param theIndex number of reference [0; NbReference]
+ * \param theReferenced the image referenced by this
+ */
+ HYDRODATA_EXPORT void ChangeReference(
+ const int theIndex, Handle(HYDROData_Image) theReferenced);
+
+ /**
+ * Removes reference by index
+ * \param theIndex number of reference [0; NbReference)
+ */
+ HYDRODATA_EXPORT void RemoveReference(const int theIndex);
+
+ /**
+ * Removes all references.
+ */
+ HYDRODATA_EXPORT void ClearReferences();
+
+protected:
+
+ friend class HYDROData_Iterator;
+
+ /**
+ * Creates new object in the internal data structure. Use higher level objects
+ * to create objects with real content.
+ */
+ HYDROData_Image();
+
+ /**
+ * Destructs properties of the object and object itself, removes it from the document.
+ */
+ ~HYDROData_Image();
+
+};
+
+#endif
--- /dev/null
+#include <HYDROData_Iterator.h>
+
+#include <HYDROData_Image.h>
+
+#include <TDataStd_Name.hxx>
+#include <NCollection_DataMap.hxx>
+
+//! Returns label by root objects kind and the kind of the object
+static TDF_Label GetLabelByKind(TDF_Label theRoot, ObjectKind theKind)
+{
+ if (theKind == KIND_UNKNOWN) return theRoot;
+ return theRoot.FindChild(theKind);
+}
+
+HYDROData_Iterator::HYDROData_Iterator(Handle(HYDROData_Document) theDoc, ObjectKind theKind)
+ : myIter(GetLabelByKind(theDoc->LabelOfObjects(), theKind),
+ TDataStd_Name::GetID(), theKind == KIND_UNKNOWN) // iterate all sub-objects for unknown kind
+{
+}
+
+void HYDROData_Iterator::Next()
+{
+ myIter.Next();
+ // omit the properties iteration in case of UNKNOWN kind filtering
+ while(myIter.More() && myIter.Value()->Label().Depth() != 4)
+ myIter.Next();
+}
+
+bool HYDROData_Iterator::More() const
+{
+ return myIter.More();
+}
+
+Handle(HYDROData_Object) HYDROData_Iterator::Current()
+{
+ return Object(myIter.Value()->Label());
+}
+
+Handle_HYDROData_Object HYDROData_Iterator::CreateObject(
+ Handle(HYDROData_Document) theDoc, ObjectKind theKind)
+{
+ TDF_Label aNewLab = GetLabelByKind(theDoc->LabelOfObjects(), theKind).
+ FindChild(theDoc->NewID());
+ // object exists if there is name attribute
+ TDataStd_Name::Set(aNewLab, TCollection_ExtendedString(""));
+ return Object(aNewLab);
+}
+
+Handle_HYDROData_Object HYDROData_Iterator::Object(const TDF_Label theLabel)
+{
+ ObjectKind aKind = theLabel.Father().Tag();
+ Handle(HYDROData_Object) aResult;
+ switch(aKind) {
+ case KIND_IMAGE:
+ aResult = new HYDROData_Image();
+ break;
+ }
+ if (!aResult.IsNull())
+ aResult->SetLabel(theLabel);
+ return aResult;
+}
--- /dev/null
+#ifndef HYDROData_Object_HeaderFile
+#define HYDROData_Object_HeaderFile
+
+#include <HYDROData.h>
+
+#include <TDF_Label.hxx>
+#include <QString>
+
+///! Kind of an object in a document
+typedef int ObjectKind;
+///! Unrecognized object
+const ObjectKind KIND_UNKNOWN = 0;
+const ObjectKind KIND_IMAGE = 1;
+
+DEFINE_STANDARD_HANDLE(HYDROData_Object, MMgt_TShared)
+
+/**\class HYDROData_Object
+ * \brief Generic class of any object in the data model.
+ *
+ * Interface for getting access to the object that belong to the data model.
+ * Managed by Document. Provides access to the common properties:
+ * kind of an object, name.
+ */
+class HYDROData_Object : public MMgt_TShared
+{
+public:
+ DEFINE_STANDARD_RTTI(HYDROData_Object);
+
+ /**
+ * Returns the kind of this object. Must be redefined in all objects of known type.
+ */
+ HYDRODATA_EXPORT virtual const ObjectKind GetKind() const {return KIND_UNKNOWN;}
+
+ /**
+ * Returns the name of this object.
+ */
+ HYDRODATA_EXPORT QString GetName() const;
+
+ /**
+ * Updates the name of this object.
+ */
+ HYDRODATA_EXPORT void SetName(const QString& theName);
+
+ /**
+ * Checks is object exists in the data structure.
+ * \returns true is object is not exists in the data model
+ */
+ HYDRODATA_EXPORT bool IsRemoved() const;
+
+ /**
+ * Removes object from the data structure.
+ */
+ HYDRODATA_EXPORT void Remove();
+
+ /**
+ * Returns unique integer identifier of the object (may be used for ordering of objects)
+ */
+ HYDRODATA_EXPORT inline int ID() const {return myLab.Tag();}
+
+ /**
+ * Copies all properties of this to the destinated object.
+ * Objects must be the same type.
+ * \param theDestination initialized object (from any document) - target of copying
+ */
+ HYDRODATA_EXPORT void CopyTo(Handle_HYDROData_Object theDestination) const;
+
+protected:
+
+ friend class HYDROData_Iterator;
+
+ /**
+ * Creates new object in the internal data structure. Use higher level objects
+ * to create objects with real content.
+ */
+ HYDRODATA_EXPORT HYDROData_Object();
+
+ /**
+ * Destructs properties of the object and object itself, removes it from the document.
+ */
+ virtual HYDRODATA_EXPORT ~HYDROData_Object();
+
+ /**
+ * Put the object to the label of the document.
+ * \param theLabel new label of the object
+ */
+ HYDRODATA_EXPORT virtual void SetLabel(TDF_Label theLabel);
+
+ /**
+ * Returns the label of this object.
+ */
+ TDF_Label& Label() {return myLab;}
+
+protected:
+ /// Array of pointers to the properties of this object; index in this array is returned by \a AddProperty.
+ TDF_Label myLab; ///< label of this object
+};
+
+///! Is Equal for HYDROData_Object mapping
+HYDRODATA_EXPORT bool IsEqual(const Handle_HYDROData_Object& theObj1, const Handle_HYDROData_Object& theObj2);
+
+#endif
--- /dev/null
+#include<test_HYDROData_Document.h>
+
+#include <HYDROData_Document.h>
+#include <QFile>
+
+void test_HYDROData_Document::testSaveOpen()
+{
+ // temporarly created file name (in the current directory)
+ const char* aTestFile = "TestDoc.cbf";
+ // save
+ Handle(HYDROData_Document) aDoc = HYDROData_Document::Document(1);
+ CPPUNIT_ASSERT(!aDoc.IsNull());
+ // keep some saved information to check after retreive
+ aDoc->NewID();
+ int anID = aDoc->NewID();
+ Data_DocError aStatus = aDoc->Save(aTestFile);
+ CPPUNIT_ASSERT(aStatus == DocError_OK);
+ aDoc->Close();
+ CPPUNIT_ASSERT(!HYDROData_Document::HasDocument(1));
+
+ // open
+ aStatus = HYDROData_Document::Load(aTestFile, 2);
+ CPPUNIT_ASSERT(aStatus == DocError_OK);
+ CPPUNIT_ASSERT(HYDROData_Document::HasDocument(2));
+ aDoc = HYDROData_Document::Document(2);
+ CPPUNIT_ASSERT(!aDoc.IsNull());
+ // check that retreived correctly
+ CPPUNIT_ASSERT(aDoc->NewID() == anID + 1);
+
+ // remove the created file using Qt functionality
+ QFile aFile(aTestFile);
+ aFile.remove();
+
+ aDoc->Close();
+}
+
+void test_HYDROData_Document::testOperations()
+{
+ Handle(HYDROData_Document) aDoc = HYDROData_Document::Document(1);
+ CPPUNIT_ASSERT(!aDoc.IsNull());
+ CPPUNIT_ASSERT(!aDoc->IsOperation());
+ CPPUNIT_ASSERT(!aDoc->IsModified());
+ // commit operation
+ aDoc->StartOperation();
+ CPPUNIT_ASSERT(aDoc->IsOperation());
+ int anID = aDoc->NewID();
+ aDoc->CommitOperation();
+ CPPUNIT_ASSERT(!aDoc->IsOperation());
+ CPPUNIT_ASSERT(aDoc->IsModified());
+ // abort operation
+ aDoc->StartOperation();
+ CPPUNIT_ASSERT(aDoc->IsOperation());
+ int anIDAborted = aDoc->NewID();
+ aDoc->AbortOperation();
+ CPPUNIT_ASSERT(!aDoc->IsOperation());
+ CPPUNIT_ASSERT(aDoc->IsModified());
+
+ CPPUNIT_ASSERT(anID + 1 == aDoc->NewID());
+
+ aDoc->Close();
+}
+
+void test_HYDROData_Document::testUndoRedo()
+{
+ Handle(HYDROData_Document) aDoc = HYDROData_Document::Document(1);
+ CPPUNIT_ASSERT(!aDoc.IsNull());
+ CPPUNIT_ASSERT(!aDoc->CanUndo());
+ CPPUNIT_ASSERT(!aDoc->CanRedo());
+ // commit operation
+ aDoc->StartOperation();
+ CPPUNIT_ASSERT(aDoc->IsOperation());
+ int anID = aDoc->NewID();
+ aDoc->CommitOperation();
+ CPPUNIT_ASSERT(aDoc->CanUndo());
+ CPPUNIT_ASSERT(!aDoc->CanRedo());
+ CPPUNIT_ASSERT(aDoc->IsModified());
+ // undo
+ aDoc->Undo();
+ CPPUNIT_ASSERT(!aDoc->CanUndo());
+ CPPUNIT_ASSERT(aDoc->CanRedo());
+ CPPUNIT_ASSERT(anID == aDoc->NewID());
+ CPPUNIT_ASSERT(!aDoc->IsModified());
+ // redo
+ aDoc->Redo();
+ CPPUNIT_ASSERT(aDoc->CanUndo());
+ CPPUNIT_ASSERT(!aDoc->CanRedo());
+ CPPUNIT_ASSERT(aDoc->IsModified());
+
+ aDoc->Close();
+}
--- /dev/null
+#include<test_HYDROData_Image.h>
+
+#include <HYDROData_Document.h>
+#include <HYDROData_Image.h>
+#include <QPainter>
+
+static QImage TestImage() {
+ QImage aPic(50, 40, QImage::Format_RGB32);
+ QPainter aPainter(&aPic);
+ aPainter.drawEllipse(6, 7, 38, 30);
+ aPainter.drawLine(0, 40, 10, 0);
+ aPainter.drawLine(10, 0, 25, 35);
+ aPainter.drawLine(25, 35, 40, 0);
+ aPainter.drawLine(40, 0, 50, 40);
+ return aPic;
+}
+
+void test_HYDROData_Image::testQImage()
+{
+ Handle(HYDROData_Document) aDoc = HYDROData_Document::Document(1);
+
+ Handle(HYDROData_Image) anImage =
+ Handle(HYDROData_Image)::DownCast(aDoc->CreateObject(KIND_IMAGE));
+ // empty image
+ QImage anEmpty = anImage->Image();
+ CPPUNIT_ASSERT(anEmpty.isNull());
+
+ // prepare Qt Image for testing
+ QImage aPic(TestImage());
+ anImage->SetImage(aPic);
+ QImage aRestored = anImage->Image();
+
+ CPPUNIT_ASSERT(!aRestored.isNull());
+ //aRestored.save("pic2.bmp");
+ CPPUNIT_ASSERT(aPic == aRestored);
+
+ aDoc->Close();
+}
+
+void test_HYDROData_Image::testTrsf()
+{
+ Handle(HYDROData_Document) aDoc = HYDROData_Document::Document(1);
+
+ Handle(HYDROData_Image) anImage =
+ Handle(HYDROData_Image)::DownCast(aDoc->CreateObject(KIND_IMAGE));
+ // empty trsf
+ QTransform anEmpty = anImage->Trsf();
+ CPPUNIT_ASSERT(anEmpty.isIdentity());
+
+ // prepare Qt transformation for testing
+ QTransform aTrsf;
+ aTrsf.translate(50, 50);
+ aTrsf.rotate(45);
+ aTrsf.scale(0.5, 1.0);
+
+ anImage->SetTrsf(aTrsf);
+ QTransform aRestored = anImage->Trsf();
+
+ CPPUNIT_ASSERT(!aRestored.isIdentity());
+ CPPUNIT_ASSERT(aTrsf == aRestored);
+
+ aDoc->Close();
+}
+
+void test_HYDROData_Image::testReferences()
+{
+ Handle(HYDROData_Document) aDoc = HYDROData_Document::Document(1);
+
+ Handle(HYDROData_Image) anImage1 =
+ Handle(HYDROData_Image)::DownCast(aDoc->CreateObject(KIND_IMAGE));
+ Handle(HYDROData_Image) anImage2 =
+ Handle(HYDROData_Image)::DownCast(aDoc->CreateObject(KIND_IMAGE));
+ Handle(HYDROData_Image) anImage3 =
+ Handle(HYDROData_Image)::DownCast(aDoc->CreateObject(KIND_IMAGE));
+
+ CPPUNIT_ASSERT(anImage1->ID() != anImage2->ID());
+ CPPUNIT_ASSERT(anImage2->ID() != anImage3->ID());
+
+ // check initially there is no references
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 0);
+
+ // append reference
+ anImage3->AppendReference(anImage1);
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 1);
+ CPPUNIT_ASSERT(IsEqual(anImage3->Reference(0), anImage1));
+
+ // change reference
+ anImage3->ChangeReference(0, anImage2);
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 1);
+ CPPUNIT_ASSERT(IsEqual(anImage3->Reference(0), anImage2));
+
+ // append one more reference
+ anImage3->AppendReference(anImage1);
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 2);
+ CPPUNIT_ASSERT(IsEqual(anImage3->Reference(0), anImage2));
+ CPPUNIT_ASSERT(IsEqual(anImage3->Reference(1), anImage1));
+
+ // remove reference
+ anImage3->RemoveReference(0);
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 1);
+ CPPUNIT_ASSERT(IsEqual(anImage3->Reference(0), anImage1));
+
+ // remove reference
+ anImage3->RemoveReference(0);
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 0);
+
+ // append two references once again and remove all references
+ anImage3->ChangeReference(0, anImage1);
+ anImage3->ChangeReference(1, anImage2);
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 2);
+ CPPUNIT_ASSERT(IsEqual(anImage3->Reference(0), anImage1));
+ CPPUNIT_ASSERT(IsEqual(anImage3->Reference(1), anImage2));
+ anImage3->ClearReferences();
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 0);
+
+ aDoc->Close();
+}
+
+void test_HYDROData_Image::testCopy()
+{
+ Handle(HYDROData_Document) aDoc = HYDROData_Document::Document(1);
+
+ Handle(HYDROData_Image) anImage1 =
+ Handle(HYDROData_Image)::DownCast(aDoc->CreateObject(KIND_IMAGE));
+ // fill image 1
+ anImage1->SetImage(TestImage());
+
+ QTransform aTrsf;
+ aTrsf.translate(50, 50);
+ aTrsf.rotate(45);
+ aTrsf.scale(0.5, 1.0);
+ anImage1->SetTrsf(aTrsf);
+
+ Handle(HYDROData_Image) anImage2 =
+ Handle(HYDROData_Image)::DownCast(aDoc->CreateObject(KIND_IMAGE));
+
+ anImage1->AppendReference(anImage2);
+
+ // copy image to the new one
+ Handle(HYDROData_Image) anImage3 =
+ Handle(HYDROData_Image)::DownCast(aDoc->CreateObject(KIND_IMAGE));
+ anImage1->CopyTo(anImage3);
+
+ // check all fields are correctly copied
+ CPPUNIT_ASSERT(anImage1->Image() == anImage3->Image());
+ CPPUNIT_ASSERT(anImage1->Trsf() == anImage3->Trsf());
+ CPPUNIT_ASSERT_EQUAL(anImage3->NbReferences(), 1);
+ CPPUNIT_ASSERT(IsEqual(anImage3->Reference(0), anImage2));
+
+ aDoc->Close();
+}
--- /dev/null
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TextTestProgressListener.h>
+#include <stdexcept>
+
+int
+ main( int argc, char* argv[] )
+{
+ std::string testPath = (argc > 1) ? std::string(argv[1]) : "";
+
+ // Create the event manager and test controller
+ CppUnit::TestResult controller;
+
+ // Add a listener that colllects test result
+ CppUnit::TestResultCollector result;
+ controller.addListener( &result );
+
+ // Add a listener that print dots as test run.
+ CppUnit::TextTestProgressListener progress;
+ controller.addListener( &progress );
+
+ CppUnit::TestFactoryRegistry& registry =
+ CppUnit::TestFactoryRegistry::getRegistry();
+ // Add the top suite to the test runner
+ CppUnit::TestRunner runner;
+ runner.addTest( registry.makeTest() );
+ try
+ {
+ std::cout << "Running " << testPath;
+ runner.run( controller, testPath );
+
+ std::cerr << std::endl;
+
+ // Print test in a compiler compatible format.
+ CppUnit::CompilerOutputter outputter( &result, std::cerr );
+ outputter.write();
+ }
+ catch ( std::invalid_argument &e ) // Test path not resolved
+ {
+ std::cerr << std::endl
+ << "ERROR: " << e.what()
+ << std::endl;
+ return 0;
+ }
+
+ return result.wasSuccessful() ? 0 : 1;
+}