QTfrontend/ui/qaspectratiolayout.cpp
author sheepluva
Sat, 28 Apr 2012 09:25:30 +0200
changeset 6946 576c453822bf
parent 6616 f77bb02b669f
permissions -rw-r--r--
fix for issue #186 ("Screen gets messed up when selecting Hand Drawn Map")

/*
 * Copyright (c) 2009 Nokia Corporation.
 */

#include "qaspectratiolayout.h"

QAspectRatioLayout::QAspectRatioLayout(QWidget* parent, int spacing) : QLayout(parent)
{
    init(spacing);
}

QAspectRatioLayout::QAspectRatioLayout(int spacing)
{
    init(spacing);
}

QAspectRatioLayout::~QAspectRatioLayout()
{
    delete item;
    delete lastReceivedRect;
    delete _geometry;
}

void QAspectRatioLayout::init(int spacing)
{
    item = 0;
    lastReceivedRect = new QRect(0, 0, 0, 0);
    _geometry = new QRect(0, 0, 0, 0);
    setSpacing(spacing);
}


/* Adds item if place isn't already taken. */
void QAspectRatioLayout::add(QLayoutItem* item)
{
    if(!hasItem())
    {
        replaceItem(item);
    }
}

/* Adds item if place isn't already taken. */
void QAspectRatioLayout::addItem(QLayoutItem* item)
{
    if(!hasItem())
    {
        replaceItem(item);
    }
}

/* Adds widget if place isn't already taken. */
void QAspectRatioLayout::addWidget(QWidget* widget)
{
    if(!hasItem())
    {
        replaceItem(new QWidgetItem(widget));
    }
}

/* Returns the item pointer and dereferences it here. */
QLayoutItem* QAspectRatioLayout::take()
{
    QLayoutItem* item = 0;
    if(this->hasItem())
    {
        item = this->item;
        this->item = 0;
    }
    return item;
}

/* Returns the item pointer and dereferences it here. */
QLayoutItem* QAspectRatioLayout::takeAt(int index)
{
    if(index != 0)
    {
        return 0;
    }
    return this->take();
}

/* Returns the item pointer. */
QLayoutItem* QAspectRatioLayout::itemAt(int index) const
{
    if(index != 0)
    {
        return 0;
    }
    if(hasItem())
    {
        return this->item;
    }
    return 0;
}

/* Checks if we have an item. */
bool QAspectRatioLayout::hasItem() const
{
    return this->item != 0;
}

/* Returns the count of items which can be either 0 or 1. */
int QAspectRatioLayout::count() const
{
    int returnValue = 0;
    if(hasItem())
    {
        returnValue = 1;
    }
    return returnValue;
}

/* Replaces the item with the new and returns the old. */
QLayoutItem* QAspectRatioLayout::replaceItem(QLayoutItem* item)
{
    QLayoutItem* old = 0;
    if(this->hasItem())
    {
        old = this->item;
    }
    this->item = item;
    setGeometry(*this->_geometry);
    return old;
}

/* Tells which way layout expands. */
Qt::Orientations QAspectRatioLayout::expandingDirections() const
{
    return Qt::Horizontal | Qt::Vertical;
}

/* Tells which size is preferred. */
QSize QAspectRatioLayout::sizeHint() const
{
    return this->item->minimumSize();
}

/* Tells minimum size. */
QSize QAspectRatioLayout::minimumSize() const
{
    return this->item->minimumSize();
}

/*
 * Tells if heightForWidth calculations is handled.
 * It isn't since width isn't enough to calculate
 * proper size.
 */
bool QAspectRatioLayout::hasHeightForWidth() const
{
    return false;
}

/* Replaces lastReceivedRect. */
void QAspectRatioLayout::setLastReceivedRect(const QRect& rect)
{
    QRect* oldRect = this->lastReceivedRect;
    this->lastReceivedRect = new QRect(rect.topLeft(), rect.size());
    delete oldRect;
}

/* Returns geometry */
QRect QAspectRatioLayout::geometry()
{
    return QRect(*this->_geometry);
}

/* Sets geometry to given size. */
void QAspectRatioLayout::setGeometry(const QRect& rect)
{
    /*
     * We check if the item is set and
     * if size is the same previously received.
     * If either is false nothing is done.
     */
    if(!this->hasItem() ||
            areRectsEqual(*this->lastReceivedRect, rect))
    {
        return;
    }
    /* Replace the last received rectangle. */
    setLastReceivedRect(rect);
    /* Calculate proper size for the item relative to the received size. */
    QSize properSize = calculateProperSize(rect.size());
    /* Calculate center location in the rect and with item size. */
    QPoint properLocation = calculateCenterLocation(rect.size(), properSize);
    /* Set items geometry */
    this->item->setGeometry(QRect(properLocation, properSize));
    QRect* oldRect = this->_geometry;
    /* Cache the calculated geometry. */
    this->_geometry = new QRect(properLocation, properSize);
    delete oldRect;
    /* Super classes setGeometry */
    QLayout::setGeometry(*this->_geometry);
}

/* Takes the shortest side and creates QSize
 * with the shortest side as width and height. */
QSize QAspectRatioLayout::calculateProperSize(QSize from) const
{
    QSize properSize;
    if(from.height() * 2 < from.width())
    {
        properSize.setHeight(from.height() - this->margin());
        properSize.setWidth(from.height() * 2 - this->margin());
    }
    else
    {
        properSize.setWidth(from.width() - this->margin());
        properSize.setHeight(from.width() / 2 - this->margin());
    }
    return properSize;
}

/* Calculates center location from the given height and width for item size. */
QPoint QAspectRatioLayout::calculateCenterLocation(QSize from,
        QSize itemSize) const
{
    QPoint centerLocation;
    if((from.width() - itemSize.width()) > 0)
    {
        centerLocation.setX((from.width() - itemSize.width())/2);
    }
    if((from.height() - itemSize.height()) > 0)
    {
        centerLocation.setY((from.height() - itemSize.height())/2);
    }
    return centerLocation;
}

/* Compares if two QRects are equal. */
bool QAspectRatioLayout::areRectsEqual(const QRect& a,
                                       const QRect& b) const
{
    bool result = false;
    if(a.x() == b.x() &&
            a.y() == b.y() &&
            a.height() == b.height() &&
            a.width() == b.width())
    {
        result = true;
    }
    return result;
}