Maybe Important - 2015-07-31 16:05 UTC-0800 Pritpal Bedi (bedipritpal at hotmail.com)(r417)[ HbQtQmlParts ]

132 views
Skip to first unread message

Pritpal Bedi

unread,
Jul 31, 2015, 9:45:04 PM7/31/15
to Harbour Users
2015-07-31 16:05 UTC-0800 Pritpal Bedi (bedipritpal at hotmail.com)(r417)
  + hbqtqmlparts

  + hbqtqmlparts/resources
  + hbqtqmlparts/resources/png
  + hbqtqmlparts/resources/png/left-32.png
  + hbqtqmlparts/resources/png/refresh-32.png
  + hbqtqmlparts/resources/png/right-32.png
  + hbqtqmlparts/resources/png/stop-32.png
  + hbqtqmlparts/resources/qml
  + hbqtqmlparts/resources/qml/BarcodeReader.qml
  + hbqtqmlparts/resources/qml/WebView.qml
  + hbqtqmlparts/resources/wav
  + hbqtqmlparts/resources/wav/barcode-beep.wav
  + hbqtqmlparts/resources/wav/camera-flash.wav

  + hbqtqmlparts/misc.prg
  + hbqtqmlparts/qmlbridge.prg
  + hbqtqmlparts/barcodereader.prg
  + hbqtqmlparts/webview.prg

  + hbqtqmlparts/hbqtqmlparts.hbc
  + hbqtqmlparts/hbqtqmlparts.hbp
  + hbqtqmlparts/hbqtqmlparts.hbx
  + hbqtqmlparts/hbqtqmlparts.qrc

  + hbqtqmlparts/tests
  + hbqtqmlparts/tests/demobarcodereader.prg
  + hbqtqmlparts/tests/demowebview.prg
  + hbqtqmlparts/tests/hbmk.hbm

  + qtcontribs.hbp
    + Added: hbqtqmlparts/hbqtqmlparts.hbp

    Initial commit of Harbour engine for QML manipulation.

    QML is the next-generation offering by Qt which facilitates to develop 
    modern-looking, javaScript based applications. QML is also the core 
    language adopted by Ubuntu mobile plaforms and its concept of 
    one-os-fit-all-devices shift. So seems QML is set to become the 
    protocol of choice for so many applications.

    Harbour's implementation of Qt, i.e. HbQt, is essentially a widget 
    based implementation. It took me a while to turn to QML because 
    of the necessity to have barcode reading inside my mobile offerings.
    I remained reluctant to give QML a try for a long time because of the 
    complexity how Signal/Slot mechanism is implemented in Harbour.
    But when I took initiative, I found that it is simpler than my fear.
    Bottom line is : we can start using QML to some extent alsong-with 
    and within our existing widget based apps.

    CLASS HbQtQmlBridge() provides the building blocks to stream-line 
    the complexity of signal/slots, set/get properties, execute methods, etc.
    
       CLASS HbQtQmlBridge()

       METHOD init( oParent )
       METHOD create( oParent )

       METHOD setQml( cQml )                                -> lSuccess
       METHOD show()                                        -> NIL
       METHOD setProperty( cProperty, xValue )              -> lSuccess
       METHOD setChildProperty( cChild, cProperty, xValue ) -> lSuccess
       METHOD getProperty( cProperty )                      -> oQVariant | NIL
       METHOD getChildProperty( cChild, cProperty )         -> oQVariant | NIL
       METHOD invokeMethod( cMethod, ... )                  -> oQVariant | NIL
       METHOD connect( cSignal, bBlock )                    -> lSuccess
       METHOD connectChild( cChild, cSignal, bBlock )       -> lSuccess

       :create() only initiates a QQuickWidget(), set some of its 
         properties, connects it to error handeling slots and 
         lays it in a best-judged layout on its parent.

       :setQml( cQml ) is where all the action happens.
          This is the only place where we could know if a QML 
          document has been loaded or not. All subsequest operations 
          are executable only if we succeed here. Be noted that QML 
          engine is a scripting engine and is based on JavaScript 
          heavily.

    Lets disect CLASS HbQtBarcodeReader() and BarcodeReader.qml in 
    relevant context only. HbQtBarcodeReader() is developed to provide 
    one-line calling methodology in mind and has many other constructs
    you are already familiar with.

    METHOD HbQtBarcodeReader:create( oParent )    
       ...
       ...
       // register C++ classes in order to access them inside QML
       // immediately before those are about to be Used
       //
       HBQAbstractVideoSurface():registerQmlTypes()
       QZXing():registerQmlTypes()

      ::oQmlBridge := HbQtQmlBridge():new():create( ::oQmlContainerWidget )

      // provide the QML document location needed
      //
      IF ::oQmlBridge:setQml( "qrc:/hbqtqml/resources/qml/BarcodeReader.qml" )
         ::stopCamera()

         #ifndef __ANDROID__
            // because QVideoProbe() is only available for Android
            // we need render the frame ourselves, so this connection
            //
            ::oQmlBridge:connectChild( "videosurface", "imageAvailable(QImage)", {| oImage | ::dispImage( oImage ) } )
         #endif
         // we could have connected the "qzxing" child also for the same effect
         // but we decided to receive signal via QML document as it implements 
         // more constructs.
         //
         ::oQmlBridge:connect( "tagFound(QString)", {| cTag | ::manageBarcodeFound( cTag ) } )

         __hbqtAppRefresh()
      ENDIF
      ...
      ...
      RETURN self   

   
    BarcodeReader.qml [ only relevant parts ]:
    =========================================

    Rectangle {
        id         : cameraUI
        objectName : "camerainterface"     // name to access the object
                                           // as this is the root object
                                           // it can be accessed directly. 
    
        property bool stopScanningFrames   // can be set/get via :setProperty
    
        signal imageCaptured( string image )
        signal tagFound( string tag )      // signal we will receive via :connect
    
        function startScanning() {
           stopScanningFrames = false;
        }
        function stopScanning() {
           stopScanningFrames = true;
        }
        function stopCamera() {            // method we will invoke via :invokeMethod
            cameraUI.stopScanning();
            camera.stop();
        }
        function startCamera() {
            camera.start();
            cameraUI.startScanning();
            myVideoSurface.decoder = decoder;
            myVideoSurface.source  = camera;
        }
    
        Camera {
            id: camera
            objectName: "camera"           // can be accessed as QObject
                                           // from PRG QObject can only be 
                                           // exploited via :connect()
        }
    
        VideoOutput {
            id               : viewfinder
            objectName       : "viewfinder"
            source           : Qt.platform.os == "android" ? camera : myVideoSurface
        }
    
        QZXing{
            id         : decoder
            objectName : "qzxing"
            onTagFound : {
                if( ! cameraUI.stopScanningFrames )
                {
                    cameraUI.stopScanningFrames = true;
                    playSoundCameraFlash.play();
                    cameraUI.tagFound( tag ); // emit the signal which we :connect()ed
                }
            }
        }
    
        HBQAbstractVideoSurface{
            id         : myVideoSurface
            objectName : "videosurface"   // will connect via :connectChild()
        }
    
        SoundEffect {
            id      : playSoundCameraFlash
            source  : "qrc:/hbqtqml/resources/wav/barcode-beep.wav"
        }
    }
    
    A convinient function, one-liner, can be fired to scan a barcode as:
    __hbqtActivateBarcodeReader( {|cBarcode| LetMePushIntoField( cBarcode ) } )

    I hope this class will flourish with passage of time as we will gain 
    more experience into QML and allied technology. I am impressed with 
    results and plan to share with you whatever meaningful I could muster.

    Enjoy and stay tuned!



Pritpal Bedi
a student of software analysis & concepts
Reply all
Reply to author
Forward
0 new messages