New QML components: IconItem

Software

Last post was about a new QML component available in Plasma workspace 4.10 with an important design pattern that comes with it: Lazy loading everywhere when possible.

Next couple of posts will be about other new and old components and the UX concept behind them.

A very important thing in Plasma is to have extremely coherent elements all across the screen, both in graphics appearance and behavior. The fact that two things together in the screen are done by two different plasmoids is something that shouldn’t really matter to the user (it’s a bit of a fail the very moment they even notice, actually). I’ll go in a future blog entry on why seamlessy melting into the environment is absolutely preferable to coming out with “clever” ideas that stick out, even if it seems counter intuitive.

Today: IconItem. From 4.10 there is a new element available in org.kde.plasma.core It’s used whenever you need to represent an icon in a plasmoid (or an active application).

This describes semantically an icon: as everything in plasma you should only describe it, and not care at all how it looks (that’s the task of the component, of the themes, of the final platform and of the global settings). Also, as common in QML, it’s just a painter, doesn’t have any event management whatsoever (so you will do it in a MouseArea for instance if needed).

To use it you just have to do:

import QtQuick 1.1
import org.kde.plasma.core 0.1 as PlasmaCore

PlamaCore.IconItem {
    width: theme.iconSizes.dialog
    height: width
    source: "go-previous"
}

And that’s it. A PlasmaCore.IconItem can load:

  • It can load: freedesktop spec icon names (like “go-previous”, or konsole”). It is the preferred way
  • QIcon instances (useful when the data comes from C++, such as a QStandardItemModel)
  • QImage or QPixmap instances (again. useful pretty much only when the data arrives from a c++ part)

Some behavioral properties:

  • If the icon name has been provided, it will try to load the “best” icon it can find: it tries first a plasma themed monochrome SVG icon from the theme. If doesn’t find it, it then falls back to the classical oxygen icons.
  • For small sizes, (from 16×16 to 64×64) it renders the icon to the nearest “right” size for which there is actually a n image for it on the disk, without trying to stretch it: no more blurry-looking icons! This is also the behavior for all panel icons in 4.10, so your panel will look way sharper.
  • If you set the property enabled to false it will look grayed-out with the same effect as all the disabled icons around KDE applications.
  • If a mouseover highlight effect is needed, set the property active to true (also a property binding like active: mouseArea.containsMouse is fine). It will have the same highlight effect as all across KDE applications.
  • State changes, like enabled/disabled or active/normal or icon changes, will have a short fade animation, that is coherent with the highlight animation of the icons in the panel, like the launcher.

So you should use it always when you have to represent a simple icon in a plasmoid. It is always preferable to the QIconItem component in org.kde.qtextracomponents (the latter should be used only when you can’t really depend from plasma).

You should not use it when your icon is actually meant to be a standalone clickable button. in this case you should either Button or ToolButton from org.kde.plasma.components. For instance, if you icon is in a delegate of a ListView and is the main “decoration” for the delegate (not a small button on a side), IconItem is the way to go, regardless if the delegate itself is clickable or not.

Internally, both Button and ToolButton of org.kde.plasma.components use IconItem to load their (optional) icon, so you are ensured a consistent look and behavior.

Let’s finish with a screenshot of an example where this new IconItem component is used: the system tray.

KDE Plasma Workspace 4.10 will have a system tray completely rewritten in QML (a lot of kudos to Dmitry for this!) and looks like this:

new system tray

Don’t see any difference? yep, that’s the point 😉 It looks exactly the same without losing any feature, it just behaves better, its layout is more reliable and the code is an order of magnitude simpler.

Btw, in this post, as well the last post by Aaron, there is also a little taste of something else… different.

6 thoughts on “New QML components: IconItem

  1. ben

    Why PlasmaCore.IconItem and not just PlasmaCore.Icon?

    The “Item” suffix seems to stem from the old Qt Graphics View naming scheme, but QtQuick has moved away from that…

    For example…

    Qt Graphics View:
    “QGraphicsRectItem
    “QGraphicsTextItem”

    Qt Quick:
    “Rectangle” (and not “RectItem”)
    “Text” (and not “TextItem”)

    Reply
  2. markg85

    In your other post i liked what you did and even intend to use it, but this one… Far from ok!

    1. You knew that i was making the exact same thing which is already working just fine and can be found here [1].

    2. You are using a animation inside the C++ part of the component. You should certainly _not_ dot that! QML shines there, let QML do the animation.

    3. This is way to complicated in source. Look at my example [1]. Oke, it’s not completely feature complete, but it’s nearly there. I only bothered to get QIcon, KIcon, QImage and QPixmap working. I didn’t need highlight stuff or other things, but that’s easy to add (as in a few lines max).

    4. Why are you doing so much size checks? That will bite you one day. Just let KIcon (or KIconLoader or whatever class it was that did the icon scaling) do the scaling stuff and just use the returned pixmap width and height for the for the rectangle that should be painted.

    5. The naming is wrong. “IconItem” gives me the idea that it’s for icons only while it can also do pixmaps. You should name it a bit more generic. I found “graphics” to be generic enough thus GraphicsItem. ImageItem would probably also work because it are all images. In fact, all that _we_both_ are trying to accomplish it recreating the QML Image element only with support for QIcon, KIcon, QImage and QPixmap.

    Sorry for criticizing you (again), but i really feel like your just duplicating efforts. You didn’t even contact me for the item i made. I could have spend a few minutes to make it feature complete compared to the one you shared here. I was considering of proposing to include my item a few days ago through the review system (which you also apparently skipped?), but decided to hold it off because it wasn’t feature complete compared to QIconItem and mine.

    [1] https://gitorious.org/porpoise/master/blobs/master/kgraphicsitem.cpp

    Reply
  3. Marco Martin

    > https://gitorious.org/porpoise/master/blobs/master/kgraphicsitem.cpp

    that looks to me more or less a copy of the old QIconItem, and as i said, different use cases.

    and no, its use is really for icons and just for icons, forces painting at the correct sizes because is about icons, manages the highlight/disable states because is about icons, prefers the svg versions because is about icons.

    the animation is inside the c++ item because otherwise i had to export a version without animation, and a version with animation, polluting the API (unfortunately is not possible to have c++ imports private to a component implementation, quite a limitation of QML I think). And no, i won’t leave it to the component users.
    the design principles are:
    * if there is an animation or not is none of plasmoid developer business
    * how big the icon gets rendered is none of plasmoid developer business
    * what the disable/highlight effects (if any) is none of plasmoid developer business
    * what icon gets loaded in particuar, besides one that represents that icon name is none of plasmoid developer business

    This class is a semantic representation of an icon, with exactly none of the look and feel details exposed to the outside (also, leaves the possibility to migrate the implementation to pure QML some day, again, what the implementation is or behaves, utterly irrelevant)

    Reply
  4. markg85

    The animation can be resolved by wrapping that element into (lets say) a “TransitionIcon” in which you have the current icon and the icon that will fade in.

    KIcon should have the perfect icons for the normal sizes already (32, 48, ….) there is absolutely no need to play with SVG there since those sizes should come from the svg files.

    Either way, you should have just used (or changed) the QIconItem class. Now there is yet another icon class.

    Reply

Comments are closed.