Saturday, 2 August 2014

HsQML 0.3.1.1 released: One Thousand Downloads

A few days ago I released HsQML 0.3.1.1, a bug fix to my Haskell binding to the Qt Quick GUI library. You can download the latest release from Hackage as usual.

The primary purpose of this release was to fix issue 20. HsQML has code which monitors variant values created using the Qt library in order to prevent objects which are referenced by a variant from being garbage collected. A flaw in this code caused it to examine the data held inside variants even when it wasn't valid, causing a crash in certain circumstances.

release-0.3.1.1 - 2014.07.31

  * Fixed crash when storing Haskell objects in QML variants.
  * Fixed corrupted logging output caused by threading.

In related news, HsQML has now reached over 1000 downloads from Hackage since Hackage 2 started collecting download statistics late last year. See the bar chart below:-


The spike in May was owed to the transition to Qt 5 brought about by the release of 0.3.0.0. Hopefully, the graph will climb to new heights with the release of more features in the future!

My target for the next release is to support rendering OpenGL graphics directly from Haskell code and into the QML scene, to better support applications with sophisticated requirements for custom drawing. This is tracked by issue 10.

Friday, 4 July 2014

Scaling content in QML

A HsQML user e-mailed me to ask me how they could get a QML Item to fill the parent Window and I thought it would make an interesting blog post. The easy answer to that question is to use anchors to snap the boundaries of the Item to its parent's as follows:

Item {
    anchors.fill: parent;
    ...

However, in a sense, that only defers the layout problem to the Item's children. They still need to position themselves in the variable amount of space offered by their parent, either using anchors again, one of the special layout elements such as Grid or GridLayout, or by property binding each child's positioning properties (x, y, etc.) to a custom layout calculation.

Qt Quick has a number of facilities to help you to lay out your Items, but there's one particular problem that it takes a few stabs at but still doesn't make especially easy. If you have an Item which has a particular aspect ratio, how do you scale it to fill the available space while still retaining the correct aspect?

The Image element solves this problem for itself with the fillMode property, which among other things allows you to preserve the source image aspect via either fitting or cropping. However, this property is specific to images and it doesn't affect any child elements you might want to position relative to the image. It does exposes the results of its calculations via the paintedWidth and paintedHeight properties so you could use this to help you place them manually, but it would still require a little work.

On the other hand, the QQuickView C++ class offers a solution at the top-level by extending the view to support scaling QML content automatically. If HsQML used this convenience class to display its QML documents that don't have explicit Windows, it could be set to always resize the content to fit the window via the setResizeMode() method. However, this would only help to resize whole documents and then only when explicit windows weren't used.

Fortunately, it's not too difficult to build an implementation of scale-to-fit using transforms and property binding. This involves specifying both a scaling transform on the content Item to size it to fit its parent and a translating transform to centre the content if the parent has a different aspect. Any children of content Item will be positioned according to the coordinate system specified by the content Item's fixed dimensions and will be transformed along with the Item to the desired size.

The scale factor and offsets can be calculated by expressions which make use of the parent Item or Window's width and height properties. QML's property binding facility means that whenever the width or height changes, the expressions which use those values will be re-evaluated and hence the layout updated. The following example demonstrates implementing this with an explicit Window element in order to make its properties accessible for binding:

import QtQuick 2.0
import QtQuick.Window 2.0

Window {
    id: win; width: 200; height: 200;

    Rectangle {
        id: rect; width: 100; height: 100; color: 'blue';

        transform: [
            Scale {
                id: scale; xScale: yScale;
                yScale: Math.min(
                    win.width/rect.width,
                    win.height/rect.height);},
            Translate {
                x: (win.width-rect.width*scale.xScale)/2;
                y: (win.height-rect.height*scale.yScale)/2;}]

        Rectangle {
            x: 0; y: 0; width: 50; height: 50; color: 'red';
        }
    }
}

This can also be made to work when you don't have an explicit Window by accessing its properties via the parent property of the root Item. The important thing to note here is that the root's parent will be initially be null when the document loads. It's only when HsQML notices that the root element isn't a Window that it will create the implicit Window for you, so a little care has to be taken to ensure that the parent's properties aren't accessed until the parent has actually been set. I took the opportunity to implement this in the Morris demo application which didn't previously handle scaling correctly, or you can look at the example code below:

Rectangle {
    id: rect; width: 100; height: 100; color: 'blue';

    property real pw : parent!=null?parent.width:width;
    property real ph : parent!=null?parent.height:height;

    transform: [
        Scale {
            id: scale; xScale: yScale;
            yScale: Math.min(
                rect.pw/board.width,rect.ph/board.height);},
        Translate {
            x: (rect.pw-board.width*scale.xScale)/2;
            y: (rect.ph-board.height*scale.yScale)/2;}]

N.B. Nothing in this post is really specific to HsQML and you can equally try out these examples with the qmlscene tool.

Sunday, 22 June 2014

Windows Qt binaries for the Haskell Platform (HsQML)

Since upgrading to Qt 5, the installation procedure for HsQML, my Qt Quick binding for Haskell, has been been less than ideal on Windows. This is because the official Qt SDK for Windows now uses a much newer version of MinGW than ships with GHC or the Haskell Platform and the two are no longer binary compatible. Binaries compiled by GHC using these Qt libraries simply crash on start-up.

It has always been possible to work around this problem by modifying GHC's configuration files to use the C compiler from Qt's MinGW rather than its own. However, this is a rather awkward thing to have to do and, regrettably, the instructions on my web-site for doing it weren't terribly clear.

I have now produced a special build of Qt 5.3.0 using GHC's MinGW which should work out of the box. The download and updated instructions are available from the Windows section on the HsQML web-site. Hopefully this will make getting HsQML running on Windows much simpler.

Longer term, GHC ticket #9218 tracks updating the version of MinGW which ships with GHC to something more recent.

Technical Details

I began by making a straightforward build of ICU 53.1, which is a Qt dependency, and then configured the Qt source tree to make a release build using the desktop OpenGL graphics stack as follows:

configure -opensource -release -opengl desktop -no-angle -skip qtwinextras -prefix C:\qt530-hp

The one oversight here was not using the -no-sseX flags to limit the use of instructions set extensions. I presume therefore that build targeted the host machine and may not work on processors which don't support SSE 4.1 or later. The QtWinExtras module relied to too heavily on functionality missing from the older MinGW headers and so I had to disable it.

Once the build was under way I ran into a few minor tool-chain issues which I resolved as follows:-
  • Remove some flags which are unsupported by the older compiler. Namely -fno-keep-inline-dllexport in qtbase/mkspecs/win32-g++/qmake.conf and -Wno-error=unused-but-set-variable in qtwebkit/Source/ThirdParty/leveldb/Target.pri.
  • Redirect required symbols missing from MinGW to suitable alternatives. Namely YieldProcessor to _mm_pause, MemoryBarrier to _mm_mfence, strcasecmp to _stricmp, strncasecmp to _strnicmp, strdup to _strdup, _exit to _Exit, and _MAX_PATH to MAX_PATH.
  • Change the name of the GUID member of the VMRGUID structure in MinGW's strmif.h so that it doesn't have the same name as its type.
  • Add the missing header file delayimp.h by copying it from a newer version of MinGW.
When I repeat this process for the next release of Qt 5, I will prepare a proper diff against the MinGW headers to make this set up more easily reproducible.

Finally, when testing the resulting binaries, I found a MinGW-specific bug which had been introduced in the Qt 5.3 release and causes it to intermittently crash. This has been filed as QTBUG-39793 and the patch attached to that bug was applied to this build.

Wednesday, 11 June 2014

HsQML 0.3.1.0 released

I've just released HsQML 0.3.1.0 which, as usual, is available for download from Hackage. This release fixes several stability issues and also introduces a facility for defining properties with the CONST attribute.

If you use a property defined on one of your Haskell objects in a QML expression and that property doesn't have an associated signal, then Qt will print the following warning:

Expression depends on non-NOTIFYable properties

For mutable objects, the accurately informs us that QML has no way of knowing if the value of that property changes. However, when using Haskell, we often prefer to work with immutable values and there was previously no way of informing Qt that the value would never change. Previously, the only course of action was to specify a dummy signal or to use nullary methods instead of properties. You can now use the new defPropertyConst function instead of defPropertyRO to specify that an associated signal is unnecessary and suppress this warning.

As an aside, Christopher Reichert has just written a blog post about using HsQML which is well worth the read.

release-0.3.1.0 - 2014.06.11

  * Added properties with constant annotation.
  * Added runtime warning for users of the non-threaded RTS.
  * Added non-TH version of Setup.hs.
  * Relaxed Cabal dependency constraint on 'transformers'.
  * Fixed premature garbage collection of QML objects.
  * Fixed intermittent crash on exit when firing signals.
  * Fixed crash when using Cmd-Q to exit on MacOS.

Monday, 5 May 2014

HsQML 0.3.0.0 released: Now with Qt 5

I've just made a new major release of HsQML, my Haskell binding for the Qt Quick GUI framework. You can download it from Hackage in the usual manner.

This is a particularly exciting release because it's the first to have been ported over to use Qt 5. Previously, HsQML was developed against an older version of the Qt Quick technology which shipped as part of Qt 4.7 and 4.8. Support for Qt 5 has been a constant theme in the e-mails I get concerning HsQML for some time and so I'm pleased to finally deliver on that point.

There are also number of other improvements to the library which should allow more idiomatic QML code and hence reduce the need for helper JavaScript. Properties now support an associated notify signal which allows QML to automatically update in response to property changes rather than needing manual signal handlers. Also, lists and Maybe values can be marshalled between Haskell and QML natively, again reducing friction between the two environments.

The API has been redesigned slightly so that object classes and signal keys can be defined directly inside Haskell functions in addition to the older type-class based method. It's unclear yet if this style is wholly superior but, for smaller programs at least, it permits greater clarity and much less verbosity.

Finally, although still far from comprehensive, I've spent some time trying to improve the documentation on my web-site. It now provides some more substantial examples and goes into greater depth. The complete buildable source code for these examples is contained in the hsqml-demo-samples package. Also, the original Nine Men's Morris demo application is still available, but the package has been renamed to hsqml-demo-morris.

release-0.3.0.0 - 2014.05.04

  * Ported to Qt 5 and Qt Quick 2
  * Added type-free mechanism for defining classes.
  * Added type-free mechanism for defining signal keys.
  * Added property signals.
  * Added marshallers for Bool, Maybe, and lists.
  * Added less polymorphic aliases for def functions.
  * Replaced Tagged with Proxy in public API.
  * Removed marshallers for URI and String.
  * New design for marshalling type-classes (again).
  * Generalised facility for user-defined Marshal instances.
  * Relaxed Cabal dependency constraint on 'QuickCheck'.
  * Fixed GHCi on Windows with pre-7.8 GHC.

Tuesday, 4 February 2014

Using the Connections element with HsQML

I was asked recently if the Connections element could be used to declaratively connect QML actions to signals defined in Haskell code. I wasn't completely sure if it would work off-hand so I wrote the following example program with HsQML 0.2.x to find out (Hint: the answer is yes).

To begin with, we need a Haskell program which will load a QML document and fire off some signals. The following program forks off a thread which blocks for the user to enter a new line in the terminal window and fires a signal every time they do. The context object has two members, the signal we're experimenting with and a property called 'self' whose function will become apparent shortly.

{-# LANGUAGE DeriveDataTypeable, TypeFamilies #-}
import Graphics.QML
import Data.Typeable
import Data.Tagged
import Control.Concurrent
import Control.Monad

main :: IO ()
main = do
    ctx <- newObject MainObject
    tid <- forkIO $ forever $ do
        putStrLn "Press ENTER to run animation"
        void $ getLine
        fireSignal (Tagged ctx ::
            Tagged TheSignal (ObjRef MainObject))
    runEngineLoop defaultEngineConfig {
        contextObject = Just $ anyObjRef ctx}
    killThread tid

data TheSignal deriving Typeable
instance SignalKey TheSignal where
    type SignalParams TheSignal = IO ()

data MainObject = MainObject deriving Typeable
instance Object MainObject where
    classDef = defClass [
        defPropertyRO "self" ((\x -> return x) ::
            ObjRef MainObject -> IO (ObjRef MainObject)),
        defSignal (Tagged "theSignal" ::
            Tagged TheSignal String)]

The QML document to accompany the above program follows below. It should be placed in a file called 'main.qml' in order to be loaded by the defaultEngineConfig. You could set the initialURL field to something else if you wanted, but I'm trying to keep the code short.

import Qt 4.7
Rectangle {
    id: root
    width: 500; height: 500
    color: "red"
    Rectangle {
        id: square
        x: 150; y: 150; width: 200; height: 200
        color: "yellow"
        Rectangle {
            width: 50; height: 50; color: "black"
        }
        transform: Rotation {
            id: rotateSquare
            origin.x: 100; origin.y: 100; angle: 0
        }
        NumberAnimation {
            id: rotateAnim
            target: rotateSquare; property: "angle"
            from: 0; to: 360; duration: 1500
        }
        Connections {
            target: self
            onTheSignal: rotateAnim.start()
        }
    }
}

The code for the Connections element is highlighted in bold. Of its two attributes, the first, called 'target', specifies the object with signals that we want to bind handlers to. In this example the signal is a member of the global object and this complicates matters because it's not straightforward to write an expression which yields the global object. Hence, I placed the 'self' property on the global object to provide a convenient way of the getting a reference to it.

There are ways to get the global object, but they're not particularly pretty and I don't fully trust that kind of thing inside Qt's script environment anyway.

The second attribute specifies the signal binding. Specifically, the attribute name identifies the signal and is derived by pre-pending the string 'on' to the actual signal name. Hence, in this case, binding to 'theSignal' is specified using the attribute 'onTheSignal'. The value of the attribute is the JavaScript code to be executed when the signal fires. In our example it causes a simple little animation to occur.

Up to now, the only example I provided of using signals was the hsqml-morris demo application. It's not a great example of idiomatic QML because it uses a big chunk of JavaScript to work around some of the present limitations of HsQML's marshalling facilities (e.g. no lists/arrays). It makes no great attempt to be a "pure" QML application, so it just calls the signal's connect() method to attach it via JavaScript.

You could use the same approach with this test program by replacing the Connections element with the following code snippet:

        Component.onCompleted: {
            self.theSignal.connect(rotateAnim.start);
        }

The 'self' property is superfluous here because we can access the signal member on the global object directly. However, it's a slightly unfair comparison because the JavaScript code only covers connecting to the signal, whereas the Connections element also handles disconnections. When you're dynamically creating and destroying Components using things like the Repeater element, this is important to prevent overloading your signals with handlers that are never cleaned up.

The Connections element also allows the target attribute to be specified with a property or dynamic expression. If the value of the target expression changes at runtime then all the signal handlers will be disconnected and reconnected to the new object.

Addendum: Writing this example has made me think that HsQML relies too heavily on top-level data and instance declarations. I'd like to rectify that in the future by making QML classes first-class values on the Haskell side.

Sunday, 2 February 2014

HsQML 0.2.0.3 released

Yesterday, I made new a minor release of HsQML in order to address two issues with using it interactively via GHCi. As usual, it's available for download from Hackage. One little mistake did slip in however, in that I forget to change the darcs repository listed in the package cabal file to the Qt 4 branch. The main trunk is now being used for porting to Qt 5.

An explanation of the GHCi problems follows:

GHCi has traditionally had a number of limitations owing to the built-in linker it uses to load static object files dynamically. The linker is capable enough to load the output of GHC and any simple FFI C code that might be included in a library, but it can't cope with some of the relocations emitted by a C++ compiler. Originally, it wasn't even capable of reading the same archive libraries used by the GHC compiler for linking, and required that Cabal produce special compounded object files for it to use.

The C++ limitation was an issue for HsQML because Qt is a C++ library and hence HsQML needs to include some C++ code as part of its binding layer. I made use of the fact that GHCi depended on special object files in order to incorporate a workaround especially for GHCi. HsQML's build script modifies the build process by removing the objects containing C++ code from being compounded into the special object file, and places them into a separate shared library which is then referenced by the package's extra-ghci-libraries field. GHCi will hence load the shared library and the compiled C++ code within using the system linker, thereby avoiding the problems with its own.

However, it came to my attention recently* than this strategy had run into trouble as GHCi can now load regular archive libraries directly, supplanting the need for special object files. I discovered that the Fedora Linux had modified their distribution of GHC to disable generating the GHCi objects by default. Furthermore, that this behaviour would become the new standard default with Cabal 1.18. This broke HsQML with GHCi because because the aforementioned workaround didn't apply to the regular archive libraries and so GHCi's linker couldn't handle the C++ object files contained within.

I didn't want to simply apply the same workaround to the archive libraries as to the GHCi ones because that would introduce dealing with an additional magic shared library to users who simply wanted to compile their applications. The modification I've applied for this release was therefore to add code to Setup.hs to force (re-)enable generating the special GHCi object files under certain circumstances.

The impact of this issue is likely to decrease over time as GHC now also supports producing shared libraries from Haskell code in addition to static ones. This means that, going forward, the entirety of HsQML can be built as a shared library and GHCi can load it using the system linked without difficulty. My understanding is that this behaviour will become the default with GHC 7.8 for platforms other than Windows.

Hence, the rule is that generating GHCi object files is only force enabled if shared libraries are not enabled. The forcing behaviour can be disabled by passing -f-ForceGHCiLib to cabal-install.

The other issue I found that's fixed with this release is that GHCi had problems finding the workaround shared library on Windows. Unlike other platforms, the extra-ghci-libraries field needed to include the "lib" prefix to the referenced library name in order for Windows GHCi to find it without the library being on the PATH. With that fixed, HsQML should now work with GHCi out of the box on all platforms.

Now, back to working on the Qt 5 port!

release-0.2.0.3 - 2014.02.01

  * Added mechanism to force enable GHCi workaround library. 
  * Fixed reference name of extra GHCi library on Windows.

* Thanks to rnons.