PDA

View Full Version : Checkable QActions (menu items) with Icons don't show check indicators.



philw
6th October 2013, 03:59
Is it true that if I add an icon to a checkable QAction, the icon is displayed INSTEAD OF the check indicator? See the accompanying image and code excerpt. Is there a way to display both? This is with Qt 4.8.5 on Windows.

9672


void IconUtils::addWindowIconActions (QMenu* parMenu, QActionGroup* actGrp)
{
actGrp->setExclusive (true);

const QStringList iconNames = windowIconNames();
const int cnt = iconNames.count();

for (int inx = 0; inx < cnt; ++inx)
{
const QString iconName = iconNames [inx];

QAction* winIconAction = new QAction (actGrp);
winIconAction -> setObjectName (iconName);
winIconAction -> setIcon (windowIconPixmap (iconName));
winIconAction -> setData (QVariant (inx));
winIconAction -> setCheckable (true);
winIconAction -> setChecked (inx == 0);

parMenu->addAction (winIconAction);
}
}
Thank you in advance,
Phil Weinstein, CADSWES

anda_skoa
6th October 2013, 10:07
Is it true that if I add an icon to a checkable QAction, the icon is displayed INSTEAD OF the check indicator?
In your case that is true.

More precisely: it depends on the widget style.
Some styles display the check indicator separately independent of whether an icon is set or not.
Some other styles, like in your case the Windows style, show the icon in pressed/released state instead.

Cheers,
_

philw
7th October 2013, 02:48
Anda, thanks. I took your response to mean that the various widget styles would all have the same problem. I did experiment with that anyway. Here are some screenshots, with each of the available Window Styles in our Qt 4.8.5 build on Windows 7.

(1) Animated ...
(2) Montage ...

96749675

(BTW, I don't see any difference between the three Windows styles).

philw
8th October 2013, 07:46
I DID ACCOMPLISH THIS — showing a CHECK INDICATOR (exclusive, radio-button type) on checkable QAction menu items having Icons. I’m creating the check indicator graphic myself — augmenting the application-level icon QPixmaps. BELOW are the three pieces of code which implement this.

SEE RESULT EXAMPLE:

9677

http://cadswes2.colorado.edu/~philw/2013/icons/WindowIcon/2013-10-07a.png

CODE SAMPLES BELOW:

#1 class QMenuIconSizeProxyStyle : public QProxyStyle … allows a QMenu to have wider-than-normal icons on menu items (QActions).

#2 QIcon checkMenuIcon (const QPixmap& sourcePmap, QSize& iconSize) … Create a two-state QIcon from a source QPixmap, adding on a check indicator graphic

#3 void addWindowIconActions (QMenu* menu, QActionGroup* actGrp) … builds a menu of exclusive items for a list of application-level icons. (uses both items above).


// QProxyStyle sublass to be installed on a QMenu needing to support
// wider-than-usual icons. It overrides the QStyle::PM_SmallIconSize
// property with the width of the QSize provided by the client.

class QMenuIconSizeProxyStyle : public QProxyStyle
{
private:
QSize _iconSize; // note: only the width is currently used.

public:
QMenuIconSizeProxyStyle() : QProxyStyle() {}

void setIconSize (const QSize& iconSize) { _iconSize = iconSize; }

int pixelMetric (QStyle::PixelMetric metric,
const QStyleOption* option=NULL,
const QWidget* widget=NULL) const override
{
if (metric == QStyle::PM_SmallIconSize)
return (_iconSize.width());

// Return base class result
return QProxyStyle::pixelMetric (metric, option, widget);
}
};


QIcon checkMenuIcon (const QPixmap& sourcePmap, QSize& iconSize)
{
// Create and return a QIcon composed from two modified versions of
// the given "source" QPixmap -- for ON and OFF states -- suitable for
// checkable QActions (menu items) having an icon. [In Qt 4.8.5,
// checkable QActions with icons don't show a drawn check indicator].
//
// The computed pixmaps have additional space to the left where a
// bullet (filled black circle) is drawn on the "ON" image. This
// appearance is intended for exclusive (radio button type)
// QActions (menu items) -- and looks like the Cleanlooks style.
//
// The QSize of the computed pixmaps (including a check indicator area)
// is returned in the iconSize reference parameter.

const QSize srcSize = sourcePmap.size();
const int srcWid = srcSize.width();
const int srcHgt = srcSize.height();
const int indWid = srcHgt; // indicator width

iconSize = QSize (srcWid + indWid, srcHgt);
QPixmap iconPmap (iconSize);
iconPmap.fill (Qt::transparent);

QPainter painter (&iconPmap);
painter.drawPixmap (indWid, 0, sourcePmap);

QIcon retIcon;
retIcon.addPixmap (iconPmap, QIcon::Normal, QIcon::Off);

const double radius (indWid / 8.0);
const QPointF cen (indWid/2.0, srcHgt/2.0);
painter.setBrush (QBrush (Qt::black));
painter.drawEllipse (cen, radius, radius);

retIcon.addPixmap (iconPmap, QIcon::Normal, QIcon::On);
return (retIcon);
}


// Build a QMenu with checkable (mutually exclusive) icon QActions.
// The 'checkMenuIcon' utility is used to add a "radio button"-type
// check indicator to the left of each source QPixmap.

void addWindowIconActions (QMenu* menu, QActionGroup* actGrp)
{
actGrp->setExclusive (true);
QSize maxIconSize;

// Create a checkable Icon QAction (menu item) for each available
// application window icon; insert into the given QMenu and QActionGroup.

const QStringList iconNames = windowIconNames();
const int cnt = iconNames.count();

for (int inx = 0; inx < cnt; ++inx)
{
const QString iconName = iconNames [inx];

QSize iconSize;
const QPixmap pmap = windowIconPixmap (iconName);
const QIcon menuIcon = checkMenuIcon (pmap, iconSize); // SEE ABOVE
maxIconSize = maxIconSize.expandedTo (iconSize);

QAction* winIconAction = new QAction (actGrp);
winIconAction -> setObjectName (iconName);
winIconAction -> setIcon (menuIcon);
winIconAction -> setData (QVariant (inx));
winIconAction -> setCheckable (true);
winIconAction -> setChecked (false);

menu->addAction (winIconAction);
}

// Instantiate a QProxyStyle for a modified QStyle::PM_SmallIconSize
// and install that on the QMenu. SEE PRIOR FUNCTION.

QMenuIconSizeProxyStyle* proxyStyle = new QMenuIconSizeProxyStyle;
proxyStyle->setIconSize (maxIconSize);
menu->setStyle (proxyStyle);
}

anda_skoa
11th October 2013, 10:23
Anda, thanks. I took your response to mean that the various widget styles would all have the same problem.


Yes and no :)

The style will display the checked state such that it fits into the targetted look&feel. If the system's visualisation for check marks on action with icons is to show the icon in a "pressed" state, then this is what the style will draw as well.



(BTW, I don't see any difference between the three Windows styles).

Then it is most likely that Windows applications do not normally show a check marker along side the icon but show the checked state by changing the icon's visualization instead.

KDE's Oygen style for example uses a separate check marker, independent of whether there is an icon or not.

Cheers,
_