From 2728f2367cc657e6a4c900ca221263ee9add26fd Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 16 Jul 2013 05:23:57 +0000 Subject: [PATCH] Initial version --- src/HYDROData/HYDROData_Document.cxx | 214 ++++++++++++++++++++++ src/HYDROData/HYDROData_Document.h | 107 +++++++++++ src/HYDROData/HYDROData_Image.h | 105 +++++++++++ src/HYDROData/HYDROData_Iterator.cxx | 61 ++++++ src/HYDROData/HYDROData_Object.h | 101 ++++++++++ src/HYDROData/test_HYDROData_Document.cxx | 90 +++++++++ src/HYDROData/test_HYDROData_Image.cxx | 151 +++++++++++++++ src/HYDROData/test_HYDROData_Main.cxx | 50 +++++ 8 files changed, 879 insertions(+) create mode 100644 src/HYDROData/HYDROData_Document.cxx create mode 100644 src/HYDROData/HYDROData_Document.h create mode 100644 src/HYDROData/HYDROData_Image.h create mode 100644 src/HYDROData/HYDROData_Iterator.cxx create mode 100644 src/HYDROData/HYDROData_Object.h create mode 100644 src/HYDROData/test_HYDROData_Document.cxx create mode 100644 src/HYDROData/test_HYDROData_Image.cxx create mode 100644 src/HYDROData/test_HYDROData_Main.cxx diff --git a/src/HYDROData/HYDROData_Document.cxx b/src/HYDROData/HYDROData_Document.cxx new file mode 100644 index 00000000..3960c4a4 --- /dev/null +++ b/src/HYDROData/HYDROData_Document.cxx @@ -0,0 +1,214 @@ +#include +#include +#include + +#include + +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); +} diff --git a/src/HYDROData/HYDROData_Document.h b/src/HYDROData/HYDROData_Document.h new file mode 100644 index 00000000..00a90729 --- /dev/null +++ b/src/HYDROData/HYDROData_Document.h @@ -0,0 +1,107 @@ +#ifndef HYDROData_Document_HeaderFile +#define HYDROData_Document_HeaderFile + +#include +#include + +#include + +/** + * 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 diff --git a/src/HYDROData/HYDROData_Image.h b/src/HYDROData/HYDROData_Image.h new file mode 100644 index 00000000..38e48c19 --- /dev/null +++ b/src/HYDROData/HYDROData_Image.h @@ -0,0 +1,105 @@ +#ifndef HYDROData_Image_HeaderFile +#define HYDROData_Image_HeaderFile + +#include + +#include +#include + +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 diff --git a/src/HYDROData/HYDROData_Iterator.cxx b/src/HYDROData/HYDROData_Iterator.cxx new file mode 100644 index 00000000..534cbd13 --- /dev/null +++ b/src/HYDROData/HYDROData_Iterator.cxx @@ -0,0 +1,61 @@ +#include + +#include + +#include +#include + +//! 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; +} diff --git a/src/HYDROData/HYDROData_Object.h b/src/HYDROData/HYDROData_Object.h new file mode 100644 index 00000000..852c0679 --- /dev/null +++ b/src/HYDROData/HYDROData_Object.h @@ -0,0 +1,101 @@ +#ifndef HYDROData_Object_HeaderFile +#define HYDROData_Object_HeaderFile + +#include + +#include +#include + +///! 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 diff --git a/src/HYDROData/test_HYDROData_Document.cxx b/src/HYDROData/test_HYDROData_Document.cxx new file mode 100644 index 00000000..9ec12219 --- /dev/null +++ b/src/HYDROData/test_HYDROData_Document.cxx @@ -0,0 +1,90 @@ +#include + +#include +#include + +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(); +} diff --git a/src/HYDROData/test_HYDROData_Image.cxx b/src/HYDROData/test_HYDROData_Image.cxx new file mode 100644 index 00000000..8e5d8ad8 --- /dev/null +++ b/src/HYDROData/test_HYDROData_Image.cxx @@ -0,0 +1,151 @@ +#include + +#include +#include +#include + +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(); +} diff --git a/src/HYDROData/test_HYDROData_Main.cxx b/src/HYDROData/test_HYDROData_Main.cxx new file mode 100644 index 00000000..67971549 --- /dev/null +++ b/src/HYDROData/test_HYDROData_Main.cxx @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#include + +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; +} -- 2.39.2