Canonical Voices

Posts tagged with 'building-sdk-app-series'

Michael Hall

screenshot_1.0So it’s finally happened, one of my first Ubuntu SDK apps has reached an official 1.0 release. And I think we all know what that means. Yup, it’s time to scrap the code and start over.

It’s a well established mantra, codified by Fred Brooks, in software development that you will end up throwing away the first attempt at a new project. The releases between 0.1 and 0.9 are a written history of your education about the problem, the tools, or the language you are learning. And learn I did, I wrote a whole series of posts about my adventures in writing uReadIt. Now it’s time to put all of that learning to good use.

Often times projects still spend an extremely long time in this 0.x stage, getting ever closer but never reaching that 1.0 release.  This isn’t because they think 1.0 should wait until the codebase is perfect, I don’t think anybody expects 1.0 to be perfect. 1.0 isn’t the milestone of success, it’s the crossing of the Rubicon, the point where drastic change becomes inevitable. It’s the milestone where the old code, with all it’s faults, dies, and out of it is born a new codebase.

So now I’m going to start on uReadIt 2.0, starting fresh, with the latest Ubuntu UI Toolkit and platform APIs. It won’t be just a feature-for-feature rewrite either, I plan to make this a great Reddit client for both the phone and desktop user. To that end, I plan to add the following:

  • A full Javascript library for interacting with the Reddit API
  • User account support, which additionally will allow:
    • Posting articles & comments
    • Reading messages in your inbox
    • Upvoting and downvoting articles and comments
  • Convergence from the start, so it’s usable on the desktop as well
  • Re-introduce link sharing via Content-Hub
  • Take advantage of new features in the UITK such as UbuntuListView filtering & pull-to-refresh, and left/right swipe gestures on ListItems

Another change, which I talked about in a previous post, will be to the license of the application. Where uReadIt 1.0 is GPLv3, the next release will be under a BSD license.

Read more
Michael Hall

It may surprise some of you (not really) to learn that in addition to being a software geek, I’m also a sci-fi nerd. One of my current guilty pleasures is the British Sci-Fi hit Doctor Who. I’m not alone in this, I know many of you reading this are fans of the show too.  Many of my friends from outside the floss-o-sphere are, and some of them record a weekly podcast on the subject.

Tonight one of them was over at my house for dinner, and I was reminded of Stuart Langridge’s post about making a Bad Voltage app and how he had a GenericPodcastApp component that provided common functionality with a clean separation from the rest of his app. So I decided to see how easy it would be to make a DWO Whocast app with it.  Turns out, it was incredibly easy.

Here are the steps I took:

  1. Create a new project in QtCreator
  2. Download Stuart’s GenericPodcastApp.qml into my project’s ./components/ folder
  3. Replace the template’s Page components with GenericPodcastApp
  4. Customize the necessary fields
  5. Add a nice icon and Suru-style gradients for good measure

That’s it! All told it took my less than 10 minutes to put the app together, test it, show it off, and submit my Click package to the store.  And the app doesn’t look half bad either.  Think about that, 10 minutes to get from an idea to the store.  It would have been available to download too if automatic reviews were working in the store (coming soon).

That’s the power of the Ubuntu SDK. What can you do with it in 10 minutes?

Update: Before this was even published this morning the app was reviewed, approved, and available in the store.  You can download it now on your Ubuntu phone or tablet.

Read more
Michael Hall

Back again for one more article on developing an Ubuntu SDK app.  This one might be short,  but it covers one of the cooler bits of magic that QML gives you: Transitions.  But first, be sure to read the previous articles in this series!

Transitions

It used to be that if you wanted to animate parts of your app, you had to setup timers, calculate distances and speeds, program each step along the way, and do it all without killing the user’s CPU.  Sure it could be done, it was done, but it wasn’t easy.  QML is different, QML Transitions aren’t something you have to bolt on yourself, they’re built in at the foundation.

A Transition is defined as a collection of Animation components that can change different properties in different ways, triggered automatically by a change in a component’s state or other properties.  All you, the developer, needs to do is tell QML what you want to change, and how.

ListView Event Transitions

QML offers a variety of ways to define transitions, depending on what you need.  All Items have a transitions  property, which takes a list of Transition instances that will be called whenever the Item’s state property is changed.  You can also define a Transition for any property change using the “Behavior on <property> {}” syntax, which creates a Transition for changes on the named property.

But for me, it was a third item that fit best.  QML’s ListView component has several properties that take a Transition instance, properties such as add and remove, which correspond to an item being added or removed from the ListView.  These transitions are then applied to the delegate ListItem component when it is being added or removed.  I used these properties to make the items slide in and out of view when changing subreddit, or moving from one page to another.

    ListView {
        id: articleList
        ...
        add: Transition {
            id: addAnimation
            property bool forward: true
            SequentialAnimation {
                NumberAnimation { properties: "x"; from: addAnimation.forward ? articleList.width : -articleList.width; to: 0; duration: 300 }
            }

        }
        remove: Transition {
            id: removeAnimation
            property bool forward: true
            SequentialAnimation {
                NumberAnimation { properties: "x"; from: 0; to: removeAnimation.forward ? -articleList.width : articleList.width; duration: 300 }
            }
        }
    }

At first I just had transitions going in one direction, but I wanted to give some implicit meaning to them, going one direction for “more results” and another for “new results” (reload, change subreddit, etc).  That’s why I added the extra forward property, which is used to determine the direction of the transition.

You can see it in action in this video:

Next Time: Who knows?

This is the last revision currently in my bzr branch.  I have some other code in the works, for Sharing using the new Friends service, and HUD integration.  But for one reason or another, neither is working quite the way I want it yet, and they haven’t been committed to my branch yet.  There were typically several days between revisions when I was developing uReadIt, and I’ve been blogging about it nearly every day since my first post.  Once I have some time to hack on uReadIt some more, I will have more to write about, so stay tuned!

Read more
Michael Hall

Hurray, it’s Friday!  I’ve got a somewhat lighter article to celebrate the end of the work week (sorry to those of you for whom it isn’t).  Today I’m going to cover revision 7, in which I replaced the large default Headers with small, customized headers specifically for my app.  If you haven’t read my previous articles in this series, I strongly encourage you to do so, as each one builds on top of the one before it.

New Header Component

To replace the old Header, I first had to create the new ones.  Headers are relatively simple things, they sit on top and display text, so there wasn’t a whole lot to it.  I created an Item to act as the container.  Items are the most based UI elements in QML, all they really do is hold other elements, and provide the base type for other elements to inherit from.  Inside of the Item I put a Rectangle, which is pretty much exactly what it sounds like.  What a Rectangle can do that an Item can’t is set a border and background color, which is what I wanted to do with my header.  Finally I put a Label inside of the Rectangle to contain the header.

Item {
    id: header
    anchors.right: parent.right
    anchors.left: parent.left
    anchors.top:parent.top

    height: headerText.height + units.gu(1)
    Rectangle{
        anchors.fill: parent
        color: 'lightblue'
        border.width: 1
        border.color: 'grey'
        Label {
            id: headerText
            anchors.centerIn: parent
            text: ''
            fontSize: 'large'
            font.bold: true
        }
    }
}

You can see that I set the anchors for the Item to place it at the top of it’s parent (SubredditListView in this case) which is important for reasons you’ll see below.  I also set the Rectangle’s background color to ‘lightblue’. For the subreddit page I made the fontSize large, bold, and centered in the header (that’s what anchors.centerIn: parent does).  That works for the short text name of a Subreddit, but for the article I needed something a little bit different.

Item {
    id: header
    anchors.right: parent.right
    anchors.left: parent.left
    anchors.top:parent.top
    visible: false
    height: headerText.contentHeight + units.gu(1)
    Rectangle{
        anchors.fill: parent
        color: 'lightblue'
        border.width: 1
        border.color: 'grey'
        Label {
            id: headerText
            anchors.fill: parent
            anchors.verticalCenter: parent.verticalCenter
            anchors.margins: units.gu(0.5)
            font.bold: false
            wrapMode: Text.WrapAtWordBoundaryOrAnywhere
        }
    }
}

Here I made left the Label text it’s default size, and not bold.  I also didn’t center it horizontally like I did for the subreddit page.  But most importantly, I set the text to wrap so that articles with an overly long title will flow over multiple lines, increasing the size of the header to accommodate it.

Keeping it up to date

Since I was already passing the full article data data to the ArticleView component, extracting the new title and updating it was easy to do, I just needed to add a line to the onArticleChanged callback.

    onArticleChanged: {
        if (article) {
            articleWebView.url = article.data.url
            headerText.text = article.data.title
        }
    }

But changing the header on the SubredditListView required a little more work.  Since I already had a property on it called subreddit, I was able to write an onSubredditChanged callback to run whenever I needed to update the Subreddit name in this header.

    onSubredditChanged: updateHeader()
    Component.onCompleted: updateHeader()
    function updateHeader() {
        if (subreddit == '') {
            headerText.text = 'Frontpage'
        } else {
            headerText.text = subreddit
        }
    }

Next time: Transitions

One of the really neat things about QML is that it makes developing rich, fancy interfaces very easy.  And part of how it does this is by building support for transition animations right in at the ground level.  I knew from the beginning of this project that I wanted to try them out, and in the next revision I finally took the opportunity to add them.

Read more