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

# puzzlewidget.cpp Example File
draganddrop/puzzle/puzzlewidget.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 distributed and/or modified under the terms of the
    ** GNU General Public License version 2 as published by the Free Software
    ** Foundation and appearing in the file LICENSE.GPL included in the
    ** packaging of this file.
    **
    ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
    ** information about Qt Commercial License Agreements.
    ** See http://www.trolltech.com/gpl/ for GPL licensing information.
    **
    ** Contact info@trolltech.com if any conditions of this licensing are
    ** not clear to you.
        **
        ** 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 <QtGui>

        #include "puzzlewidget.h"

        PuzzleWidget::PuzzleWidget(QWidget *parent)
            : QWidget(parent)
        {
            setAcceptDrops(true);
            setMinimumSize(400, 400);
            setMaximumSize(400, 400);
        }

        void PuzzleWidget::clear()
        {
            pieceLocations.clear();
            piecePixmaps.clear();
            pieceRects.clear();
            highlightedRect = QRect();
            inPlace = 0;
            update();
        }

        void PuzzleWidget::dragLeaveEvent(QDragLeaveEvent *event)
        {
            QRect updateRect = highlightedRect;
            highlightedRect = QRect();
            update(updateRect);
            event->accept();
        }

        void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event)
        {
            QRect updateRect = highlightedRect.unite(targetSquare(event->pos()));

            if (event->mimeData()->hasFormat("image/x-puzzle-piece")
                && findPiece(targetSquare(event->pos())) == -1) {

                highlightedRect = targetSquare(event->pos());
                event->setDropAction(Qt::MoveAction);
                event->accept();
            } else {
                highlightedRect = QRect();
                event->ignore();
            }

            update(updateRect);
        }

        void PuzzleWidget::dropEvent(QDropEvent *event)
        {
            if (event->mimeData()->hasFormat("image/x-puzzle-piece")
                && findPiece(targetSquare(event->pos())) == -1) {

                QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece");
                QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
                QRect square = targetSquare(event->pos());
                QPixmap pixmap;
                QPoint location;
                dataStream >> pixmap >> location;

                pieceLocations.append(location);
                piecePixmaps.append(pixmap);
                pieceRects.append(square);

                highlightedRect = QRect();
                update(square);

                event->setDropAction(Qt::MoveAction);
                event->accept();

                if (location == QPoint(square.x()/80, square.y()/80)) {
                    inPlace++;
                    if (inPlace == 25)
                        emit puzzleCompleted();
                }
            } else {
                highlightedRect = QRect();
                event->ignore();
            }
        }

        int PuzzleWidget::findPiece(const QRect &pieceRect) const
        {
            for (int i = 0; i < pieceRects.size(); ++i) {
                if (pieceRect == pieceRects[i]) {
                    return i;
                }
            }
            return -1;
        }

        void PuzzleWidget::mousePressEvent(QMouseEvent *event)
        {
            QRect square = targetSquare(event->pos());
            int found = findPiece(square);

            if (found == -1)
                return;

            QPoint location = pieceLocations[found];
            QPixmap pixmap = piecePixmaps[found];
            pieceLocations.removeAt(found);
            piecePixmaps.removeAt(found);
            pieceRects.removeAt(found);

            if (location == QPoint(square.x()/80, square.y()/80))
                inPlace--;

            update(square);

            QByteArray itemData;
            QDataStream dataStream(&itemData, QIODevice::WriteOnly);

            dataStream << pixmap << location;

            QMimeData *mimeData = new QMimeData;
            mimeData->setData("image/x-puzzle-piece", itemData);

            QDrag *drag = new QDrag(this);
            drag->setMimeData(mimeData);
            drag->setHotSpot(event->pos() - square.topLeft());
            drag->setPixmap(pixmap);

            if (!(drag->start(Qt::MoveAction) == Qt::MoveAction)) {
                pieceLocations.insert(found, location);
                piecePixmaps.insert(found, pixmap);
                pieceRects.insert(found, square);
                update(targetSquare(event->pos()));
            }
        }

        void PuzzleWidget::paintEvent(QPaintEvent *event)
        {
            QPainter painter;
            painter.begin(this);
            painter.fillRect(event->rect(), Qt::white);

            if (highlightedRect.isValid()) {
                painter.setBrush(QColor("#ffcccc"));
                painter.setPen(Qt::NoPen);
                painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1));
            }

            for (int i = 0; i < pieceRects.size(); ++i) {
                painter.drawPixmap(pieceRects[i], piecePixmaps[i]);
            }
            painter.end();
        }

        const QRect PuzzleWidget::targetSquare(const QPoint &position) const
        {
            return QRect(position.x()/80 * 80, position.y()/80 * 80, 80, 80);
        }