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:
2013-10-07a.png
http://cadswes2.colorado.edu/~philw/...013-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 QWidget* widget
=NULL) const override
{
if (metric
== QStyle::PM_SmallIconSize) return (_iconSize.width());
// Return base class result
return QProxyStyle::pixelMetric (metric, option, widget);
}
};
// 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);
}
};
To copy to clipboard, switch view to plain text mode
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
);
iconPmap.fill (Qt::transparent);
painter.drawPixmap (indWid, 0, sourcePmap);
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);
}
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);
}
To copy to clipboard, switch view to plain text mode
// 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.
{
actGrp->setExclusive (true);
// Create a checkable Icon QAction (menu item) for each available
// application window icon; insert into the given QMenu and QActionGroup.
const int cnt = iconNames.count();
for (int inx = 0; inx < cnt; ++inx)
{
const QString iconName
= iconNames
[inx
];
const QPixmap pmap
= windowIconPixmap
(iconName
);
const QIcon menuIcon
= checkMenuIcon
(pmap, iconSize
);
// SEE ABOVE maxIconSize = maxIconSize.expandedTo (iconSize);
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);
}
// 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);
}
To copy to clipboard, switch view to plain text mode
Bookmarks