Tuesday, July 22, 2014

The Community Team



So, given Jono’s departure a few weeks back, I bet a lot of folks have been wondering about the Canonical Community Team. For a little background, the community team reports into the Ubuntu Engineering division of Canonical, which means that they all report into me. We have not been idle, and this post is to discuss a bit about the Community Team going forward.

What has Stayed the Same?

First, we have made some changes to the structure of the community team itself. However, one thing did not change. I kept the community team reporting directly into me, VP of Engineering, Ubuntu. I decided to do this so that there is a direct line to me for any community concerns that have been raised to anyone on the community team.

I had a call with the Community Council a couple of weeks ago to discuss the community team and get feedback about how it is functioning and how things could be improved going forward. I laid out the following for the team.

First, there were three key things that I think that I wanted the Community Team to continue to focus on:
  • Continue to create and run innovative programs to facilitate ever more community contributions and growing the community.
  • Continue to provide good advice to me and the rest of Canonical regarding how to be the best community members we can be, given our privileged positions of being paid to work within that community.
  • Continue to assist with outward communication from Canonical to the community regarding plans, project status, and changes to those.
The Community Council was very engaged in discussing how this all works and should work in the future, as well as other goals and responsibilities for the community team.

What Has Changed?

In setting up the team, I had some realizations. First, there was no longer just one “Community Manager”. When the project was young and Canonical was small, we had only one, and the team slowly grew. However, the Team is now four people dedicated to just the Community Team, and there are others who spend almost all of their time working on Community Team projects.

Secondly, while individuals on the team had been hired to have specific roles in the community, every one of them had branched out to tackle new challenges as needed.

Thirdly, there is no longer just one “Community Spokesperson”. Everyone in Ubuntu Engineering can and should speak to/for Canonical and to/for the Ubuntu Community in the right contexts.
So, we made some small, but I think important changes to the Community Team.

First, we created the role Community Team Manager. Notice the important inclusion of the word Team”. This person’s job is not to “manage the community”, but rather to organize and lead the rest of the community team members. This includes things like project planning, HR responsibilities, strategic planning and everything else entailed in being a good line manager. After a rather competitive interview process, with some strong candidates, one person clearly rose to the top as the best candidate. So, I would like formally introduce David Planella (lp, g+) as the Community Team Manager!

Second, I change the other job titles from their rather specific titles to just “Community Manager” in order to reflect the reality that everyone on the community team is responsible for the whole community. So that means, Michael Hall (lp, g+), Daniel Holbach (lp, g+), and Nicholas Skaggs (lp, g+), are all now “Community Manager”.

What's Next?

This is a very strong team, and a really good group of people. I know them each personally, and have a lot of confidence in each of them personally. Combined as a team, they are amazing. I am excited to see what comes next.

In light of these changes, the most common question I get is, “Who do I talk to if I have a question or concern?” The answer to that is “anyone.” It’s understandable if you feel the most comfortable talking to someone on the community team, so please feel free to find David, Michael, Daniel, or Nicholas online and ask their question. There are, of course, other stalwarts like Alan Pope (lp, g+) and Oliver Grawert (lp, g+) who seem to be always online :) By which, I mean to say that while the Community Managers are here to serve the Ubuntu Community, I hope that anyone in Ubuntu Engineering considers their role in the Ubuntu Community to include working with anyone else in the Ubuntu Community :)

Want talk directly to the community team today? Easy, join their Ubuntu on Air Q&A Session at 15 UTC :)

Finally, please note that I love to be "interrupted" by questions from community members :) The best way to get in touch with me is on freenode, where I go by rickspencer3. Otherwise, I am also on g+, and of course there is this blog :)

Monday, May 5, 2014

Delaying Queries to a Server from Map Move Events



Last week I added BikeShare info to my map. But I also take the bus a lot. I would like the information I need to choose between taking a bus and grabbing a bike. So I need to show buses on the map. In my first iteration of showing bus data, I downloaded the XML for every bus stop in the metro system and loaded that. Unfortunately, this did not work. 

There are over 11,000 bus stops in the DC Metro System and using that may POI in a MapItemView made the map unusably slow. Even if it wasn't slow, when zoomed out on the map, the POI covered the map so it was just a huge blob of POI. Oh well, looks like I need to do something slightly more elegant. 

What I need to do is query the server every time the user moves the map, through a pan or a zoom and ask the web service for the XML for the bus stops centered on the center of the map, and within a certain radius that is slightly bigger than the map. However, if I do that for each and eveyr pan and zoom, I end up hammering the server when ever the user swipes. The web service doesn't like to be called so much so fast, and it's just a waste of resources and bandwidth. So I decided to add a little logic to only load the data after the map is "at rest" for some period of time. I chose to start with a two second rest, but it could be whatever. I did this by first creating a timer.

       Timer
       {
         id: mapRestTimer  
         running: false  
         interval: 2000  
       
       }  

Then I wrote add some event handlers to the Map, for zoom and pan events.
       onZoomLevelChanged:  
       {  
         if(zoomLevel >= minimumBusDataZoomLevel)  
         {  
           timeMapRest()  
         }  
       }  
       onCenterChanged:  
       {  
         if(zoomLevel >= minimumBusDataZoomLevel)  
         {  
           timeMapRest()  
         }  
       }  
Note that I set it up so that bus stops aren't displayed if the user is panned out too far due to the problems I mentioned above. The timeMapRest function just decides whether it needs to restart the timer, or to start it. If the timer is already running, then the user has moved the map before the rest period was up, so we'll reset the timer. Otherwise, we'll go ahead and start the timer.
   function timeMapRest()  
       {  
         if(mapRestTimer.running)  
         {  
           mapRestTimer.restart()  
         }  
         else  
         {  
           mapRestTimer.start()  
         }  
       }  

To finish up, I just had to write an onTriggered handler and set properties on my subclassed XmlListModel, which then goes ahead an updates itself based on the new latlong or zoom level.
         id: mapRestTimer  
         running: false  
         interval: 2000  
         onTriggered:  
         {  
           //stop the timer and set the new latlong  
           running: false  

           //get the info necessary to calculate the correct radius
           busStopListModel.latlong = [getThereMap.center.latitude,getThereMap.center.longitude]  
           var tr = getThereMap.toCoordinate(Qt.point(0,0))  
           var bl = getThereMap.toCoordinate(Qt.point(getThereMap.width,getThereMap.height))  
           var latdiff = bl.latitude - tr.latitude  
           var londiff = bl.longitude - tr.longitude  
           //TODO: fix this silly calculation for the radius  
           var rad = (latdiff > londiff) ? latdiff * (34.67 * 5280 / 3) : londiff * (34.67 * 5280 / 3 )  
           busStopListModel.mapRadius = rad  
         }  
       }  


The code for the whole project is here.

Monday, April 21, 2014

Adding Interactivity to a Map with Popovers

On Friday I started my app "GetThereDC". I started by adding the locations of all of the Bikeshare stations in DC to a map. Knowing where the stations are is great, but it's a bummer when you go to a station and there are no bikes, or there are no empty parking spots. Fortunately, that exact information is in the XML feed, so I just need a way to display it.  
The way I decided to do it is to make the POI (the little icons for each station on the map) clickable, and when the user clicks the POI to use the Popover feature in the Ubuntu Components toolkit to display the data.

Make the POI Clickable

When you want to make anyting "clickable" in QML, you just use a MouseArea component. Remember that each POI is constructed as a delegate in the MapItemView as an Image component. So all I have to do is add a MouseArea inside the Image and respond to the Click event. So, not my image looks like this:
           sourceItem: Image  
           {  
             id: poiImage  
             width: units.gu(2)  
             height: units.gu(2)  
             source: "images/bike_poi.png"  
             MouseArea  
             {  
               anchors.fill: parent  
               onClicked:  
               {  
                 print("The POI was clicked! ")  
               }  
             }  
           }  
This can be used anywhere in QML to make an image respond to a click. MouseArea, of course, has other useful events as well, for things like onPressed, onPressAndHold, etc...

Add the Roles to the XmlListModel

I already know that I'll want something to use for a title for each station, the address, as well as the number of bikes and the number of parking slots. Looking at the XML I can see that the "name" property is the address, so that's a bonus. Additionally, I can see the other properties I want are called "nbBikes" and "nbEmptyDocks". So, all I do is add those three new roles to the XmlListModel that I constructed before:
   XmlListModel  
   {  
     id: bikeStationModel  
     source: "https://www.capitalbikeshare.com/data/stations/bikeStations.xml"  
     query: "/stations/station"  
     XmlRole { name: "lat"; query: "lat/string()"; isKey: true }  
     XmlRole { name: "lng"; query: "long/string()"; isKey: true }  
     XmlRole {name: "name"; query: "name/string()"; isKey: true}  
     XmlRole {name: "available"; query: "nbBikes/string()"; isKey: true}  
     XmlRole {name: "freeSlots"; query: "nbEmptyDocks/string()"; isKey: true}  
   }  

Make a Popover Component

The Ubuntu SDK offers some options for displaying additional information. In old school applications these might be dialog boxes, or message boxes. For the purposes of this app, Popover looks like the best bet. I suspect that over time the popover code might get a little complex, so I don't want it to be too deeply nested inside the MapItemView, as the code will become unwieldy. So, instead I decided to add a file called BikeShareStationPopover.qml to the components sub-directory. Then I copy and pasted the sample code in the documentation to get started. 

To make a popover, you start with a Component tag, and then add a popover tag inside that. Then, you can put pretty much whatever you want into that Popover. I am going to go with a Column and use ListItem components because I think it will look nice, and it's the easiest way to get started. Since I already added the XmlRoles I'll just use those roles in the construction of each popover. 

Since I know that I will be adding other kinds of POI, I decided to add a Capital Bike Share logo to the top of the list so users will know what kind of POI they clicked. I also added a close button just to be certain that users don't get confused about how to go back to the map. So, at the end of they day, I just have a column with ListItems:
 import QtQuick 2.0  
 import Ubuntu.Components 0.1  
 import Ubuntu.Components.ListItems 0.1 as ListItem  
 import Ubuntu.Components.Popups 0.1  
 Component  
 {  
   id: popoverComponent  
   Popover  
   {  
     id: popover  
     Column  
     {  
       id: containerLayout  
       anchors  
       {  
         left: parent.left  
         top: parent.top  
         right: parent.right  
       }  
       ListItem.SingleControl  
       {  
         control: Image  
         {  
           source: "../images/CapitalBikeshare_Logo.jpg"  
           height: units.gu(5)  
           width: units.gu(5)  
         }  
       }  
       ListItem.Header { text: name}  
       ListItem.Standard { text: available + " bikes available" }  
       ListItem.Standard { text: freeSlots + " parking spots available"}  
       ListItem.SingleControl  
       {  
         highlightWhenPressed: false  
         control: Button  
         {  
           text: "Close"  
           onClicked: PopupUtils.close(popover)  
         }  
     }  
   }  
 }  

Make the Popover Component Appear on Click

So, now that I made the component code, I just need to add it to the MapItemView and make it appear on click. So, I add the tag and give it an id to the MapQuickItem Delegate, and change the onClicked handler for the MouseArea to open the popover:
 delegate: MapQuickItem  
         {  
           id: poiItem  
           coordinate: QtPositioning.coordinate(lat,lng)  
           anchorPoint.x: poiImage.width * 0.5  
           anchorPoint.y: poiImage.height  
           z: 9  
           sourceItem: Image  
           {  
             id: poiImage  
             width: units.gu(2)  
             height: units.gu(2)  
             source: "images/bike_poi.png"  
             MouseArea  
             {  
               anchors.fill: parent  
               onClicked:  
               {  
                 PopupUtils.open(bikeSharePopover)  
               }  
             }  
           }  
           BikeShareStationPopover  
           {  
             id: bikeSharePopover  
           }  
         }  
And when I run the app, I can click on any POI and see the info I want! Easy!

Code is here

Friday, April 18, 2014

It's Easy and Fun to Write Map Based Apps

Yesterday I started work on an app that I personally want to use. I don't have a car, so I use services like Metro Bus, Metro Rail, Car2Go, and BikeShare around DC all the time. It's annoying to go to each different web page or app to get the information that I want, so I decided to write an app that combines it all for me in one place.

After asking around, I settled on a best practice for Ubuntu map apps, and I was pointed to this excellent code as a basis:
http://bazaar.launchpad.net/~yohanboniface/osmtouch/trunk/view/head:/OSMTouch.qml

It was so easy and fun once I got started, that I decided to show the world. So, here we go.

I started with a "Simple UI" project. Then I deleted the default column that it started with, and I set the title of the Page to an empty string. While I was at it, I changed the height and width to be more like a phone's dimensions to make testing a little easier. So my starter code for an emply Window looks like this:
 import QtQuick 2.0  
 import Ubuntu.Components 0.1  
 import "components"  
 MainView {  
   objectName: "mainView"  
   applicationName: "com.ubuntu.developer.rick-rickspencer3.MapExample"  
   width: units.gu(40)  
   height: units.gu(60)  
   Page  
   {  
     title: i18n.tr("")  
   }  
 }  
So what's missing now is a map. First I need to import the parts of Qt where I get location and map information, so I add these imports:
 import QtPositioning 5.2  
 import QtLocation 5.0  
Then I can use the Map tag to add a Map to the MainView. I do four things in the Map to make it show up. First, I tell it to fill it's parent (normal for any component). Then I set it's center property. I choose to do this using a coordinate. Note that you can't make a coordinate in a declarative way, you have to construct it like below. The center property tells the map the latitude and longitude to be centered on. Then I choose the zoom level, which determines the scale of the map. Finally, I need to specify the plug in. For various reasons, I choose to use the Open Street Maps plugin, though feel free to experiment with others. So, a basic funcitonal map looks like this:
   Page  
   {  
     title: i18n.tr("")  
     Map  
     {  
       anchors.fill: parent  
       center: QtPositioning.coordinate(38.87, -77.045)  
       zoomLevel: 13  
       plugin: Plugin { name: "osm"}  
     }  
    }  
When I run it, I get a lot of functionality for free. On the desktop I can drag the map, and when I run the app on my phone or tablet, I can pinch to zoom in or out. All that functionality comes for free. Of course, you are free to add mapping controls as desired, but I find that map works well out of the box, at least on a device that supports pinch and zoom.


Typically, a map displays little pinpoints. These are often referred to as Points of Interest, or more typically "POI". It's delightfully easy to populate your map with POI using our old friend XmlListModel. First, you will need some XML that has location information. For this exmaple, I am going to use the Bike Share feed for Washington, DC. It's easy to get and to parse, so it makes a nice example. You can see the feed here:
https://www.capitalbikeshare.com/data/stations/bikeStations.xml

So let's use it to set up our XmlListModel. First, of course, we need to import the XmlListModel functionality.


 import QtQuick.XmlListModel 2.0  
Next, we'll make the list model, and use the query and Roles functionality to set up the model with the latitude and longitude of each POI inside the model. This is *exactly* like using the XmlListModel for a typical list view. Very cool.
   XmlListModel  
   {  
     id: bikeStationModel  
     source: "https://www.capitalbikeshare.com/data/stations/bikeStations.xml"  
     query: "/stations/station"  
     XmlRole { name: "lat"; query: "lat/string()"; isKey: true }  
     XmlRole { name: "lng"; query: "long/string()"; isKey: true }  
   }  
Now that I have my list model set up, it's time to display them on the Map. We don't do that with a ListView, but rather wtih a MapItemView. This works exactly the same as a ListView, except it displays items on a map instead of in a list. Just like a ListView I need a delegate that will translate use data from the each item in the XmlListModel to create a UI element. In this case, it's a MapQuickItem instead of a ListItem (or similar). A MapQuickItem needs to know 4 things.

  1. The model where it will get the data. In this case, it's my XmlListModel, but it could be a javascript list or other model as well.
  2. A latitude and longitude for the POI, which I set up as roles in the XmlListModel.
  3. An offset for whatever I am using for POI so that it is positioned properly. In this case I have made a little pushpin image out of the bikeshare logo (I know it's bad I'll make a better one later :) ). The offset is set by anchorPoint, so I make the anchorPoint the bottom and center of of the pushpin. 
  4. Something to use for the POI. In this case, I choose to use an image. Note that it is important to use grid units, or the POI may appear too small on some devices, and too large on others. Grid Units make them "just right" on all devices, and ensure that users can click them on any device. 


So, here is my MapItemView that goes *inside* the Map tag. It's a MapItemView for the map, after all.

       MapItemView  
       {  
         model: bikeStationModel  
         delegate: MapQuickItem  
         {  
          id: poiItem  
          coordinate: QtPositioning.coordinate(lat,lng)  
          anchorPoint.x: poiImage.width * 0.5  
          anchorPoint.y: poiImage.height  
          sourceItem: Image  
          {  
            id: poiImage  
            width: units.gu(2)  
            height: units.gu(2)  
            source: "bike_poi.png"  
          }  
         }  
       }  
Now when I run the app, the POI are displayed. As you would expect, when the user moves the Map, the MapItemView automatically displays the correct POI. It's really that easy.


If you want to add interactivity, that's easy, you can simply add a MouseArea to the Image and then use things like Ubuntu.Components.Popups to popup additional information about the POI. 


This sample code is here: http://bazaar.launchpad.net/~rick-rickspencer3/+junk/MapExample/view/head:/MapExample.qml