QTfrontend/ui/qaspectratiolayout.cpp
author unc0rr
Thu, 01 Nov 2012 14:31:53 +0400
branch0.9.18
changeset 7916 be11c26a3a0b
parent 6616 f77bb02b669f
permissions -rw-r--r--
Fix 0.9.18 desync: CreateNetGame() slot creates signal-slot connections from hwnet to hwgame. The problem is that this slot is called asynchronously using queued connection, and hwnet could send some signals to hwgame before hwgame object is created and connected. Changed this to direct connection. Also changed connections to hwgame object to queued, but this is unrelated. Sorry, it is frontend patch. Maybe a little delay on server side could help, but not much, as tcp packets could get glued on client's side, and that greately depends on pc and internet connection performance. Frontend should be reworked to be safe for queued connections, as it is extemely dangerous to have a mix of queued/direct connections.

/*
 * 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;
}