Qt 4.0: displayshape.cpp Example File (tools/qtdemo/displayshape.cpp)

|  | Home · All Classes · Main Classes · Grouped Classes · Modules · Functions |

# displayshape.cpp Example File
tools/qtdemo/displayshape.cpp

        /****************************************************************************
        **
        ** Copyright (C) 2005-2005 Trolltech AS. All rights reserved.
        **
        ** This file is part of the documentation of the Qt Toolkit.
        **
        ** This file may be used under the terms of the GNU General Public
    ** License version 2.0 as published by the Free Software Foundation
    ** and appearing in the file LICENSE.GPL included in the packaging of
    ** this file.  Please review the following information to ensure GNU
    ** General Public Licensing requirements will be met:
    ** http://www.trolltech.com/products/qt/opensource.html
    **
    ** If you are unsure which license is appropriate for your use, please
    ** review the following information:
    ** http://www.trolltech.com/products/qt/licensing.html or contact the
    ** sales department at sales@trolltech.com.
        **
        ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
        ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        **
        ****************************************************************************/

        #include <math.h>
        #include <QtGui>

        #include "displayshape.h"

        DisplayShape::DisplayShape(const QPointF &position, const QSizeF &maxSize)
            : pos(position), maxSize(maxSize), interactive(false)
        {
        }

        bool DisplayShape::animate()
        {
            if (!targetPos.isNull()) {
                QLineF displacement(pos, targetPos);
                QPointF newPosition = displacement.pointAt(0.25);
                if (displacement.length() <= 1.0) {
                    pos = targetPos;
                    targetPos = QPointF();
                } else {
                    pos = newPosition;
                }
                return true;
            }

            return false;
        }

        bool DisplayShape::contains(const QString &key) const
        {
            return meta.contains(key);
        }

        bool DisplayShape::isInteractive() const
        {
            return interactive;
        }

        QVariant DisplayShape::metaData(const QString &key) const
        {
            return meta.value(key);
        }

        void DisplayShape::paint(QPainter *painter) const
        {
            painter->save();
            painter->drawImage(pos, image);
            painter->restore();
        }

        QPointF DisplayShape::position() const
        {
            return pos;
        }

        QRectF DisplayShape::rect() const
        {
            return QRectF(pos, image.size());
        }

        void DisplayShape::removeMetaData(const QString &key)
        {
            meta.remove(key);
        }

        void DisplayShape::setInteractive(bool enable)
        {
            interactive = enable;
        }

        void DisplayShape::setMetaData(const QString &key, const QVariant &value)
        {
            meta[key] = value;
        }

        void DisplayShape::setPosition(const QPointF &position)
        {
            pos = position;
        }

        void DisplayShape::setTarget(const QPointF &position)
        {
            targetPos = position;
        }

        QSizeF DisplayShape::size() const
        {
            return maxSize;
        }

        QPointF DisplayShape::target() const
        {
            return targetPos;
        }

        PanelShape::PanelShape(const QPainterPath &path, const QBrush &normal,
                               const QBrush &highlighted, const QPen &pen,
                               const QPointF &position, const QSizeF &maxSize)
            : DisplayShape(position, maxSize), highlightedBrush(highlighted),
              normalBrush(normal), path(path), pen(pen)
        {
            brush = normalBrush;
        }

        bool PanelShape::animate()
        {
            bool updated = false;

            if (!meta.contains("destroy")) {
                if (meta.contains("fade")) {
                    QColor penColor = pen.color();
                    QColor brushColor = brush.color();
                    int penAlpha = penColor.alpha();
                    int brushAlpha = brushColor.alpha();
                    int fadeMinimum = meta.value("fade minimum").toInt();

                    if (penAlpha != fadeMinimum || brushAlpha != fadeMinimum
                        || meta.value("fade").toInt() > 0) {

                        penAlpha = qBound(fadeMinimum,
                                          penAlpha + meta.value("fade").toInt(), 255);
                        brushAlpha = qBound(fadeMinimum,
                                          brushAlpha + meta.value("fade").toInt(), 255);

                        penColor.setAlpha(penAlpha);
                        brushColor.setAlpha(brushAlpha);
                        pen.setColor(penColor);
                        brush.setColor(brushColor);

                        if (penAlpha == 0 && brushAlpha == 0) {
                            meta["destroy"] = true;
                            meta.remove("fade");
                        } else if (penAlpha == 255 && brushAlpha == 255)
                            meta.remove("fade");

                        updated = true;
                    }
                } else if (meta.contains("highlight")) {
                    qreal scale = meta.value("highlight scale").toDouble();
                    QColor color = brush.color();

                    if (meta.value("highlight").toBool())
                        scale = qBound(0.0, scale + 0.5, 1.0);
                    else
                        scale = qBound(0.0, scale - 0.2, 1.0);

                    if (scale == 0.0) {
                        brush = normalBrush;
                        meta.remove("highlight");
                        meta.remove("highlight scale");
                        updated = true;
                    } else if (scale != meta["highlight scale"]) {
                        meta["highlight scale"] = scale;

                        if (scale == 1.0)
                            brush = highlightedBrush;
                        else {
                            QColor normal = normalBrush.color();
                            QColor highlighted = highlightedBrush.color();

                            color.setRedF((1.0-scale) * normal.redF()
                                          + scale*highlighted.redF());
                            color.setGreenF((1.0-scale) * normal.greenF()
                                            + scale*highlighted.greenF());
                            color.setBlueF((1.0-scale) * normal.blueF()
                                           + scale*highlighted.blueF());
                            brush.setColor(color);
                        }
                        updated = true;
                    }
                }
            }

            return DisplayShape::animate() || updated;
        }

        void PanelShape::paint(QPainter *painter) const
        {
            painter->save();
            painter->setRenderHint(QPainter::Antialiasing);
            painter->setBrush(brush);
            painter->setPen(pen);
            painter->translate(pos);
            painter->drawPath(path);
            painter->restore();
        }

        QRectF PanelShape::rect() const
        {
            return QRectF(pos + path.boundingRect().topLeft(),
                          path.boundingRect().size());
        }

        TitleShape::TitleShape(const QString &text, const QFont &f,
                               const QPen &pen, const QPointF &position,
                               const QSizeF &maxSize, Qt::Alignment alignment)
            : DisplayShape(position, maxSize), font(f), text(text), pen(pen),
              alignment(alignment)
        {
            QFontMetricsF fm(font);
            textRect = fm.boundingRect(QRectF(QPointF(0, 0), maxSize), alignment, text);

            qreal textWidth = qMax(fm.width(text), textRect.width());
            qreal textHeight = qMax(fm.height(), textRect.height());

            qreal scale = qMin(maxSize.width()/textWidth,
                               maxSize.height()/textHeight);

            font.setPointSizeF(font.pointSizeF() * scale);
            fm = QFontMetricsF(font);
            textRect = fm.boundingRect(QRectF(QPointF(0, 0), maxSize), alignment, text);
        }

        bool TitleShape::animate()
        {
            bool updated = false;

            if (!meta.contains("destroy")) {
                if (meta.contains("fade")) {
                    QColor penColor = pen.color();
                    int penAlpha = penColor.alpha();

                    penAlpha = qBound(meta.value("fade minimum").toInt(),
                                      penAlpha + meta.value("fade").toInt(), 255);

                    penColor.setAlpha(penAlpha);
                    pen.setColor(penColor);

                    if (penAlpha == 0) {
                        meta["destroy"] = true;
                        meta.remove("fade");
                    } else if (penAlpha == 255)
                        meta.remove("fade");

                    updated = true;
                }
            }

            return DisplayShape::animate() || updated;
        }

        void TitleShape::paint(QPainter *painter) const
        {
            QRectF rect(textRect);
            rect.translate(pos);
            painter->save();
            painter->setRenderHint(QPainter::TextAntialiasing);
            painter->setPen(pen);
            painter->setFont(font);
            painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop, text);
            painter->restore();
        }

        QRectF TitleShape::rect() const
        {
            QRectF rect(textRect);
            return rect.translated(pos);
        }

        ImageShape::ImageShape(const QImage &original, const QPointF &position,
                               const QSizeF &maxSize, int alpha,
                               Qt::Alignment alignment)
            : DisplayShape(position, maxSize), alpha(alpha), alignment(alignment)
        {
            source = original.convertToFormat(QImage::Format_ARGB32_Premultiplied);
            scale = qMin(qMin(maxSize.width()/source.width(),
                              maxSize.height()/source.height()), 1.0);
            image = QImage(int(ceil(scale * source.width())),
                           int(ceil(scale * source.height())),
                           QImage::Format_ARGB32_Premultiplied);

            offset = QPointF(0.0, 0.0);

            if (alignment & Qt::AlignHCenter)
                offset.setX((maxSize.width() - image.width())/2);
            else if (alignment & Qt::AlignRight)
                offset.setX(maxSize.width() - image.width());

            if (alignment & Qt::AlignVCenter)
                offset.setY((maxSize.height() - image.height())/2);
            else if (alignment & Qt::AlignBottom)
                offset.setY(maxSize.height() - image.height());

            redraw();
        }

        void ImageShape::redraw()
        {
            image.fill(qRgba(alpha, alpha, alpha, alpha));

            QPainter painter;
            painter.begin(&image);
            painter.setRenderHint(QPainter::SmoothPixmapTransform);
            painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
            painter.scale(scale, scale);
            painter.drawImage(0, 0, source);
            painter.end();
        }

        void ImageShape::paint(QPainter *painter) const
        {
            painter->drawImage(pos + offset, image);
        }

        QRectF ImageShape::rect() const
        {
            return QRectF(pos, maxSize);
        }

        bool ImageShape::animate()
        {
            bool updated = false;

            if (!meta.contains("destroy")) {
                if (meta.contains("fade")) {
                    alpha = qBound(meta.value("fade minimum").toInt(),
                                   alpha + meta.value("fade").toInt(), 255);
                    redraw();

                    if (alpha == 0) {
                        meta["destroy"] = true;
                        meta.remove("fade");
                    } else if (alpha == 255)
                        meta.remove("fade");

                    updated = true;
                }
            }

            return DisplayShape::animate() || updated;
        }

        DocumentShape::DocumentShape(const QString &text, const QFont &f,
                               const QPen &pen, const QPointF &position,
                               const QSizeF &maxSize)
            : DisplayShape(position, maxSize), font(f), pen(pen)
        {
            paragraphs = text.split("\n", QString::SkipEmptyParts);

            QFontMetricsF fm(font);
            qreal scale = qMax(maxSize.height()/(fm.lineSpacing()*20), 1.0);
            font.setPointSizeF(font.pointSizeF() * scale);

            qreal oldHeight = maxSize.height();
            qreal height = formatText();
            if (height > oldHeight) {
                font.setPointSizeF(font.pointSizeF() * oldHeight/height);
                formatText();
            }
        }

        DocumentShape::~DocumentShape()
        {
            qDeleteAll(layouts);
            layouts.clear();
        }

        bool DocumentShape::animate()
        {
            bool updated = false;

            if (!meta.contains("destroy")) {
                if (meta.contains("fade")) {
                    QColor penColor = pen.color();
                    int penAlpha = penColor.alpha();

                    penAlpha = qBound(meta.value("fade minimum").toInt(),
                                      penAlpha + meta.value("fade").toInt(), 255);

                    penColor.setAlpha(penAlpha);
                    pen.setColor(penColor);

                    if (penAlpha == 0) {
                        meta["destroy"] = true;
                        meta.remove("fade");
                    } else if (penAlpha == 255)
                        meta.remove("fade");

                    updated = true;
                }
            }

            return DisplayShape::animate() || updated;
        }

        qreal DocumentShape::formatText()
        {
            qDeleteAll(layouts);
            layouts.clear();

            QFontMetricsF fm(font);
            qreal lineHeight = fm.height();
            qreal y = 0.0;
            qreal leftMargin = 0.0;
            qreal rightMargin = maxSize.width();

            foreach (QString paragraph, paragraphs) {

                QTextLayout *textLayout = new QTextLayout(paragraph, font);
                textLayout->beginLayout();

                while (true) {
                    QTextLine line = textLayout->createLine();
                    if (!line.isValid())
                        break;

                    line.setLineWidth(rightMargin - leftMargin);
                    line.setPosition(QPointF(leftMargin, y));
                    y += line.height();
                }

                textLayout->endLayout();
                layouts.append(textLayout);

                y += lineHeight;
            }

            maxSize.setHeight(y);
            return y;
        }

        void DocumentShape::paint(QPainter *painter) const
        {
            painter->save();
            painter->setRenderHint(QPainter::TextAntialiasing);
            painter->setPen(pen);
            painter->setFont(font);
            foreach (QTextLayout *layout, layouts)
                layout->draw(painter, pos);
            painter->restore();
        }

        QRectF DocumentShape::rect() const
        {
            return QRectF(pos, maxSize);
        }