0025149: Samples - add Qt5/QML sample for Android 4.x
authoribs <ibs@opencascade.com>
Fri, 3 Oct 2014 10:11:30 +0000 (14:11 +0400)
committerbugmaster <bugmaster@opencascade.com>
Fri, 7 Nov 2014 14:53:52 +0000 (17:53 +0300)
28 files changed:
dox/FILES_HTML.txt
dox/overview/images/samples_java_android_occt.jpg [new file with mode: 0644]
dox/overview/images/samples_qml_android_occt.jpg [new file with mode: 0644]
dox/overview/overview.md
samples/qt/AndroidQt/.gitignore [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt.cxx [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt.h [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt.pro [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt.qrc [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt_TouchParameters.cxx [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt_TouchParameters.h [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt_UserInteractionParameters.h [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt_Window.cxx [new file with mode: 0644]
samples/qt/AndroidQt/AndroidQt_Window.h [new file with mode: 0644]
samples/qt/AndroidQt/Deployment.pri [new file with mode: 0644]
samples/qt/AndroidQt/Main.cxx [new file with mode: 0644]
samples/qt/AndroidQt/OCCT.pri [new file with mode: 0644]
samples/qt/AndroidQt/ReadMe.md [new file with mode: 0644]
samples/qt/AndroidQt/android/AndroidManifest.xml [new file with mode: 0644]
samples/qt/AndroidQt/android/assets/opencascade/shared/.gitignore [new file with mode: 0644]
samples/qt/AndroidQt/android/res/drawable-hdpi/ic_launcher.png [new file with mode: 0644]
samples/qt/AndroidQt/android/res/drawable-mdpi/ic_launcher.png [new file with mode: 0644]
samples/qt/AndroidQt/android/res/drawable-xhdpi/ic_launcher.png [new file with mode: 0644]
samples/qt/AndroidQt/android/res/drawable-xxhdpi/ic_launcher.png [new file with mode: 0644]
samples/qt/AndroidQt/android/res/values/strings.xml [new file with mode: 0644]
samples/qt/AndroidQt/android/src/org/qtproject/example/AndroidQt/AndroidQt.java [new file with mode: 0644]
samples/qt/AndroidQt/res/icons/ic_action_collection.png [new file with mode: 0644]
samples/qt/AndroidQt/res/qml/main.qml [new file with mode: 0644]

index 6cc2a4a..3e7f0e7 100644 (file)
@@ -11,6 +11,9 @@ overview/overview.md
 ../samples/CSharp/ReadMe.md
 ../samples/CSharp/ReadMe_D3D.md
 
+../samples/qt/AndroidQt/ReadMe.md
+../samples/java/jniviewer/ReadMe.md
+
 tutorial/tutorial.md
 
 technical_overview/technical_overview.md
diff --git a/dox/overview/images/samples_java_android_occt.jpg b/dox/overview/images/samples_java_android_occt.jpg
new file mode 100644 (file)
index 0000000..ecba473
Binary files /dev/null and b/dox/overview/images/samples_java_android_occt.jpg differ
diff --git a/dox/overview/images/samples_qml_android_occt.jpg b/dox/overview/images/samples_qml_android_occt.jpg
new file mode 100644 (file)
index 0000000..3fbdbd3
Binary files /dev/null and b/dox/overview/images/samples_qml_android_occt.jpg differ
index a2f3932..2608d9d 100644 (file)
@@ -620,3 +620,16 @@ There is also another C# example with the same functionality, which demonstrates
 
 See \subpage samples_csharp_direct3d "Readme" for details.
 
+@subsubsection OCCT_OVW_SECTION_7_3_4 Android
+
+There are two samples are representing usage OCCT framework on Android mobile platform. They represent an OCCT-based 3D-viewer with CAD import support in formats BREP, STEP and IGES: jniviewer (java) and AndroidQt (qt+qml)
+
+jniviewer
+@image html /overview/images/samples_java_android_occt.jpg
+@image latex /overview/images/samples_java_android_occt.jpg
+Java - See \subpage samples_java_android_occt "Readme" for details.
+
+AndroidQt
+@image html /overview/images/samples_qml_android_occt.jpg
+@image latex /overview/images/samples_qml_android_occt.jpg
+Qt - See \subpage samples_qml_android_occt "Readme" for details.
diff --git a/samples/qt/AndroidQt/.gitignore b/samples/qt/AndroidQt/.gitignore
new file mode 100644 (file)
index 0000000..2c0f0cc
--- /dev/null
@@ -0,0 +1,2 @@
+3rdparty
+occt
\ No newline at end of file
diff --git a/samples/qt/AndroidQt/AndroidQt.cxx b/samples/qt/AndroidQt/AndroidQt.cxx
new file mode 100644 (file)
index 0000000..927c6f0
--- /dev/null
@@ -0,0 +1,292 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AndroidQt_Window.h>
+#include <AndroidQt.h>
+#include <AndroidQt_UserInteractionParameters.h>
+
+#include <AIS_Shape.hxx>
+#include <BRepTools.hxx>
+#include <BRep_Builder.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <Quantity_Color.hxx>
+#include <Standard_ErrorHandler.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
+#include <UnitsAPI.hxx>
+
+#include <EGL/egl.h>
+#include <QFileInfo>
+
+// =======================================================================
+// function : AndroidQt
+// purpose  :
+// =======================================================================
+AndroidQt::AndroidQt()
+: myFitAllAction (false)
+{
+  connect (this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
+
+  // set shaders location variable
+  QByteArray aDataRoot = "/data/data/org.qtproject.example.AndroidQt/files/opencascade/shared";
+  qputenv ("CSF_ShadersDirectory", aDataRoot + "/Shaders");
+}
+
+// =======================================================================
+// function : ReadShapeFromFile
+// purpose  :
+// =======================================================================
+bool AndroidQt::ReadShapeFromFile (QString theFilePath)
+{
+  QUrl    aFileUrl   (theFilePath);
+  QString aFilePath = theFilePath;
+  if (aFileUrl.isLocalFile())
+  {
+    aFilePath = QUrl (theFilePath).toLocalFile();
+  }
+
+  if (!QFile (aFilePath).exists())
+  {
+    return false;
+  }
+
+  TopoDS_Shape aShape;
+  BRep_Builder aBuildTool;
+  try
+  {
+    OCC_CATCH_SIGNALS
+
+    if (!BRepTools::Read (aShape, aFilePath.toStdString().c_str(), aBuildTool))
+    {
+      return false;
+    }
+
+    if (!myContext.IsNull())
+    {
+      myContext->EraseAll (Standard_False);
+
+      Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape);
+      aShapePrs->SetColor (Quantity_Color(1.0, 0.73, 0.2, Quantity_TOC_RGB));
+
+      myContext->Display        (aShapePrs, Standard_False);
+      myContext->SetDisplayMode (aShapePrs, AIS_Shaded, Standard_False);
+    }
+
+    myMutex.lock();
+    myFitAllAction = true;
+    myMutex.unlock();
+
+    if (window())
+    {
+      window()->update();
+    }
+  }
+  catch (Standard_Failure)
+  {
+    return false;
+  }
+
+  return true;
+}
+
+// =======================================================================
+// function : InitTouch
+// purpose  :
+// =======================================================================
+void AndroidQt::InitTouch (const double theX,
+                           const double theY)
+{
+  myMutex.lock();
+  myTouchPoint.SetStarts (theX, theY);
+  myMutex.unlock();
+}
+
+// =======================================================================
+// function : UpdateTouch
+// purpose  :
+// =======================================================================
+void AndroidQt::UpdateTouch (const double theX,
+                             const double theY)
+{
+  myMutex.lock();
+  myTouchPoint.SetEnds (theX, theY);
+  myMutex.unlock();
+
+  if (window())
+    window()->update();
+}
+
+// =======================================================================
+// function : handleWindowChanged
+// purpose  :
+// =======================================================================
+void AndroidQt::handleWindowChanged (QQuickWindow* theWin)
+{
+  if (theWin == NULL)
+  {
+    return;
+  }
+
+  connect(theWin, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
+
+  theWin->setClearBeforeRendering (false);
+}
+
+// =======================================================================
+// function : sync
+// purpose  :
+// =======================================================================
+void AndroidQt::sync()
+{
+  myViewportSize = window()->size() * window()->devicePixelRatio();
+
+  if (myViewer.IsNull())
+  {
+    initViewer();
+    connect (window(), SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
+  }
+  else
+  {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
+    if (aDriver->getRawGlContext() != eglGetCurrentContext())
+    {
+      initViewer();
+    }
+    else
+    {
+      Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window());
+      aWindow->SetSize (myViewportSize.width(), myViewportSize.height());
+      //myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed
+
+      EGLContext anEglContext = eglGetCurrentContext();
+      myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
+    }
+  }
+}
+
+// =======================================================================
+// function : paint
+// purpose  :
+// =======================================================================
+void AndroidQt::paint()
+{
+  myMutex.lock();
+
+  if (Abs(myTouchPoint.DevX()) + Abs(myTouchPoint.DevY()) > 1)
+  {
+    myView->StartRotation (myTouchPoint.X().first,  myTouchPoint.Y().first);
+    myView->Rotation      (myTouchPoint.X().second, myTouchPoint.Y().second);
+
+    myTouchPoint.ClearDev();
+  }
+
+  if (myFitAllAction)
+  {
+    myView->FitAll();
+    myFitAllAction = false;
+  }
+
+  myMutex.unlock();
+
+  myView->Redraw();
+}
+
+// =======================================================================
+// function : initViewer
+// purpose  :
+// =======================================================================
+bool AndroidQt::initViewer()
+{
+  EGLint aCfgId = 0;
+  int aWidth = 0, aHeight = 0;
+  EGLDisplay anEglDisplay = eglGetCurrentDisplay();
+  EGLContext anEglContext = eglGetCurrentContext();
+  EGLSurface anEglSurf    = eglGetCurrentSurface (EGL_DRAW);
+
+  if (anEglDisplay == EGL_NO_DISPLAY
+   || anEglContext == EGL_NO_CONTEXT
+   || anEglSurf    == EGL_NO_SURFACE)
+  {
+    release();
+    return false;
+  }
+
+  eglQuerySurface (anEglDisplay, anEglSurf, EGL_WIDTH,     &aWidth);
+  eglQuerySurface (anEglDisplay, anEglSurf, EGL_HEIGHT,    &aHeight);
+  eglQuerySurface (anEglDisplay, anEglSurf, EGL_CONFIG_ID, &aCfgId);
+
+  const EGLint aConfigAttribs[] = { EGL_CONFIG_ID, aCfgId, EGL_NONE };
+  EGLint       aNbConfigs = 0;
+  void*        anEglConfig = NULL;
+
+  if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE)
+  {
+    release();
+    return false;
+  }
+
+  if (!myViewer.IsNull())
+  {
+    Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
+    Handle(AndroidQt_Window)     aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window());
+    if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
+    {
+      release();
+      return false;
+    }
+
+    aWindow->SetSize (aWidth, aHeight);
+    myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
+  }
+
+  Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False);
+  aDriver->ChangeOptions().buffersNoSwap = Standard_True;
+  //aDriver->ChangeOptions().glslWarnings  = Standard_True; // for GLSL shaders debug
+
+  if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
+  {
+    release();
+    return false;
+  }
+
+  // create viewer
+  myViewer = new V3d_Viewer (aDriver, TCollection_ExtendedString("Viewer").ToExtString(), "", 1000.0,
+                             V3d_XposYnegZpos, AndroidQt_UserInteractionParameters::BgColor.Name(), V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT,
+                             Standard_True, Standard_False);
+  myViewer->SetDefaultLights();
+  myViewer->SetLightOn();
+
+  // create AIS context
+  myContext = new AIS_InteractiveContext (myViewer);
+  myContext->SetDisplayMode (AIS_Shaded);
+
+  Handle(AndroidQt_Window) aWindow = new AndroidQt_Window (aWidth, aHeight);
+  myView = myViewer->CreateView();
+
+  myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
+  myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER);
+
+  return true;
+}
+
+// =======================================================================
+// function : release
+// purpose  :
+// =======================================================================
+void AndroidQt::release()
+{
+  myContext.Nullify();
+  myView.Nullify();
+  myViewer.Nullify();
+}
diff --git a/samples/qt/AndroidQt/AndroidQt.h b/samples/qt/AndroidQt/AndroidQt.h
new file mode 100644 (file)
index 0000000..9bc0e57
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef ANDROIDQT_H
+#define ANDROIDQT_H
+
+#include <OpenGl_Context.hxx>
+
+// workaround broken definitions in Qt
+#define GLdouble GLdouble
+
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/QQuickItem>
+
+#undef GLdouble
+
+#include <AIS_InteractiveContext.hxx>
+#include <V3d_View.hxx>
+
+#include <QMutex>
+
+#include <AndroidQt_TouchParameters.h>
+
+//! QML item with embedded OCCT viewer.
+class AndroidQt : public QQuickItem
+{
+  Q_OBJECT
+
+public:
+  //! Default constructor.
+  AndroidQt();
+
+  //! Display shape from file.
+  Q_INVOKABLE bool ReadShapeFromFile (QString theFilePath);
+
+  //! Handle touch event.
+  Q_INVOKABLE void InitTouch   (const double theX,
+                                const double theY);
+  
+  //! Handle touch event.
+  Q_INVOKABLE void UpdateTouch (const double theX,
+                                const double theY);
+
+public slots:
+
+  //! Handle OpenGL context creation and window resize events.
+  void sync();
+  
+  //! Redraw OCCT viewer and handle pending viewer events in rendering thread.
+  void paint();
+
+private slots:
+
+  //! Handle window change event.
+  void handleWindowChanged (QQuickWindow* theWin);
+
+private:
+
+  //! (Re-)initialize viewer on OpenGL context change.
+  bool initViewer();
+
+  //! Close viewer
+  void release();
+
+private:
+
+  Handle(V3d_Viewer)             myViewer;       //!< 3D viewer
+  Handle(V3d_View)               myView;         //!< 3D view
+  Handle(AIS_InteractiveContext) myContext;      //!< interactive context
+
+  QMutex                         myMutex;        //!< mutex for interconnection with rendering thread
+  QSize                          myViewportSize; //!< QML item size
+  AndroidQt_TouchParameters      myTouchPoint;   //!< cached state of touch event
+  bool                           myFitAllAction; //!< queued viewer FitALL event
+
+};
+
+#endif // ANDROIDQT_H
diff --git a/samples/qt/AndroidQt/AndroidQt.pro b/samples/qt/AndroidQt/AndroidQt.pro
new file mode 100644 (file)
index 0000000..7ddc34b
--- /dev/null
@@ -0,0 +1,31 @@
+TEMPLATE = app
+
+QT += qml quick widgets
+
+SOURCES += Main.cxx \
+           AndroidQt.cxx \
+           AndroidQt_Window.cxx \
+           AndroidQt_TouchParameters.cxx
+
+RESOURCES += AndroidQt.qrc
+
+# Additional import path used to resolve QML modules in Qt Creator's code model
+QML_IMPORT_PATH =
+
+# OCCT
+include(OCCT.pri)
+
+# Default rules for deployment.
+include(Deployment.pri)
+
+HEADERS += \
+           AndroidQt.h \
+           AndroidQt_Window.h \
+           AndroidQt_TouchParameters.h \
+           AndroidQt_UserInteractionParameters.h
+
+OTHER_FILES += \
+    android/src/org/qtproject/example/AndroidQt/AndroidQt.java \
+    android/AndroidManifest.xml
+
+ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
diff --git a/samples/qt/AndroidQt/AndroidQt.qrc b/samples/qt/AndroidQt/AndroidQt.qrc
new file mode 100644 (file)
index 0000000..bcead84
--- /dev/null
@@ -0,0 +1,8 @@
+<RCC>
+    <qresource prefix="/">
+        <file>res/qml/main.qml</file>
+    </qresource>
+    <qresource prefix="/icons">
+        <file>res/icons/ic_action_collection.png</file>
+    </qresource>
+</RCC>
diff --git a/samples/qt/AndroidQt/AndroidQt_TouchParameters.cxx b/samples/qt/AndroidQt/AndroidQt_TouchParameters.cxx
new file mode 100644 (file)
index 0000000..c844e26
--- /dev/null
@@ -0,0 +1,107 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AndroidQt_TouchParameters.h>
+
+// =======================================================================
+// function : AndroidQt_TouchParameters
+// purpose  :
+// =======================================================================
+AndroidQt_TouchParameters::AndroidQt_TouchParameters()
+: myXStart (0.0),
+  myXEnd   (0.0),
+  myYStart (0.0),
+  myYEnd   (0.0)
+{
+}
+
+// =======================================================================
+// function : AndroidQt_TouchParameters
+// purpose  :
+// =======================================================================
+AndroidQt_TouchParameters::AndroidQt_TouchParameters (const double theX,
+                                                      const double theY)
+: myXStart (theX),
+  myXEnd   (theX),
+  myYStart (theY),
+  myYEnd   (theY)
+{
+}
+
+// =======================================================================
+// function : X
+// purpose  :
+// =======================================================================
+QPair<double, double> AndroidQt_TouchParameters::X() const
+{
+  return qMakePair(myXStart, myXEnd);
+}
+
+// =======================================================================
+// function : DevX
+// purpose  :
+// =======================================================================
+double AndroidQt_TouchParameters::DevX() const
+{
+  return myXEnd - myXStart;
+}
+
+// =======================================================================
+// function : Y
+// purpose  :
+// =======================================================================
+QPair<double, double> AndroidQt_TouchParameters::Y() const
+{
+  return qMakePair(myYStart, myYEnd);
+}
+
+// =======================================================================
+// function : DevY
+// purpose  :
+// =======================================================================
+double AndroidQt_TouchParameters::DevY() const
+{
+  return myYEnd - myYStart;
+}
+
+// =======================================================================
+// function : SetStarts
+// purpose  :
+// =======================================================================
+void AndroidQt_TouchParameters::SetStarts (const double theXStart,
+                                           const double theYStart)
+{
+  myXStart = theXStart;
+  myYStart = theYStart;
+}
+
+// =======================================================================
+// function : SetEnds
+// purpose  :
+// =======================================================================
+void AndroidQt_TouchParameters::SetEnds (const double theXEnd,
+                                         const double theYEnd)
+{
+  myXEnd = theXEnd;
+  myYEnd = theYEnd;
+}
+
+// =======================================================================
+// function : ClearDev
+// purpose  :
+// =======================================================================
+void AndroidQt_TouchParameters::ClearDev()
+{
+  myXStart = myXEnd;
+  myYStart = myYEnd;
+}
diff --git a/samples/qt/AndroidQt/AndroidQt_TouchParameters.h b/samples/qt/AndroidQt/AndroidQt_TouchParameters.h
new file mode 100644 (file)
index 0000000..1debd06
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef ANDROIDQT_TOUCHPARAMETERS_H
+#define ANDROIDQT_TOUCHPARAMETERS_H
+
+#include <QPair>
+
+//! Class holding touch event state.
+class AndroidQt_TouchParameters
+{
+
+public:
+
+  //! Empty constructor.
+  AndroidQt_TouchParameters();
+
+  //! Default constructor.
+  AndroidQt_TouchParameters (const double theX,
+                             const double theY);
+
+  //! x coord
+  QPair<double, double> X() const;
+  double DevX() const;
+
+  //! y coord
+  QPair<double, double> Y() const;
+  double DevY() const;
+
+  //! Start coords
+  void SetStarts (const double theXStart,
+                  const double theYStart);
+
+  //! End coords
+  void SetEnds (const double theXEnd,
+                const double theYEnd);
+
+  void ClearDev();
+
+private:
+
+  double myXStart;
+  double myXEnd;
+
+  double myYStart;
+  double myYEnd;
+
+};
+
+#endif // ANDROIDQT_TOUCHPARAMETERS_H
diff --git a/samples/qt/AndroidQt/AndroidQt_UserInteractionParameters.h b/samples/qt/AndroidQt/AndroidQt_UserInteractionParameters.h
new file mode 100644 (file)
index 0000000..2010046
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef ANDROIDQT_USERINTERACTIONPARAMETERS_H
+#define ANDROIDQT_USERINTERACTIONPARAMETERS_H
+
+#include <Quantity_Color.hxx>
+
+namespace AndroidQt_UserInteractionParameters
+{
+  const double RotationThreshold  = 2;    // [pixel]
+  const double PanThreshold       = 4;    // [pixel]
+  const double ZoomThreshold      = 6;    // [pixel]
+  const double ZoomRatio          = 0.13; // distance ratio
+  const Quantity_Color BgColor    = Quantity_Color(0.145, 0.145, 0.145, Quantity_TOC_RGB); // color of viewer's background
+}
+
+#endif // USERINTERACTIONPARAMETERS_H
diff --git a/samples/qt/AndroidQt/AndroidQt_Window.cxx b/samples/qt/AndroidQt/AndroidQt_Window.cxx
new file mode 100644 (file)
index 0000000..5fc200c
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AndroidQt_Window.h>
+
+IMPLEMENT_STANDARD_HANDLE (AndroidQt_Window, Aspect_Window)
+IMPLEMENT_STANDARD_RTTIEXT(AndroidQt_Window, Aspect_Window)
+
+// =======================================================================
+// function : AndroidQt_Window
+// purpose  :
+// =======================================================================
+AndroidQt_Window::AndroidQt_Window (const int theWidth, const int theHeight,
+                                    const int theX1,    const int theX2,
+                                    const int theY1,    const int theY2)
+: myWidth (theWidth), myHeight(theHeight),
+  myX1 (theX1), myX2 (theX2),
+  myY1 (theY1), myY2 (theY2)
+{
+  if (myX1 == -1) myX1 = 0;
+  if (myX2 == -1) myX2 = myWidth;
+
+  if (myY1 == -1) myY1 = 0;
+  if (myY2 == -1) myY2 = myHeight;
+}
+
+// =======================================================================
+// function : Position
+// purpose  :
+// =======================================================================
+void AndroidQt_Window::Position (Standard_Integer& theX1,
+                                 Standard_Integer& theY1,
+                                 Standard_Integer& theX2,
+                                 Standard_Integer& theY2) const
+{
+  theX1 = myX1;
+  theX2 = myX2;
+  theY1 = myY1;
+  theY2 = myY2;
+}
+
+// =======================================================================
+// function : SetPosition
+// purpose  :
+// =======================================================================
+void AndroidQt_Window::SetPosition (const Standard_Integer theX1,
+                                    const Standard_Integer theY1,
+                                    const Standard_Integer theX2,
+                                    const Standard_Integer theY2)
+{
+  myX1 = theX1;
+  myX2 = theX2;
+  myY1 = theY1;
+  myY2 = theY2;
+}
+
+// =======================================================================
+// function : Size
+// purpose  :
+// =======================================================================
+void AndroidQt_Window::Size (Standard_Integer& theWidth,
+                             Standard_Integer& theHeight) const
+{
+  theWidth  = myWidth;
+  theHeight = myHeight;
+}
+
+// =======================================================================
+// function : SetSize
+// purpose  :
+// =======================================================================
+void AndroidQt_Window::SetSize (const Standard_Integer theWidth,
+                                const Standard_Integer theHeight)
+{
+  myWidth  = theWidth;
+  myHeight = theHeight;
+}
diff --git a/samples/qt/AndroidQt/AndroidQt_Window.h b/samples/qt/AndroidQt/AndroidQt_Window.h
new file mode 100644 (file)
index 0000000..575b194
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef ANDROIDQT_WINDOW_H
+#define ANDROIDQT_WINDOW_H
+
+#include <Aspect_Window.hxx>
+
+//! This class defines dummy window.
+//! The main functionality is viewport dimensions.
+class AndroidQt_Window : public Aspect_Window
+{
+
+public:
+
+  //! Creates a wrapper over existing Window handle
+  AndroidQt_Window(const int theWidth,   const int theHeight,
+                   const int theX1 = -1, const int theX2 = -1,
+                   const int theY1 = -1, const int theY2 = -1);
+
+  //! Returns native Window handle
+  virtual Aspect_Drawable NativeHandle() const { return 0; }
+
+  //! Returns parent of native Window handle.
+  virtual Aspect_Drawable NativeParentHandle() const { return 0; }
+
+  virtual void Destroy() {}
+
+  //! Opens the window <me>
+  virtual void Map() const {}
+
+  //! Closes the window <me>
+  virtual void Unmap() const {}
+
+  //! Applies the resizing to the window <me>
+  virtual Aspect_TypeOfResize DoResize() const { return Aspect_TOR_UNKNOWN; }
+
+  //! Apply the mapping change to the window <me>
+  virtual Standard_Boolean DoMapping() const { return Standard_True; }
+
+  //! Returns True if the window <me> is opened
+  virtual Standard_Boolean IsMapped() const { return Standard_True; }
+
+  //! Returns The Window RATIO equal to the physical WIDTH/HEIGHT dimensions
+  virtual Quantity_Ratio Ratio() const { return 1.0; }
+
+  //! Returns The Window POSITION in PIXEL
+  virtual void Position (Standard_Integer& theX1,
+                         Standard_Integer& theY1,
+                         Standard_Integer& theX2,
+                         Standard_Integer& theY2) const;
+
+  //! Set The Window POSITION in PIXEL
+  virtual void SetPosition (const Standard_Integer theX1,
+                            const Standard_Integer theY1,
+                            const Standard_Integer theX2,
+                            const Standard_Integer theY2);
+
+  //! Returns The Window SIZE in PIXEL
+  virtual void Size (Standard_Integer& theWidth,
+                     Standard_Integer& theHeight) const;
+
+  //! Set The Window SIZE in PIXEL
+  virtual void SetSize (const Standard_Integer theWidth,
+                        const Standard_Integer theHeight);
+
+private:
+
+  int myWidth;
+  int myHeight;
+
+  int myX1;
+  int myX2;
+  int myY1;
+  int myY2;
+
+public:
+
+  DEFINE_STANDARD_RTTI(AndroidQt_Window)
+
+};
+
+DEFINE_STANDARD_HANDLE(AndroidQt_Window, Aspect_Window)
+
+#endif // ANDROIDQT_WINDOW_H
diff --git a/samples/qt/AndroidQt/Deployment.pri b/samples/qt/AndroidQt/Deployment.pri
new file mode 100644 (file)
index 0000000..5441b63
--- /dev/null
@@ -0,0 +1,27 @@
+android-no-sdk {
+    target.path = /data/user/qt
+    export(target.path)
+    INSTALLS += target
+} else:android {
+    x86 {
+        target.path = /libs/x86
+    } else: armeabi-v7a {
+        target.path = /libs/armeabi-v7a
+    } else {
+        target.path = /libs/armeabi
+    }
+    export(target.path)
+    INSTALLS += target
+} else:unix {
+    isEmpty(target.path) {
+        qnx {
+            target.path = /tmp/$${TARGET}/bin
+        } else {
+            target.path = /opt/$${TARGET}/bin
+        }
+        export(target.path)
+    }
+    INSTALLS += target
+}
+
+export(INSTALLS)
diff --git a/samples/qt/AndroidQt/Main.cxx b/samples/qt/AndroidQt/Main.cxx
new file mode 100644 (file)
index 0000000..48102a5
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <QApplication>
+#include <QQmlApplicationEngine>
+
+#include <AndroidQt.h>
+
+int main(int argc, char *argv[])
+{
+  QApplication app(argc, argv);
+
+  qmlRegisterType<AndroidQt>("AndroidQt", 1, 0, "AndroidQt");
+
+  QQmlApplicationEngine engine;
+  engine.load (QUrl (QStringLiteral ("qrc:///res/qml/main.qml")));
+
+  return app.exec();
+}
diff --git a/samples/qt/AndroidQt/OCCT.pri b/samples/qt/AndroidQt/OCCT.pri
new file mode 100644 (file)
index 0000000..200a4e6
--- /dev/null
@@ -0,0 +1,53 @@
+#
+INCLUDEPATH += $$_PRO_FILE_PWD_/occt/inc $$_PRO_FILE_PWD_/3rdparty/include
+DEPENDPATH  += $$_PRO_FILE_PWD_/occt/inc $$_PRO_FILE_PWD_/3rdparty/include
+
+DEFINES += OCC_CONVERT_SIGNALS CSFDB
+
+QMAKE_CFLAGS   += -fexceptions -Wno-ignored-qualifiers
+QMAKE_CXXFLAGS += -fexceptions -Wno-ignored-qualifiers
+
+CONFIG(debug,debug|release) {
+  DEFINES += DEB
+}
+
+occt_lib_subpath = libs/armeabi-v7a
+
+occt_lib_path      = $$_PRO_FILE_PWD_/occt/$$occt_lib_subpath
+3rdparty_lib_path  = $$_PRO_FILE_PWD_/3rdparty/$$occt_lib_subpath
+
+
+LIBS += -L$$occt_lib_path \
+        -lTKernel \
+        -lTKMath \
+        -lTKG2d \
+        -lTKG3d \
+        -lTKGeomBase \
+        -lTKBRep \
+        -lTKGeomAlgo \
+        -lTKTopAlgo \
+        -lTKShHealing \
+        -lTKService \
+        -lTKMesh \
+        -lTKHLR \
+        -lTKV3d \
+        -lTKOpenGl \
+        -lEGL
+
+# IMPORTANT. load libraries in a proper order
+ANDROID_EXTRA_LIBS =  $$3rdparty_lib_path/libfreeimage.so \
+                      $$3rdparty_lib_path/libfreetype.so \
+                      $$occt_lib_path/libTKernel.so \
+                      $$occt_lib_path/libTKMath.so \
+                      $$occt_lib_path/libTKG2d.so \
+                      $$occt_lib_path/libTKG3d.so \
+                      $$occt_lib_path/libTKGeomBase.so \
+                      $$occt_lib_path/libTKBRep.so \
+                      $$occt_lib_path/libTKGeomAlgo.so \
+                      $$occt_lib_path/libTKTopAlgo.so \
+                      $$occt_lib_path/libTKShHealing.so \
+                      $$occt_lib_path/libTKService.so \
+                      $$occt_lib_path/libTKMesh.so \
+                      $$occt_lib_path/libTKHLR.so \
+                      $$occt_lib_path/libTKV3d.so \
+                      $$occt_lib_path/libTKOpenGl.so
diff --git a/samples/qt/AndroidQt/ReadMe.md b/samples/qt/AndroidQt/ReadMe.md
new file mode 100644 (file)
index 0000000..080f5cb
--- /dev/null
@@ -0,0 +1,54 @@
+OCCT AndroidQt sample for Android {#samples_qml_android_occt}
+================== 
+
+This sample demonstrates a simple way of using OCCT libraries in Android application written using Qt/Qml.
+
+The connection between Qt/Qml and OCCT (C++) level is provided by proxy library, libAndroidQt.so, written in C++.
+The proxy library contains single C++ class AndroidQt encapsulating OCCT viewer and providing functionality to manipulate this viewer
+and to import OCCT shapes from supported format of CAD file (BREP).
+
+Requirements for building sample:
+* Java Development Kit 1.7 or higher
+* Qt 5.3 or higher
+* Android SDK  from 2014.07.02 or newer
+* Android NDK r9d or newer
+* Apache Ant 1.9.4 or higher
+Configure project for building sample:
+
+In QtCreator, open AndroidQt.pro project-file:
+~~~~
+  File -> Open file or Project... 
+~~~~
+
+Specify Android configurations:
+~~~~
+Tools->Options->Android
+~~~~ 
+* In JDK location specify path to Java Development Kit
+* In Android SDK location specify path to Android SDK
+* In Android NDK location specify path to Android NDK
+* In Ant executable specify path to ant.bat file located in Apache Ant bin directory
+
+Make sure that "Android for armeabi-v7a" kit has been detected
+~~~~
+Tools->Options->Build & Run
+~~~~ 
+
+The paths to OCCT and 3rdparty libraries are specified in "OCCT.pri" file:
+
+the paths to the headers:
+~~~~
+INCLUDEPATH += /occt/inc /3rdparty/include
+DEPENDPATH  += /occt/inc /3rdparty/include
+~~~~
+
+the libraries location:
+~~~~
+LIBS += -L/occt/libs/armeabi-v7a
+~~~~
+
+OCCT resources (Shaders, SHMessage, StdResource, TObj, UnitsAPI and XSMessage folder) should be copied to androidqt_dir/android/assets/opencascade/shared/ directory. Current sample requires at least Shaders folder.
+
+Select build configuration: Debug or Release and click Build->Build Project "AndroidQt" or (Ctrl + B).
+After successful build the application can be deployed to device or emulator.
diff --git a/samples/qt/AndroidQt/android/AndroidManifest.xml b/samples/qt/AndroidQt/android/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..4d5be71
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<manifest package="org.qtproject.example.AndroidQt" xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" android:versionCode="0" android:versionName="">
+    <application android:hardwareAccelerated="true" 
+                 android:name="org.qtproject.qt5.android.bindings.QtApplication" 
+                 android:icon="@drawable/ic_launcher" 
+                 android:label="@string/app_name">
+        <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation"
+                  android:name="org.qtproject.example.AndroidQt.AndroidQt"
+                  android:label="@string/app_name"
+                  android:screenOrientation="landscape"
+                  android:launchMode="singleInstance">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+            <!--  For file browsers -->
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW"/>
+
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+
+                <data android:scheme=""/>
+                <data android:scheme="file"/>
+                <data android:host="*"/>
+
+                <data android:pathPattern=".*\\.brep"/>
+            </intent-filter>
+
+            <!-- For email attachments -->
+            <intent-filter>
+               <action android:name="android.intent.action.VIEW"/>
+               <category android:name="android.intent.category.DEFAULT"/>
+               <category android:name="android.intent.category.BROWSABLE"/>
+               <data android:mimeType="application/octet-stream" host="*" android:scheme="content"/>
+
+
+                <data android:pathPattern=".*\\.brep"/>
+            </intent-filter>
+
+            <meta-data android:name="android.app.lib_name" android:value="AndroidQt"/>
+            <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
+            <meta-data android:name="android.app.repository" android:value="default"/>
+            <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
+            <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
+            <!-- Deploy Qt libs as part of package -->
+            <meta-data android:name="android.app.bundle_local_qt_libs" android:value="1"/>
+            <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
+            <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
+            <!-- Run with local libs -->
+            <meta-data android:name="android.app.use_local_qt_libs" android:value="1"/>
+            <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
+            <meta-data android:name="android.app.load_local_libs" android:value="plugins/platforms/android/libqtforandroid.so:lib/libQt5QuickParticles.so"/>
+            <meta-data android:name="android.app.load_local_jars" android:value="jar/QtAndroid.jar:jar/QtAndroidAccessibility.jar:jar/QtAndroid-bundled.jar:jar/QtAndroidAccessibility-bundled.jar"/>
+            <meta-data android:name="android.app.static_init_classes" android:value=""/>
+            <!--  Messages maps -->
+            <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
+            <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
+            <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
+            <!--  Messages maps -->
+
+            <!-- Splash screen -->
+            <!--
+            <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
+            -->
+            <!-- Splash screen -->
+        </activity>
+    </application>
+    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15"/>
+    <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
+
+    <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
+         Remove the comment if you do not require these default permissions. -->
+        <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+
+    <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
+         Remove the comment if you do not require these default features. -->
+        <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
+
+</manifest>
diff --git a/samples/qt/AndroidQt/android/assets/opencascade/shared/.gitignore b/samples/qt/AndroidQt/android/assets/opencascade/shared/.gitignore
new file mode 100644 (file)
index 0000000..51e1556
--- /dev/null
@@ -0,0 +1 @@
+Shaders
diff --git a/samples/qt/AndroidQt/android/res/drawable-hdpi/ic_launcher.png b/samples/qt/AndroidQt/android/res/drawable-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..d27ba82
Binary files /dev/null and b/samples/qt/AndroidQt/android/res/drawable-hdpi/ic_launcher.png differ
diff --git a/samples/qt/AndroidQt/android/res/drawable-mdpi/ic_launcher.png b/samples/qt/AndroidQt/android/res/drawable-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..4b86dbf
Binary files /dev/null and b/samples/qt/AndroidQt/android/res/drawable-mdpi/ic_launcher.png differ
diff --git a/samples/qt/AndroidQt/android/res/drawable-xhdpi/ic_launcher.png b/samples/qt/AndroidQt/android/res/drawable-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..cd79bea
Binary files /dev/null and b/samples/qt/AndroidQt/android/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/samples/qt/AndroidQt/android/res/drawable-xxhdpi/ic_launcher.png b/samples/qt/AndroidQt/android/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..a34301f
Binary files /dev/null and b/samples/qt/AndroidQt/android/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/samples/qt/AndroidQt/android/res/values/strings.xml b/samples/qt/AndroidQt/android/res/values/strings.xml
new file mode 100644 (file)
index 0000000..4f59f34
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='utf-8'?>
+<resources>
+    <string name="app_name">AndroidQt</string>
+</resources>
diff --git a/samples/qt/AndroidQt/android/src/org/qtproject/example/AndroidQt/AndroidQt.java b/samples/qt/AndroidQt/android/src/org/qtproject/example/AndroidQt/AndroidQt.java
new file mode 100644 (file)
index 0000000..d67d8fd
--- /dev/null
@@ -0,0 +1,99 @@
+package org.qtproject.example.AndroidQt;
+
+import android.content.Intent;
+import android.content.res.AssetManager;
+import android.os.Bundle;
+
+import java.util.List;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class AndroidQt extends org.qtproject.qt5.android.bindings.QtActivity
+{
+  @Override public void onCreate(Bundle theBundle)
+  {
+    super.onCreate(theBundle);
+
+    // copy OCCT resources
+    String aResFolder = getFilesDir().getAbsolutePath();
+    copyAssetFolder (getAssets(), "opencascade", aResFolder + "/opencascade");
+
+  }
+
+  //! Copy folder from assets
+  private boolean copyAssetFolder (AssetManager theAssetMgr,
+                                   String       theAssetFolder,
+                                   String       theFolderPathTo)
+  {
+    try
+    {
+      String[] aFiles  = theAssetMgr.list (theAssetFolder);
+      File     aFolder = new File (theFolderPathTo);
+      aFolder.mkdirs();
+      boolean isOk = true;
+      for (String aFileIter : aFiles)
+      {
+        if (aFileIter.contains ("."))
+        {
+          isOk &= copyAsset (theAssetMgr,
+                             theAssetFolder  + "/" + aFileIter,
+                             theFolderPathTo + "/" + aFileIter);
+        }
+        else
+        {
+          isOk &= copyAssetFolder (theAssetMgr,
+                                   theAssetFolder  + "/" + aFileIter,
+                                   theFolderPathTo + "/" + aFileIter);
+        }
+      }
+      return isOk;
+    }
+    catch (Exception theError)
+    {
+      theError.printStackTrace();
+      return false;
+    }
+  }
+
+  //! Copy single file from assets
+  private boolean copyAsset (AssetManager theAssetMgr,
+                             String       thePathFrom,
+                             String       thePathTo)
+  {
+    try
+    {
+      InputStream aStreamIn = theAssetMgr.open (thePathFrom);
+      File aFileTo = new File (thePathTo);
+      aFileTo.createNewFile();
+      OutputStream aStreamOut = new FileOutputStream (thePathTo);
+      copyStreamContent (aStreamIn, aStreamOut);
+      aStreamIn.close();
+      aStreamIn = null;
+      aStreamOut.flush();
+      aStreamOut.close();
+      aStreamOut = null;
+      return true;
+    }
+    catch (Exception theError)
+    {
+      theError.printStackTrace();
+      return false;
+    }
+  }
+
+  //! Copy single file
+  private static void copyStreamContent (InputStream  theIn,
+                                         OutputStream theOut) throws IOException
+  {
+    byte[] aBuffer = new byte[1024];
+    int aNbReadBytes = 0;
+    while ((aNbReadBytes = theIn.read (aBuffer)) != -1)
+    {
+      theOut.write (aBuffer, 0, aNbReadBytes);
+    }
+  }
+}
diff --git a/samples/qt/AndroidQt/res/icons/ic_action_collection.png b/samples/qt/AndroidQt/res/icons/ic_action_collection.png
new file mode 100644 (file)
index 0000000..c41ca8c
Binary files /dev/null and b/samples/qt/AndroidQt/res/icons/ic_action_collection.png differ
diff --git a/samples/qt/AndroidQt/res/qml/main.qml b/samples/qt/AndroidQt/res/qml/main.qml
new file mode 100644 (file)
index 0000000..c80be25
--- /dev/null
@@ -0,0 +1,82 @@
+// Created: 2014-08-28
+//
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+import QtQuick 2.2
+import QtQuick.Window 2.1
+
+import QtQuick.Dialogs 1.2
+
+import QtQuick.Controls 1.2
+import QtQuick.Controls.Styles 1.2
+
+import AndroidQt 1.0
+
+Window {
+  id: root_window
+  visible: true
+
+  Item {
+    id: root_item
+    anchors.fill: parent
+
+    AndroidQt {
+      id: viewer
+    }
+
+    MouseArea {
+      anchors.fill: parent
+
+      onPressed: viewer.InitTouch(mouseX, mouseY)
+      onPositionChanged: viewer.UpdateTouch (mouseX, mouseY)
+    }
+
+    // open button
+    Rectangle {
+      id: open_button
+
+      // align
+      anchors.top: parent.top
+      anchors.left: parent.left
+
+      // size
+      width:  200
+      height: 200
+
+      color: "white"
+
+      // image
+      Image {
+        anchors.horizontalCenter: parent.horizontalCenter
+        anchors.verticalCenter: parent.verticalCenter
+
+        source: "qrc:///icons/res/icons/ic_action_collection.png"
+      }
+
+      MouseArea {
+        anchors.fill: parent
+        onClicked: file_dialog.open()
+      }
+    }
+  }
+
+  FileDialog {
+    id: file_dialog
+    title: "Please choose a file"
+    selectMultiple: false
+    nameFilters: [ "BRep files (*.brep)", "All files (*)" ]
+    onAccepted: viewer.ReadShapeFromFile(file_dialog.fileUrl)
+  }
+}