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 selfBarcodeReader.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