PDA

View Full Version : "Proxy Style" does not work!



Dimon
12th August 2009, 11:39
Hi everybody!

I'm trying to use a "Proxy style" technique in order to change menu icon size and faced a problem. When I use a direct inheritance from the platform-specific style, all is OK:

class MyStyle : public QWindowsXPStyle
{
Q_OBJECT

public:
explicit MyStyle() : QWindowsXPStyle()
{
}
int pixelMetric(PixelMetric metric, const QStyleOption* option = 0, const QWidget* widget = 0) const
{
if (metric == PM_SmallIconSize)
{
return 32;
}
else
return QWindowsXPStyle::pixelMetric(metric, option, widget);
}
};
Main:

QApplication app(argc, argv);
MyStyle* pNewStyle = new MyStyle();
app.setStyle(pNewStyle);

The code above is working properly, changing the menu icon size to 32x32. Then I tried to use "Proxy style", but it does not work. Here is the implementaion.
Proxy class:

class ProxyStyle : public QStyle
{
public:
explicit ProxyStyle(const QString& style);
~ProxyStyle();
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget = 0) const;
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = 0) const;

// Other virtual methods declarations ...

private:
QStyle* pStyle;
};

ProxyStyle::ProxyStyle(const QString& style)
: QStyle(), pStyle(QStyleFactory::create(style))
{
}
ProxyStyle::~ProxyStyle()
{
delete pStyle;
}
void ProxyStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
{
pStyle->drawComplexControl(control, option, painter, widget);
}

void ProxyStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
pStyle->drawControl(element, option, painter, widget);
}

// Other virtual methods implementations are similar ...

Custom style class:

class MyStyle : public ProxyStyle
{
Q_OBJECT

public:
explicit MyStyle(const QString& baseStyle) : ProxyStyle(baseStyle)
{
}
int pixelMetric(PixelMetric metric, const QStyleOption* option = 0, const QWidget* widget = 0) const
{
if (metric == PM_SmallIconSize)
{
return 32;
}
else
return ProxyStyle::pixelMetric(metric, option, widget);
}
};
Main

QApplication app(argc, argv);
MyStyle* pNewStyle = new MyStyle(app.style()->objectName());
app.setStyle(pNewStyle);

I noticed in debugger, that MyStyle::pixelMetric() method is called before the first appearance of each menu, returned the proper size (32), but icons in menu remains the same (16x16).
Platform details: Qt 4.5.1, WinXP SP3, Visual C++ 2005 SP1.

Can anybody help me?
Thanks in advance.

caduel
12th August 2009, 12:15
this is limitation of the proxy pattern:
once the proxy has delegated (aka called) something to the "proxied" style, that style will call only its own methods.
I.e. overriding a virtual method does not help, as there are two classes involved - each with its own virtual method lookup table. Once you have "stepped into the realm" of the proxied class, there is no way back as that class does not know about the proxy and as you have not subclassed the real style, virtual methods don't help.

If you find a way about that problem, I'd be interested, too.
I doubt there is one, though. (Maybe with templates, if it is ok that the proxy works only with a set of styles defined at compile time.)

HTH

Dimon
12th August 2009, 16:30
Thank you, I have missed this detail! Tracing into Qt src I noticed, that PixelMetric() called
from DrawControl(). Of cause, after DrawControl() was delegated to the "proxied" style, it
can call only PixelMetric() implementation of this style (not my overriden PixelMetric()
implementation). In My case I should override DrawControl(), that is too complicated. I
don't see elegant solution at this time, and I'll return to use a direct inheritance
from the platform-specific styles.

Thank you for participation.

toutarrive
18th February 2010, 11:20
have a look at this :
http://labs.trolltech.com/blogs/2009/06/05/cross-platform-code-and-styles