You are here

Introducing the Popup Dropper


About a year ago we had an issue in Amarok 2 development because we wanted to be able to move portable device track access into collections (this is happening with Alejandro's GSoC project), but we couldn't figure out a good paradigm for accessing the various device specific functions. There were some other concerns too, about the right-click menus getting too overloaded, making it hard to find common functions. Finally, when people wanted to drag music to the playlist, they now had to cross the entire window, whereas before it was a quick drag and drop...a lot less mouse movement, and possibly the difference between picking the mouse up and not.

So I had a brainstorm. We have this ginormous context view area in the middle of A2. What if we could put it to good use, and allow it to act as a surrogate menu? For many people, dragging the mouse a bit to drop items on a big target is much easier than navigating small right-click menus, where it's easy to overshoot your destination and accidentally close submenus. Thus the PUD -- the PopUp Dropper -- was born. My first sketch of it is here:

(Here's the preceding page that talks about collection groups. If you like that idea, be sure to let us know at amarok@kde.org.)

The PUD actually lived for a long time in the Amarok source tree, but there were problems. One was that it tied in too tightly to the existing Amarok context view code -- something that, as that code was refactored over and over again, was painfully obvious would not work. The other was that the actual popping up and drawing was painfully slow. It seems drawing a QGraphicsView on top of another one wasn't making Qt happy. Fortunately, as of Qt 4.4, this problem has been solved.

The final nail in the coffin (related to the first one actually) is that some of the people that saw the work wanted to see it available for all of KDE to use. This approach wasn't going to work.

When Qt 4.4 hit qt-copy, I started to play around with things again. Soon enough I was addicted to making it work. I took the Drag 'n Drop Robot example and started modifying it to use the PUD library I was making. The goals: make it Qt-only, make it very customizable so it could work in any situation, and make it actually able to replace a right-click menu.

I'm happy to say that those goals have been met. Here's a list of current features:

  • Runs on top of any QWidget (theoretically, though not fully tested).
  • Two ways of creating submenus: either call addOverlay(), which essentially gives you a "clean slate" that you start afresh, and that runs on top of the current menu when show() is called, or you create a second PUD and pass it into addSubmenu() on the first, which is quite similar to the way a QMenu would be constructed.
  • Can pop or fade in/out with configurable fade timing on a per-submenu basis.
  • Background color and transparency, as well as text, is configurable on a per-submenu basis.
  • When the mouse leaves the PUD area, it disappears (or the top layer disappears, and keeping it outside makes subsequent layers disappear)...configurable.
  • The PUD items contain a PUD action, allowing for both drops (which calls triggered()) and hovers (which calls hovered())...each one individually configurable, of course.
  • The items are represented by a SVG element you pass in, along with a renderer (or the default is to use the PUD's renderer).
  • The items arrange themselves automatically (submenu offset is configurable).
  • Many more things. All of them configurable (sense a trend?).

I really wanted to make a video available, but I could get neither xvidcap, nor vnc2swf, nor captury working at all. recordmydesktop worked, but interfered with the drops, so it wouldn't work as intended. Instead, I'm making an "alpha" version of the PUD available for people to see (I had been using a local git repository, which is included in the tarball). Don't worry...despite me calling it alpha, it's quite stable (in fact, as you'll see, it's already used in Amarok). No dependencies are needed, just qmake the dragdroprobot.pro file, make, and run the dragdroprobot file. Caveats: it's not commented (see coloritem.cpp for usage examples), I know of a few bugs, it's not finished (I have several more things to add to it), there is at least one crash that I can't reproduce reliably and have not found, there are some things I need to test but have so far been unable to (such as more than one submenu layer), and note the copyrights and distribution requirements on the files -- it's a modified example from Qt. Preferably run in a Qt 4.4 environment (i.e. in a KDE trunk login) to get all the benefits of Alien, or else it might be rather slow depending on your system. But with that all said, let me know how you like it.

Finally, it's been updated in the Amarok source tree. Now that I got the submenu support working, Nikolaj has gotten it integrated. In recent builds of Amarok you can simply start dragging an item from your collection and see it in motion. Some screenshots follow. The first is showing the normal menu, the second shows the submenu that pops up when you hover over the Organize Files item (you can see the previous menu behind it, through the transparency).

So what's next? Hopefully, this will eventually make it in some way shape or form into kdelibs, assuming the API stays stable (it was written in the kdelibs style, with a d pointer and private classes), making it easy for KDE apps to take advantage of it without being an external dependency. And as it gets completed I'll be making it available separately for any Qt app out there that wants to use it (not sure what license it will be under...either GPL or BSD). For now, if you want to see the latest versions, keep your eye on the Amarok source code in the src/popupdropper directory (it has a few modifications to my "master" source simply to make it build in the Amarok source tree...specifically, adding moc file includes since it's not using qmake, and exporting PopupDropperAction).

Comments appreciated!


Continue reading "Introducing the Popup Dropper"