Adding C++ Objects to your QML

There’s many times that you may want to access a C++ object from your QML. One obvious example is if you’ve already written a data model in C++; you can leverage that model with QML-based user interface. Any other time you need to access things you can only touch from C++, like hardware integration not provided by Qt Mobility, is another example.

As a simple example, consider a case where you want to expose a C++-based application controller (think model-view-controller) to your QML. You’ve got a class, AppController, with some Qt metaobject invocable methods, either expressed as properties, slots or using Q_INVOKABLE. Mine looks like this:

class AppController : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int width READ width NOTIFY sizeChanged)
    Q_PROPERTY(int height READ height NOTIFY sizeChanged)

public:
    explicit AppController(QObject *parent = 0);
    void setSize(const QSize& size) { mSize = size; emit sizeChanged(); };
    int width() { return mSize.width(); };
    int height() { return mSize.height(); };

   Q_INVOKABLE void magicInvocation();

signals:
    void sizeChanged();

private:
    QSize mSize;
};

Because QML binds using Qt’s metaobject system, the C++ object you want to expose to QML must be a descendant of QObject. Our AppController class is pretty simple; it’s just carrying the size of the window displaying the QML view, along with some C++ method my QML invokes named magicInvocation. (If I told you what it did… you get the idea.)

Of course, we need to fire up a QML viewer with our QML, and add an instance of AppController to the object hierarchy in the QML engine. I do that in my application’s main, which looks like this:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QRect screen = QApplication::desktop()->screenGeometry();
    QMainWindow* window = new QMainWindow(0, Qt::FramelessWindowHint );
    QDeclarativeView* view = new QDeclarativeView(window);
    AppController* controller(window);

    // The only thing we show is the declarative view.
    window->setCentralWidget(&view);

    // Size the window to be as big as it can be, except we don't
    // want it too big on our dev workstations.
    if (screen.width() <= kDesiredWidth) {
        window->showMaximized();
    } else {
        window->setGeometry(QRect(
            (screen.width()-kDesiredWidth)/2, (screen.height()-kDesiredHeight)/2, 
            kDesiredWidth, kDesiredHeight));
        window->show();
    }
    controller.setSize(window.size());

    // Proxy in our app controller so QML get its properties and show our QML
    view->rootContext()->setContextProperty("controller", controller);
    view->setSource(QUrl("qml/main.qml"));

    int result =  app.exec();
    delete window;
    return result;
}

Pretty basic stuff here:

  1. I get the screen size, used by the AppController for its own nefarious purposes.
  2. I create a full-screen main window with no window chrome.
  3. I create a QDeclarativeView to display the QML, and make the main window’s main widget the new QDeclarativeView.
  4. I create an instance of AppController.
  5. I do some funny stuff with the main window’s size so I don’t go crazy working on my desktop’s 22″ monitor, restricting the maximum possible size of the main window for test purposes.
  6. Using the QDeclarativeView‘s QDeclarativeEngine, I add the AppController instance to the QML context, giving it the name controller.
  7. I set the initial source of the QML to the QML entry point for my user interface, included as a file in my application’s package (not as a resource, but you could also choose to package it as a Qt application resource if you want.)
  8. Finally, I pass control to QApplication‘s main loop, and return its result code when its event loop exits.

The magic is QDeclarativeEngine::setContextProperty, which binds a QObject-derived instance to a specific name in the QML context. Once I do this, in my QML I can access this just as I would any QML or JavaScript object; its name is controller. So I might write controller.magicInvocation() to invoke my magic function in an onPressed signal handler, for instance.

(This is well-documented, but I found it handy to break this point out into a separate example to refer to. It’s also a predecessor for several upcoming posts, so it’s here so that those posts can refer back to this one.)

Compiling QtDBus for Windows…

I keep needing to do this. Each time I do, I have to rediscover how to do it.

Worse, I’m doing it slightly differently each time.

For interested parties, here’s what I just did for Qt 4.7.1. Worked for Qt 4.7.0, too.

I’m using MinGW, cmake, libexpat, and of course Qt. To begin, you need to build dbus itself for Windows, and then you can rebuild

  1. Make sure you have MinGW installed and correctly configured. Its bin directory should be in your path.
  2. Download cmake. Install.
  3. Download and install libexpat from http://www.winkde.org/pub/kde/ports/win32/repository-4.4/win32libs/(as suggested in the dbus documentation). You’ll want the lib archive. You’ll need the include directory no matter what for when you build QtDBus. Unpack these zips to C:\Program Files\win32libs.
  4. Grab dbus from the repository, put it in c:\dbus-1.4.0.
  5. Edit dbus-1.4.0\cmake\CMakeLists.txt, add
    set(LIBEXPAT_LIBRARIES "C:/Program Files/win32libs/lib/libexpat.lib")
    set(LIBEXPAT_INCLUDE_DIR "C:/Program Files/win32libs/include")
    set(LIBEXPAT_FOUND ON)
    

    after
    project(dbus)

  6. Start a Windows Command Prompt
  7. mdkir c:\dbus && cd c:\dbus
  8. cmake -G "MinGW Makefiles" ..\dbus-1.4.0\cmake -DDBUS_USE_EXPAT=on
  9. mingw32-make
  10. Add c:\dbus\bin to your path.
  11. Edit c:\qt\4.7.1\src\dbus\dbus.pro:
    win32 {
        wince*:LIBS_PRIVATE += -lws2
        else:LIBS_PRIVATE += -lws2_32 \
        -ladvapi32 \
        -lnetapi32 \
        -luser32
        CONFIG(debug, debug|release):LIBS_PRIVATE += -ldbus-1 -Lc:/dbus/bin
        else:LIBS_PRIVATE += -ldbus-1 -Lc:/dbus/bin
        INCLUDEPATH += c:/dbus-1.4.0 c:/dbus
    }
    
  12. You don’t need to build QtDBus separately to begin with the way I do here (step 13) — but it’s much faster to do that and know it’s working than it is to start the configure / mingw32-make step, walk away, and find out an hour later that it died someplace in the middle because you messed up the path to dbus or something.

  13. Start a Qt Command Shell.
  14. cd c:\qt\4.7.1\src\dbus && qmake && mingw32-make
  15. cd ..\.. && configure -dbus && mingw32-make

Your mileage may vary. I seem to remember fixing at least one compilation error in dbus at one point, but don’t remember precisely where or why. It wasn’t hard to do, though — something about a missing argument.

Stay tuned for some Qt tips!

Over the last several months, I’ve been really busy with my coauthor getting my latest book, Beginning Nokia Apps Development finished. Although not a project sponsored by my employer, it’s been exciting working on a book that connects so closely with what I do in the office day-to-day, and my management at Nokia Research Center has been very supportive of the effort, letting me do some of the last-minute edits and tweaks as the schedule got down to the wire. Now that we’re in the last phases of editing (galley proofs, anyone?), I’ve got more time to talk about what I’ve been doing with Qt on mobile devices and other stuff.

As a result, expect a slow but steady stream of posts here in the next several weeks, largely focused on small tips and tricks for working with Qt, especially the Qt Meta-Object Language (QML).

Finally… updates to the Mac OS X eReader scripts!

I’ve been using Kovid Goyal’s excellent Calibre application for a few months now to manage ebooks on my Sony eReader. It’s a great tool for managing my library of ebooks, and can also automatically download, convert, and install news from any RSS feed you throw at it. I’ve converted a lot of stuff I had in LIT format using it, and been very pleased with Kovid’s work overall.

At the same time, I’ve used Feedbooks as a source for ebooks, especially classic literature. Feedbooks provides all the formats you’d expect, and its ePub output looks really nice on the eReader. It also provides reading lists so I can tag content I want to download later, and has the makings of a social network for bookworms through those lists. I frequently download ePubs from Feedbooks and drop them on the eReader via Calibre, so I can keep both current events and literature on the device.

Last night, I took a look at the News section of Feedbooks, and was I impressed! They have a lot of RSS feeds they’re aggregating and formatting, and it looks great on the eReader. Sadly, since I’m using Mac OS X, I can’t use their News Stand application to automate content downloads when I attach the eReader.

But I liked the idea of getting the news formatted content straight from a server; not only would it be faster, but I wouldn’t have to either leave Calibre running or launch it every morning. Since automating the download and installation of Feedbooks news content is an extension of what I’d already done previously for PDF printing, I figured it was time to do a bit more hacking.
Continue reading Finally… updates to the Mac OS X eReader scripts!

Whither thee launchd?

Unfortunately, for a number of reasons, I’ve been far too busy to follow up my previous post to use Mac OS X’s launchd to detect when the Sony eReader connects. There’s a lot of good launchd stuff on the Web, though, and it promises to be pretty easy once I sit down and actually write a plist for it.

In the mean time, here’s a revised script for moving the printed PDF files from a spooling directory to the eReader on connection. The setup is the same as before; simply kick the script with a Folder Action.

#!/usr/bin/env sh
PATH=/opt/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
export PATH

readermain="/Volumes/PRS 700"
readercard="/Volumes/700 CARD"
spool="/Users/kf6gpe/.cups-pdf-spool"
pdfdest="$readercard/PDFs/"

growl()
{
    message="$*"
    which growlnotify > /dev/null
    if [ $? -eq 0 ]; then
        echo $message | growlnotify -t "eReader" -p -2 -a /Applications/Preview.app
    fi
}

if [ -f "/tmp/prs-busy" ]; then
    exit 0;
fi

if [ -d "$readercard" ]; then
    touch /tmp/prs-busy
    growl "Device detetected.";
    for f in `ls $spool/*.pdf`
    do
        cp $f "$pdfdest"
        if [ $? -eq 0 ]; then
            rm -f $f
            growl "Transferred `basename $f`."
        fi
    done
    growl "PDF transfer complete.";
    rm /tmp/prs-busy
else
    rm /tmp/pre-busy 2>&1 /dev/null
fi
exit 0

The changes are pretty self-explanatory. In brief:

  1. Have use Preview’s icon, in case Calibre isn’t installed.
  2. Only look for the eReader’s card; there’s really no reason to look for both volumes. 
  3. Use the lock file /tmp/prs-busy to ensure that the actual movement of the files doesn’t occur while it’s actually running. 

Of these changes, (3) was certainly the most important, because if you mounted another volume (say, a digital camera) while the script was doing things, weird things could happen. In practice, I never saw anything amiss, but this makes me sleep better at night.

Better printing to the Sony eReader using CUPS-PDF

After the recent work I’ve done integrating my Sony eReader with Mac OS X, I still wanted to be able to optimize page layout for the device. 

After some digging around and realizing that I don’t have ppdc I grabbed a PPD file for a generic Postscript printer and started hacking. 

Download ereader.ppd

The results work pretty well, although I see goofy margins from some applications such as TextMate.

Next up? Ditching the Folder Action script I wrote about yesterday in favor of launchd.

Improving Interaction Between the Sony eReader and Mac OS X

I have always read a ridiculous amount. Sadly, in recent years as I’ve taken greater advantage of resources such as the Association for Computing Machinery‘s Digital Library, what that really means is that I print a lot.  There’s a definite advantage to paper; you can stick it in your bag, or put your feet up and lean back more so than with a laptop or desktop PC. At the same time, I don’t archive what I read on paper; I either make notes citing the papers I’ve read, or if the paper is really important to me, I archive a copy of the PDF itself. As a result, my professional reading workflow is one of researching, printing, reading, and recycling the results. This is a tremendous waste of paper.

While I’ve tried various ebook solutions on PDAs over the years, I’ve never been particularly happy with PDF handling on mobile devices.  I’ve watched with interest the growing market for ebooks on devices including the Sony eReader and the Amazon Kindle, although until recently neither has had particularly good PDF handling either.

Last month I laid hands on a Sony eReader, and really liked what I saw. PDF presentation with later firmware in the PRS 505 is much improved over previous firmware releases, and both the PRS 505 and PRS 700 support Secure Digital cards. As USB devices, these products show up as a mass storage device when mounted on Mac OS X. As an added bonus, Kovid Goyal’s Calibre application supports both format translation and automatic harvesting of Web content from RSS feeds. I have to admit that it’s pretty spiffy to get up in the morning, grab the eReader from my desk and have the latest content from both The New York Times and The Economist at my fingertips. In conjunction with the large number of freely available books from Feedbooks, it’s a leisure reader’s dream.

Although the eReader’s appearance as a mass storage device in the Mac OS X Finder is useful, I quickly tired of downloading papers and manually copying them to the device. Intuitively, it seemed that what I wanted to be able to do was to treat the eReader as another printer.

Upon reflection, this idea is quite compelling. It doesn’t require me to change my work flow at all; moreover, there is something cool about the idea of an eInk device being directly accessible as a printer.

Continue reading Improving Interaction Between the Sony eReader and Mac OS X

Capturing Stack Crawls in Application Emulation under Win32

I have always freely admitted that Win32 development is not my thing. What started as a religious conviction (UNIX being what it was when I was a lad…) and later became first a lack of opportunity and exposure and most recently a conscious choice to keep my skills marketable in niche markets, I’ve just done very little work on the platform. Sure, during the heyday of Windows CE (now Windows Mobile) I learned enough to talk with skilled Win32 developers transitioning to Windows CE, and successfully managed WinCE-based development projects, but that’s not engineering. More recently, I wrote a book on developing applications for eBay that included examples in C#, but that’s different. C# is managed code, and anyway, writing still isn’t really engineering.

Nonetheless, much of my career has been spent working within the confines of the Win32 platform. Many mobile platforms such as Qualcomm BREW stage their development environments on top of Win32, providing emulators in which the application you’re writing is linked in as a Win32 DLL. While this has its limitations—emulation isn’t simulation, etc—it’s definitely a good way to go for platform vendors, because the Win32 tool chain is well-understood by countless developers, even if the intricacies of a specific mobile platform isn’t.

At the day job, I recently came across a need to track down a number of memory leaks in a C-based application for Qualcomm BREW. The code had already been written, so it wasn’t feasible to go back and implement a wrapper to the memory management utilities that tracked allocation and free operations using the __FILE__ and __LINE__ macros; even if I could, I also needed to track down a few BREW component instance leaks, which would be considerably more complex to track using wrappers. Because of the need to determine component instance leaks and how the BREW simulator manages its own heap (providing leak reporting, at least), tools like Purify weren’t really an option either.

By hand-editing the include files that define BREW’s object creation and memory allocation routines (AEEShell.h and StdLib.h) I could directly hook the memory allocations, giving me an opportunity to determine the source of the leaks…if only I knew what portions of the code were performing the allocations. Using a dictionary matching pointers to memory or components and information about how those regions re allocated isn’t my idea; it’s hardly new, and frankly, I don’t know where it originated. It is a good idea, though, because it makes the work go a lot faster. By instrumenting allocations to track where in the code the allocation is being made (typically inserting that information in a dictionary keyed by the pointer to the region or component being allocated) and instrumenting the deallocation to release those records, an examination of the resulting dictionary after a run gives you a list of points in your code that may be allocating resources that aren’t freed later. The technique isn’t perfect, of course, especially if you pass references to memory or components around to other systems that you can’t instrument, but it’s a good start. I had a dictionary implementation that I could use to store information about each allocation referenced by pointer; if I could get stack frame data at the points where I hooked the allocator and deallocators, the work would become much easier.

I knew that I should be able to programmatically get stack trace information running under the simulator on Win32, although I had no idea how. Oddly, this doesn’t seem to be common knowledge, either, after pinging a few colleagues on the subject. However, after more reading of MSDN articles and googling than I care to admit, I came across Jochen Kalmbach’s StackWalker class, a C++ class that provides an utterly simple interface to obtain a stack crawl anywhere in your Win32 application. Great stuff, and I’m glad I found it! Using it was far simpler for me than trying to wrap my head (and some new code) around the debugger API that Microsoft provides.

I was quickly able to modify it to meet our needs to run within the Qualcomm BREW simulator and provide stack dumps to a log file; after those changes and a bit of truly shameless hacking on private copies of AEEStdlib.h and AEEShell.h, leak tracking became much easier. At some point I plan on providing a simple BREW component for simulator-only use that incorporates his code and provides much of the same functionality; it may make a good article or blog post in the future. In the mean time, I hope that simply describing the process here helps someone.

This experience provides a situation supporting my belief that a general interest in computing and computing platforms is key to being a good software engineer; if I’d thought too narrowly about the problem as being inherent to an application running on Qualcomm BREW, I might never have decided to add a bit of simulation-specific code to automate the bookkeeping behind my debugging.

Using Common Lisp on Mac OS X

I’ve been a Lisp nut for years. I was first exposed to Lisp on my TRS-80, when I was about thirteen; Randy Beer had written a Lisp introduction in the March ’83 issue of 80 Micro, and I remember reading it again and again. I’ve used various flavors of Lisp for exploratory prototyping programming over the years, and have enjoyed using both Scheme and Common Lisp.

Getting a dialect of Common Lisp running on Mac OS X isn’t hard — in fact, if you’re just setting out, an excellent choice is LispWorks Personal Edition. I’ve recently gotten to the point, however, where I’ve wanted to do some work with the Common Lisp Interface Manager, which isn’t supported in LispWorks Personal Edition under Mac OS X, and set out to configure a Common Lisp installation on my MacBook from the ground up.

It wasn’t difficult, although it took some Googling to get all the pieces together; shortly after I finished, someone on the Bay Area Functional Programmer‘s mailing list asked about running Common Lisp on Mac OS X, and I put together my notes on the topic and replied. The list is fairly small — less than 300 members — and I promised them and myself that I’d organize the notes and provide them in a more accessible location.

What follows is a step-by-step installation guide to installing Steel Bank Common Lisp (SBCL) and McCLIM on a PowerBook G4; I undertook this from the initial notes I took configuring the MacBook. I chose SBCL because it’s well-supported by the open source community and works well with McCLIM; I have nothing against other Common Lisp implementations, including Clozure. 

A word of warning is in order: I’m comfortable with Common Lisp, but relatively unfamiliar with how Common Lisp programmers handle package distribution. I get the basic idea behind ASDF, of course, but I’m not seasoned in its use. Consequently, I had a get-things-working-and-clean-up-later mentality when I undertook my first SBCL-McCLIM configuration, and this largely remained when I wrote what follows. Other Lisp developers may have better ways to organize their working environments, and I’d welcome positive comments (drop me an email, and we’ll figure out how to incorporate your feedback).

Starting out, you should have a relatively up-to-date Mac OS X box (I’ve done this on Mac OS X 10.4.x and 10.5.x systems). When you’re done, you will have installed Carbon Emacs, SLIME, SBCL, and McCLIM configured to work with the X Windows server Mac OS X provides, along with darcs. 

Continue reading Using Common Lisp on Mac OS X

The obligatory first post…

Installing and configuring WordPress has been on my personal to-do list for an absurdly long amount of time. Back in February 2002, I started a personal blog on LiveJournal, which I kept up-to-date on an intermittent basis. I’d always planned on using it both as a professional soapbox and a personal journal, although it quickly became more of the latter than the former. In recent years, it’s largely lain fallow, a victim of benign neglect as I tackle professional writing and engineering commitments.

With the imminent publication of my latest book, Beginning Javaâ„¢ ME Platform (Beginning from Novice to Professional), it’s again apparent that I should put more effort into reaching out to both those I know and those who read my work. Not only is this an important part of publicity for me as an author, but it’s also a service to you, my readers, because it gives me an opportunity to keep you up to date. I only hope that I am more successful in keeping you up to date than I am self-publicity, something I have generally neglected. 

Hence, this blog.

I’m not certain what all I will post here, or how frequently I will post. You can certainly expect any updates or feedback on my books, of course, but I’m also planning on using this as a working notebook for other technical musings. I don’t have any plans to become a career blogger and make this a central part of my professional activities; to be frank I think there’s too much of that on the Internet already! Instead, I think this is going to fill a very narrow nice, with me posting the occasional update to a previous (probably paper) publication, various tips and tricks I’ve picked up in my engineering career, and possibly some engineering notes about things I’ve found difficult in the hopes that capturing it here will help others.

Thanks for stopping by!