Lacking a nice way to do this, I found an ugly way to do it... the following code seems to work well enough for me under MacOS/X and Windows, at least. (I haven't tried it under other OS's but I expect it would work elsewhere as well):
#include <QComboBox>
#include <QIdentityProxyModel>
#include <QStandardItemModel>
#include <QProxyStyle>
static const char * shortLabels[] = {"mS", "f", "m", [... and so on...] };
static const char * longLabels[] = {"milliseconds", "feet", "meters", [... and so on...] };
// A wrapper-facade data-model object that will provide the long label strings, but only when appropriate
class LongLabelsProxyModel : public QIdentityProxyModel
{
public:
LongLabelsProxyModel(QAbstractItemModel * source, QObject * parent = 0) : QIdentityProxyModel(parent), forceShortLabelsCounter(0)
{
setSourceModel(source);
}
virtual QVariant data(const QModelIndex &index, int role) const
{
return ((forceShortLabelsCounter == 0)&&((role == Qt::DisplayRole)||(role == Qt::EditRole)))
? QVariant(QString(longLabels[index.row()])) :
QIdentityProxyModel::data(index, role);
}
void BeginForceShortNames() {forceShortLabelsCounter++;}
void EndForceShortNames() {forceShortLabelsCounter--;}
private:
int forceShortLabelsCounter;
};
#ifndef __APPLE__
// Under MacOS/X, this class isn't necessary, because OS/X uses a native/non-Qt popup widget.
// For other OS's, however, we need to make the Qt popup widget wider so the long labels can be fully visible
class WiderPopupProxyStyle : public QProxyStyle
{
public:
WiderPopupProxyStyle(QStyle * baseStyle) : QProxyStyle(baseStyle) {/* empty */}
virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const
{
QRect r = QProxyStyle::subControlRect(cc, option, sc, widget);
if ((cc == QStyle::CC_ComboBox)&&(sc == QStyle::SC_ComboBoxListBoxPopup)) r.setWidth(r.width()*2);
return r;
}
};
#endif
// My customized combo-box class that will show long strings in the popup menu
class DelayUnitsComboBox : public EnumComboBoxComponent
{
public:
DelayUnitsComboBox(QWidget * parent = NULL ) : QComboBox(parent)
{
#ifndef __APPLE__
// otherwise the popup list is the same width as the combo box
// itself, which isn't wide enough to see the long strings
setStyle(new WiderPopupProxyStyle(style()));
#endif
setModel(new LongLabelsProxyModel(new QStandardItemModel(0, 1, this), this));
// Officially populate the QComboBox with the short labels
for (int i=0; i<((sizeof(shortLabels)/sizeof(shortLabels[0])); i++) addItem(shortLabels[i]);
}
// overridden so that when drawing the actual QComboBox, we still use the shorter names
virtual void paintEvent(QPaintEvent * p)
{
LongLabelsProxyModel * llpm = static_cast<LongLabelsProxyModel*>(model());
llpm->BeginForceShortNames();
EnumComboBoxComponent::paintEvent(p);
llpm->EndForceShortNames();
}
};