Sunday, 23 June 2013

Playing around with the guts of Sailfish Silica Components

Have you ever felt the need to dig around in the guts of the Sailfish Silica provided QML components to work out how things are done? This article explains how you can do this.

Recently I decided to change the way my LandedSettings app allows the user to create, edit and delete entries in the settings database.

Under the existing solution, when the user double-clicked an item in a view (and I have four views), the view delegate would push an appropriate configuration page. This page was festooned with new, edit and delete buttons. Each of these would push a further page allowing that action to be carried out.

I was never entirely happy with this solution. It always struck me as more than a little clumsy and very "desktop", but as LandedSettings was a secondary app supporting the main app Landed I stuck with it.

Then I started porting to Sailfish Silica. Using the Sailfish ComponentsGallery as a reference (click on the propeller on the home screen) I found that under Silica, when a view entry is pressed and held, a context menu drops down.

This seemed to be a much better solution to offer new, copy, edit and delete options, so I set about changing LandedSettings to use this type of context menu.

After a little bit of hacking, I got the ContextMenu to open, but not quite as I expected. This strange behaviour is reported here:

So how do I track down and cure this behaviour?

Well the first step is to find the guilty qml file. In QtCreator a right-click / "Follow Symbol Under Cursor" takes us to the file

In this case it's ContextMenu.qml, and can be found in /Users/<your home drive>/SailfishOS/mersdk/targets/SailfishOS-i486-x86/usr/lib/qt4/imports/Sailfish/Silica/

Now I could have edited this file direct, then copied it to the Emulator via SSH / SCP. But I did not want to change the original

Instead, I  decided to create a clone LandedContextMenu in my project. I could then change the clone to my heart's desire, and deploy it just as I deploy any other .qml file in my project.

To get the clone to work, I had to make a few more changes:

a) in addition to copying ContextMenu to my project, I also had to copy Util.js and HighlightBar.qml, both of which are used by ContextMenu.qml, and can be found in the private subdirectory.

b) change the import in LandedContextMenu to

import "Util.js" as Util
import Sailfish.Silica.private 1.0
The Sailfish.Silica.private import is required to get the ScreenChangeNotifier component working. This exposed by a c++ plugin, and not as a .qml file.

Having done this I could now change things within LandedContextMenu, and see how this affected LandedSettings.

My desk-checking of ContextMenu.qml had suggested that the problem might be caused by a PropertyChanges element that operates on the contentY property of a Flickable.
target: _flickable
contentY:Math.max(contextMenu.mapToItem(_flickable.contentItem, 0, contextMenu.childrenRect.height).y-_flickable.height, _flickable.contentY)
interactive: false
explicit: true

So my next task is to understand this, and then decide if I can find a workaround, or maybe even keep a modified version of the clone in my project.

No comments:

Post a Comment