page x of y using QPrinter - c++

im generating a pdf file from html code using qt:
QTextDocument *document = new QTextDocument();
document->setHtml(htmlContent);
QPrinter printer(QPrinter::HighResolution);
printer.setPageSize(QPrinter::A4);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("filename.pdf");
document->print(printer);
Is it possible to have the page information "Page X of Y" instead of only the page number? If yes, how?

The solution I propose is based on this code. I have added the necessary support for HighResolution
static const int textMargins = 12; // in millimeters
static const int borderMargins = 10; // in millimeters
static double mmToPixels(QPrinter& printer, int mm)
{
return mm * 0.039370147 * printer.resolution();
}
static void paintPage(int pageNumber, int pageCount,
QPainter* painter, QTextDocument* doc,
const QRectF& textRect, qreal footerHeight)
{
painter->save();
// textPageRect is the rectangle in the coordinate system of the QTextDocument, in pixels,
// and starting at (0,0) for the first page. Second page is at y=doc->pageSize().height().
const QRectF textPageRect(0, pageNumber * doc->pageSize().height(), doc->pageSize().width(), doc->pageSize().height());
// Clip the drawing so that the text of the other pages doesn't appear in the margins
painter->setClipRect(textRect);
// Translate so that 0,0 is now the page corner
painter->translate(0, -textPageRect.top());
// Translate so that 0,0 is the text rect corner
painter->translate(textRect.left(), textRect.top());
doc->drawContents(painter);
painter->restore();
QRectF footerRect = textRect;
footerRect.setTop(textRect.bottom());
footerRect.setHeight(footerHeight);
painter->drawText(footerRect, Qt::AlignVCenter | Qt::AlignRight, QObject::tr("Page %1 of %2").arg(pageNumber+1).arg(pageCount));
}
static void printDocument(QPrinter& printer, QTextDocument* doc)
{
QPainter painter( &printer );
doc->documentLayout()->setPaintDevice(&printer);
doc->setPageSize(printer.pageRect().size());
QSizeF pageSize = printer.pageRect().size(); // page size in pixels
// Calculate the rectangle where to lay out the text
const double tm = mmToPixels(printer, textMargins);
const qreal footerHeight = painter.fontMetrics().height();
const QRectF textRect(tm, tm, pageSize.width() - 2 * tm, pageSize.height() - 2 * tm - footerHeight);
doc->setPageSize(textRect.size());
const int pageCount = doc->pageCount();
bool firstPage = true;
for (int pageIndex = 0; pageIndex < pageCount; ++pageIndex) {
if (!firstPage)
printer.newPage();
paintPage(pageIndex, pageCount, &painter, doc, textRect, footerHeight );
firstPage = false;
}
}
Example:
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QTextDocument *document = new QTextDocument();
QTextCursor cursor(document);
QTextBlockFormat blockFormat;
for(int i=0; i < 10; i++){
cursor.insertBlock(blockFormat);
cursor.insertHtml(QString("<h1>This is the %1 page</h1>").arg(i+1));
blockFormat.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore);
}
QPrinter printer(QPrinter::HighResolution);
printer.setPageSize(QPrinter::A4);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("filename.pdf");;
printDocument(printer, document);
return app.exec();
}

The above Is a good solution but will break your QTextDocument object if you work with it after the print. I have a QTextDocument that is a member of a dialog and when the calling function that provided the Printer (paintDevice) loses scope it crashes the document.
I suggest getting a poiner of the current paintDevice at the start of the function then restoring it at the end.
static void printDocument(QPrinter& printer, QTextDocument* doc)
{
QPaintDevice * oldDevice=doc->documentLayout()->paintDevice();
doc->documentLayout()->setPaintDevice(&printer);
doc->documentLayout()->setPaintDevice(oldDevice);
}

Related

How to use QPainter::setTransform in paint() in Qt?

I have a simple QGraphicsView with text written over it.That text is wrapped under a bounding rect. I have truncated a text using QFontMetrics::elidedText.
When initially view gets loaded, it shows all truncated text properly. But when I zoom-in only few truncated text gets visible. If for few more times I zoomed-in, then some times it shows all the truncated text and some times , it never shows any truncated text.
Before truncated text code gets added, zoom-in was working properly.
widget.cpp
void widget::ZoomIn()
{
double scaleFactor = 1.1;
view->scale(scaleFactor,scaleFactor);
}
void Widget::on_textButton_clicked()
{
//logic to get string s and its co-ordinates firstPos and secondPos
Text* t = new Text() ;
QGraphicsTextItem* text = t->drawText(s,firstPos,secondPos,50,40);
scene->addItem(text);
}
Text.cpp
Text::Text(const QString &text,int left,int top,int width,int height)
: QGraphicsTextItem (text),currentString(text),
Left(left),Top(top),Width(width),Height(height)
{}
Text::Text(){}
QGraphicsTextItem *Text::drawText(QString s, int left,int top,int width,int height)
{
QGraphicsTextItem *text = new Text(s,left,top,width,height);
return text;
}
void Text::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
QFont defaultFont = QApplication::font();
QFontMetrics fm = QFontMetrics(defaultFont);
QRect rect = QRect(Left,Top,Width,Height);
QString elidedText = fm.elidedText(currentString, Qt::ElideLeft,rect.width());
QTransform trans = view->transform();
QTransform prevTrans;
painter->setTransform(trans);
painter->drawText(rect,Qt::AlignRight,elidedText);
painter->setTransform(prevTrans);
}
I understood that, in zoom-in I am changing transformation and painter is drawing on old transformation. So I have to take transformation from view and set it with painter then drawText() and then set painter transformation as previous transformation.
I did , but still problem persist.

How to get Image pixel position loaded in QGraphicsView - Strange MapToScene() behaviour

I am originally loading image in QGraphicsView and using this method for basic zoom out and zoom in functionality.
However, I am unable to retrieve actual image pixel position using mapToScene functionality in eventFilter function of Graphics_view_zoom class. The below code produces behaviour exactly as windows photo viewer zooming only selected region.
MapToScene() returns same Point as mouse event position.
Here is the class which deals with zooming.
#include "Graphics_view_zoom.h"
#include <QMouseEvent>
#include <QApplication>
#include <QScrollBar>
#include <qmath.h>
Graphics_view_zoom::Graphics_view_zoom(QGraphicsView* view)
: QObject(view), _view(view)
{
_view->viewport()->installEventFilter(this);
_view->setMouseTracking(true);
_modifiers = Qt::ControlModifier;
_zoom_factor_base = 1.0015;
}
void Graphics_view_zoom::gentle_zoom(double factor) {
_view->scale(factor, factor);
_view->centerOn(target_scene_pos);
QPointF delta_viewport_pos = target_viewport_pos - QPointF(_view->viewport()->width() / 2.0,
_view->viewport()->height() / 2.0);
QPointF viewport_center = _view->mapFromScene(target_scene_pos) - delta_viewport_pos;
_view->centerOn(_view->mapToScene(viewport_center.toPoint()));
emit zoomed();
}
void Graphics_view_zoom::set_modifiers(Qt::KeyboardModifiers modifiers) {
_modifiers = modifiers;
}
void Graphics_view_zoom::set_zoom_factor_base(double value) {
_zoom_factor_base = value;
}
bool Graphics_view_zoom::eventFilter(QObject *object, QEvent *event) {
if (event->type() == QEvent::MouseMove) {
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
QPointF delta = target_viewport_pos - mouse_event->pos();
// Here I want to get absolute image coordinates
if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5) {
target_viewport_pos = mouse_event->pos();
target_scene_pos = _view->mapToScene(mouse_event->pos());
}
} else if (event->type() == QEvent::Wheel) {
QWheelEvent* wheel_event = static_cast<QWheelEvent*>(event);
if (QApplication::keyboardModifiers() == _modifiers) {
if (wheel_event->orientation() == Qt::Vertical) {
double angle = wheel_event->angleDelta().y();
double factor = qPow(_zoom_factor_base, angle);
gentle_zoom(factor);
return true;
}
}
}
Q_UNUSED(object)
return false;
In mainwindow.cpp,
I am creating object of this class and loading an image as below:
m_GraphicsScene = new QGraphicsScene();
pixmapItem = new QGraphicsPixmapItem();
m_GraphicsScene->addItem(multiview[i].pixmapItem);
view_wrapper = new Graphics_view_zoom(ui->GraphicsView);
ui->GraphicsView->setScene(multiview[i].m_GraphicsScene);
pixmapItem->setPixmap(QPixmap::fromImage("img.jpg"));
multiview[view].m_GraphicsView->fitInView(QRectF(0,0,640,320),Qt::KeepAspectRatio);
Can anyone help with how do I achieve this ?
Keep in mind that the scaling you use only scales the scene, not the items. Given this, the position of the pixel can be obtained, so the algorithm is:
Obtain the mouse position with respect to the QGraphicsView
Transform that position with respect to the scene using mapToScene
Convert the coordinate with respect to the scene in relation to the item using mapFromScene of the QGraphicsItem.
Considering the above, I have implemented the following example:
#include <QtWidgets>
#include <random>
static QPixmap create_image(const QSize & size){
QImage image(size, QImage::Format_ARGB32);
image.fill(Qt::blue);
std::random_device rd;
std::mt19937_64 rng(rd());
std::uniform_int_distribution<int> uni(0, 255);
for(int i=0; i< image.width(); ++i)
for(int j=0; j < image.height(); ++j)
image.setPixelColor(QPoint(i, j), QColor(uni(rng), uni(rng), uni(rng)));
return QPixmap::fromImage(image);
}
class GraphicsView : public QGraphicsView
{
Q_OBJECT
Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers WRITE setModifiers)
public:
GraphicsView(QWidget *parent=nullptr): QGraphicsView(parent){
setScene(new QGraphicsScene);
setModifiers(Qt::ControlModifier);
auto item = scene()->addPixmap(create_image(QSize(100, 100)));
item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
item->setPos(40, 40);
fitInView(QRectF(0, 0, 640, 320),Qt::KeepAspectRatio);
resize(640, 480);
}
void setModifiers(const Qt::KeyboardModifiers &modifiers){
m_modifiers = modifiers;
}
Qt::KeyboardModifiers modifiers() const{
return m_modifiers;
}
signals:
void pixelChanged(const QPoint &);
protected:
void mousePressEvent(QMouseEvent *event) override{
if(QGraphicsPixmapItem *item = qgraphicsitem_cast<QGraphicsPixmapItem *>(itemAt(event->pos()))){
QPointF p = item->mapFromScene(mapToScene(event->pos()));
QPoint pixel_pos = p.toPoint();
emit pixelChanged(pixel_pos);
}
QGraphicsView::mousePressEvent(event);
}
void wheelEvent(QWheelEvent *event) override{
if(event->modifiers() == m_modifiers){
double angle = event->orientation() == Qt::Vertical ? event->angleDelta().y(): event->angleDelta().x();
double factor = qPow(base, angle);
applyZoom(factor, event->pos());
}
}
private:
void applyZoom(double factor, const QPoint & fixedViewPos)
{
QPointF fixedScenePos = mapToScene(fixedViewPos);
centerOn(fixedScenePos);
scale(factor, factor);
QPointF delta = mapToScene(fixedViewPos) - mapToScene(viewport()->rect().center());
centerOn(fixedScenePos - delta);
}
Qt::KeyboardModifiers m_modifiers;
const double base = 1.0015;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GraphicsView *view = new GraphicsView;
QLabel *label = new QLabel;
QObject::connect(view, &GraphicsView::pixelChanged, label, [label](const QPoint & p){
label->setText(QString("(%1, %2)").arg(p.x()).arg(p.y()));
});
label->setAlignment(Qt::AlignCenter);
QWidget w;
QVBoxLayout *lay = new QVBoxLayout(&w);
lay->addWidget(view);
lay->addWidget(label);
w.show();
return a.exec();
}
#include "main.moc"
It may be better to use a custom graphics scene subclassed from QGraphicsScene as this makes extracting the necessary coordinates much simpler. The only snag is you have to have the QGraphicsPixmapItem::pos available in the custom QGraphicsScene class - I have included a full working example which uses Graphics_view_zoom.h and Graphics_view_zoom.cpp from the linked question. The position of the QGraphicsPixmapItem is passed to a member of the QGraphicsScene subclass, Frame, in order to make the necessary correction.
#include <QPixmap>
#include <QGraphicsPixmapItem>
#include <QGraphicsTextItem>
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <qfont.h>
#include "Graphics_view_zoom.h"
class Frame : public QGraphicsScene {
Q_OBJECT
public:
QGraphicsTextItem * coords;
QPointF pic_tl;
Frame::Frame(QWidget* parent)
: QGraphicsScene(parent) {
coords = new QGraphicsTextItem();
coords->setZValue(1);
coords->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
addItem(coords);
}
void Frame::tl(QPointF p) {
pic_tl = p;
}
protected:
void Frame::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
QPointF pos = event->scenePos();
coords->setPlainText("(" + QString("%1").arg(int(pos.x() - pic_tl.x())) + ", "
+ QString("%1").arg(int(pos.y() - pic_tl.y())) + ")");
coords->setPos(pos);
coords->adjustSize();
}
};
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QMainWindow* main = new QMainWindow();
QGraphicsView* GraphicsView = new QGraphicsView(main);
Graphics_view_zoom* view_wrapper = new Graphics_view_zoom(GraphicsView);
Frame* frame = new Frame(main);
QGraphicsPixmapItem* pixmapItem = new QGraphicsPixmapItem();
frame->addItem(pixmapItem);
GraphicsView->setScene(frame);
// Loads a 497x326 pixel test image
pixmapItem->setPixmap(QPixmap(":/StackOverflow/test"));
// small offset to ensure it works for pictures which are not at
// (0,0). Larger offsets produce the same result but require manual
// adjustments of the view, I have neglected those for brevity as
// they are not in the scope of the question.
pixmapItem->setPos(-20, 20);
frame->tl(pixmapItem->pos());
GraphicsView->fitInView(QRectF(0, 0, 640, 320), Qt::KeepAspectRatio);
GraphicsView->centerOn(pixmapItem->pos());
main->resize(1920, 1080);
main->show();
GraphicsView->resize(main->width(), main->height());
return a.exec();
}
This will display the image coordinates of the pixel under the mouse relative to (0,0) at the top left corner.
The mouse is not visible in these screenshots but in the first it is in exactly the upper left corner and the second it is in exactly the lower right corner. If these coordinates are needed inside the Graphics_view_zoom object then you simply have to scope the Frame instance appropriately, or pass the value as needed.
Note - the exact coordinates displayed may not precisely represent the position of the mouse in this example since they are cast to ints for demonstration, but the floating point values can be easily accessed since QGraphicsSceneMoveEvent::scenePos() returns a QPointF. Additionally, note that in running this demonstration there may be some (hopefully very small) variation on where the mouse appears to be relative to it's 'actual' position - I recommend using Qt::CrossCursor to allay this. For example on my system the default cursor is off by about a pixel for certain areas on my smaller display, this is also affected by the zoom level - higher zoom will produce more accurate results, less zoom will be less accurate.

Qt: How to create a clearly visible glow effect for a QLabel? (e.g. using QGraphicsDropShadowEffect)

I am trying to add a glow effect to a QLabel so that it looks like the time display in the following picture:
I found out that you can "misuse" a QGraphicsDropShadowEffect for this:
QGraphicsDropShadowEffect * dse = new QGraphicsDropShadowEffect();
dse->setBlurRadius(10);
dse->setOffset(0);
dse->setColor(QColor(255, 255, 255));
ui.label->setGraphicsEffect(dse);
However, the resulting effect is too weak, you can barely see it:
Unfortunately, you can not modify the strength of the effect, only color and blur radius.
One idea would be to apply multiple QGraphicsDropShadowEffect to the label, so that it gets more visible due to overlapping. But calling ui.label->setGraphicsEffect(dse); will always delete any previous effects, i.e. I was not able to set multiple QGraphicsEffect to the same object.
Any ideas how you can create a clearly visible glow effect with Qt?
Meanwhile, I tinkered my own graphics effect based on QGraphicsBlurEffect and using parts of this answer. If you know any better solutions, let me know.
qgraphicsgloweffect.h:
#pragma once
#include <QGraphicsEffect>
#include <QGraphicsBlurEffect>
#include <QGraphicsColorizeEffect>
#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QPainter>
class QGraphicsGlowEffect :
public QGraphicsEffect
{
public:
explicit QGraphicsGlowEffect(QObject *parent = 0);
QRectF boundingRectFor(const QRectF &rect) const;
void setColor(QColor value);
void setStrength(int value);
void setBlurRadius(qreal value);
QColor color() const;
int strength() const;
qreal blurRadius() const;
protected:
void draw(QPainter* painter);
private:
static QPixmap applyEffectToPixmap(QPixmap src, QGraphicsEffect *effect, int extent);
int _extent = 5;
QColor _color = QColor(255, 255, 255);
int _strength = 3;
qreal _blurRadius = 5.0;
};
qgraphicsgloweffect.cpp:
#include "QGraphicsGlowEffect.h"
#include <QtCore\qmath.h>
QGraphicsGlowEffect::QGraphicsGlowEffect(QObject *parent) : QGraphicsEffect(parent)
{
}
void QGraphicsGlowEffect::setColor(QColor value) {
_color = value;
}
void QGraphicsGlowEffect::setStrength(int value) {
_strength = value;
}
void QGraphicsGlowEffect::setBlurRadius(qreal value) {
_blurRadius = value;
_extent = qCeil(value);
updateBoundingRect();
}
QColor QGraphicsGlowEffect::color() const {
return _color;
}
int QGraphicsGlowEffect::strength() const {
return _strength;
}
qreal QGraphicsGlowEffect::blurRadius() const {
return _blurRadius;
}
QRectF QGraphicsGlowEffect::boundingRectFor(const QRectF &rect) const {
return QRect(
rect.left() - _extent,
rect.top() - _extent,
rect.width() + 2 * _extent,
rect.height() + 2 * _extent);
}
void QGraphicsGlowEffect::draw(QPainter* painter) {
QPoint offset;
QPixmap source = sourcePixmap(Qt::LogicalCoordinates, &offset);
QPixmap glow;
QGraphicsColorizeEffect *colorize = new QGraphicsColorizeEffect;
colorize->setColor(_color);
colorize->setStrength(1);
glow = applyEffectToPixmap(source, colorize, 0);
QGraphicsBlurEffect *blur = new QGraphicsBlurEffect;
blur->setBlurRadius(_blurRadius);
glow = applyEffectToPixmap(glow, blur, _extent);
for (int i = 0; i < _strength; i++)
painter->drawPixmap(offset - QPoint(_extent, _extent), glow);
drawSource(painter);
}
QPixmap QGraphicsGlowEffect::applyEffectToPixmap(
QPixmap src, QGraphicsEffect *effect, int extent)
{
if (src.isNull()) return QPixmap();
if (!effect) return src;
QGraphicsScene scene;
QGraphicsPixmapItem item;
item.setPixmap(src);
item.setGraphicsEffect(effect);
scene.addItem(&item);
QSize size = src.size() + QSize(extent * 2, extent * 2);
QPixmap res(size.width(), size.height());
res.fill(Qt::transparent);
QPainter ptr(&res);
scene.render(&ptr, QRectF(), QRectF(-extent, -extent, size.width(), size.height()));
return res;
}
Then you can use it like:
QGraphicsGlowEffect * glow = new QGraphicsGlowEffect();
glow->setStrength(4);
glow->setBlurRadius(7);
ui.label->setGraphicsEffect(glow);
This results in a nice glow effect:

save the current items on qwidget as image

I'm trying draw some rhombuses with random colors in a QWidget. And i want to save the current QWidget as image. I use such code to do this:
QPixmap pixmap(this->size());
this->render(&pixmap);
pixmap.save("test.png");
The problem is that the render() seems to call paintEvent again, and the paintEvent will draw the rhombuses with new random colors, so that i always get a different Image saved compared to the image displayed. Can someone tell me how to save the current QWidget? Thanks in advance.
Code for drawing rhombuses:
void Dialog::paintEvent(QPaintEvent *e) {
QPainter painter(this);
QRect background(0,0,this->geometry().width(),this->geometry().height());
painter.setBrush( QBrush( Qt::white ) );
painter.setPen( Qt::NoPen );
//QBrush bbrush(Qt::black,Qt::SolidPattern);
painter.drawRect(background);
int width = this->geometry().width();
int height = this->geometry().height();
//draw rectangles
int rec_size=64;
int rows=0;
int cols=0;
rows=floor((double)height/(double)rec_size);
cols=floor((double)width/(double)rec_size);
QPointF points[4]; // QRect rec(0,0,rec_size,rec_size);
for (int i=0;i<floor(rows);i++){
for (int j=0;j<floor(cols);j++){
painter.setBrush( QBrush( colors[rand() % color_size] ) );
//QPainter painter(this);
points[0] = QPointF(rec_size*(j),rec_size*(i+0.5));
points[1] = QPointF(rec_size*(j+0.5),rec_size*(i));
points[2] = QPointF(rec_size*(j+1),rec_size*(i+0.5));
points[3] = QPointF(rec_size*(j+0.5),rec_size*(i+1));
painter.drawPolygon(points, 4);
}
}
painter.end();
}
You can have a class member variable of boolean type to check in the paintEvent whether a random color should be used. Also a variable to save the index of the last color used is necessary:
bool isRandom;
int lastColor;
The paintEvent should be like :
void Dialog::paintEvent(QPaintEvent *e) {
...
if(isRandom)
{
lastColor = rand() % color_size;
painter.setBrush( QBrush( colors[lastColor] ) );
}
else
painter.setBrush( QBrush( colors[lastColor] ) );
...
}
The variable has true when drawing the widget regularly. When you want to save it's image, assign the variable to false, save the image and assign it to true again :
isRandom = false;
QPixmap pixmap(this->size());
this->render(&pixmap);
pixmap.save("test.png");
isRandom = true;

How to align text (alone) of a QToolButton

I have a QToolButton. I'm using it instead of QPushButton because I need a label-like looking button. QPushButton is too chunky even after setting stylesheet's borders and paddings to None-0px.
I would like this QToolButton to contain a text (no-icon) align right.
However, text-align: right; is not working. .setAlignment(Qt.AlignRight) is also not working.
How can I align the text to right?
Thank you.
You can try to sub-class QStyle and re-implement QStyle::drawControl() to align the text to the right. Check the file qt/src/gui/styles/qcommonstyle.cpp to see how it's done. (Sorry I'm using C++ not Python)
case CE_ToolButtonLabel:
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QRect rect = toolbutton->rect;
int shiftX = 0;
int shiftY = 0;
if (toolbutton->state & (State_Sunken | State_On)) {
shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
}
// Arrow type always overrules and is always shown
bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow;
if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty())
|| toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) {
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
This example of align button content (icon & text) to center, but you can adopt this example to your demands (align to right). Override QToolButoon::paintEvent as next:
void CMyToolButton::paintEvent( QPaintEvent* )
{
QStylePainter sp( this );
QStyleOptionToolButton opt;
initStyleOption( &opt );
const QString strText = opt.text;
const QIcon icn = opt.icon;
//draw background
opt.text.clear();
opt.icon = QIcon();
sp.drawComplexControl( QStyle::CC_ToolButton, opt );
//draw content
const int nSizeHintWidth = minimumSizeHint().width();
const int nDiff = qMax( 0, ( opt.rect.width() - nSizeHintWidth ) / 2 );
opt.text = strText;
opt.icon = icn;
opt.rect.setWidth( nSizeHintWidth );//reduce paint area to minimum
opt.rect.translate( nDiff, 0 );//offset paint area to center
sp.drawComplexControl( QStyle::CC_ToolButton, opt );
}