UBSelectionFrame.cpp 17.6 KB
Newer Older
Claudio Valerio's avatar
Claudio Valerio committed
1
/*
Craig Watson's avatar
Craig Watson committed
2 3
 * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM)
 *
Claudio Valerio's avatar
Claudio Valerio committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * Copyright (C) 2013 Open Education Foundation
 *
 * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour
 * l'Education Numérique en Afrique (GIP ENA)
 *
 * This file is part of OpenBoard.
 *
 * OpenBoard is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License,
 * with a specific linking exception for the OpenSSL project's
 * "OpenSSL" library (or with modified versions of it that use the
 * same license as the "OpenSSL" library).
 *
 * OpenBoard is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OpenBoard. If not, see <http://www.gnu.org/licenses/>.
 */


Ilia Ryabokon's avatar
Ilia Ryabokon committed
28 29 30 31 32
#include "UBSelectionFrame.h"

#include <QtGui>

#include "domain/UBItem.h"
33
#include "domain/UBGraphicsItemZLevelUndoCommand.h"
34
#include "domain/UBGraphicsGroupContainerItem.h"
Ilia Ryabokon's avatar
Ilia Ryabokon committed
35 36 37
#include "board/UBBoardController.h"
#include "core/UBSettings.h"
#include "core/UBApplication.h"
38
#include "gui/UBResources.h"
39
#include "gui/UBMainWindow.h"
40
#include "core/UBApplication.h"
Ilia Ryabokon's avatar
Ilia Ryabokon committed
41
#include "board/UBBoardView.h"
42
#include "board/UBDrawingController.h"
Ilia Ryabokon's avatar
Ilia Ryabokon committed
43 44 45 46

UBSelectionFrame::UBSelectionFrame()
    : mThickness(UBSettings::settings()->objectFrameWidth)
    , mAntiscaleRatio(1.0)
47
    , mRotationAngle(0)
48 49 50 51
    , mDeleteButton(0)
    , mDuplicateButton(0)
    , mZOrderUpButton(0)
    , mZOrderDownButton(0)
52
    , mGroupButton(0)
53
    , mRotateButton(0)
Ilia Ryabokon's avatar
Ilia Ryabokon committed
54 55 56 57
{
    setLocalBrush(QBrush(UBSettings::paletteColor));
    setPen(Qt::NoPen);
    setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control));
58
    setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::SelectionFrame)); //Necessary to set if we want z value to be assigned correctly
59 60
    setFlags(QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsSelectable | ItemIsMovable);

Ilia Ryabokon's avatar
Ilia Ryabokon committed
61
    connect(UBApplication::boardController, SIGNAL(zoomChanged(qreal)), this, SLOT(onZoomChanged(qreal)));
Ilia Ryabokon's avatar
Ilia Ryabokon committed
62 63

    onZoomChanged(UBApplication::boardController->currentZoom());
Ilia Ryabokon's avatar
Ilia Ryabokon committed
64 65 66 67 68 69 70 71 72
}

void UBSelectionFrame::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    QPainterPath path;
    QRectF shRect = option->rect;
Ilia Ryabokon's avatar
Ilia Ryabokon committed
73
    path.addRoundedRect(shRect, adjThickness() / 2, adjThickness() / 2);
Ilia Ryabokon's avatar
Ilia Ryabokon committed
74 75 76

    if (rect().width() > 1 && rect().height() > 1) {
        QPainterPath extruded;
Ilia Ryabokon's avatar
Ilia Ryabokon committed
77
        extruded.addRect(shRect.adjusted(adjThickness(), adjThickness(), (adjThickness() * -1), (adjThickness() * -1)));
Ilia Ryabokon's avatar
Ilia Ryabokon committed
78 79 80 81 82 83 84 85
        path = path.subtracted(extruded);
    }

    painter->fillPath(path, mLocalBrush);
}

QRectF UBSelectionFrame::boundingRect() const
{
Ilia Ryabokon's avatar
Ilia Ryabokon committed
86
    return rect().adjusted(-adjThickness(), -adjThickness(), adjThickness(), adjThickness());
Ilia Ryabokon's avatar
Ilia Ryabokon committed
87 88 89 90 91 92
}

QPainterPath UBSelectionFrame::shape() const
{
    QPainterPath resShape;
    QRectF ownRect = rect();
Ilia Ryabokon's avatar
Ilia Ryabokon committed
93 94
    QRectF shRect = ownRect.adjusted(-adjThickness(), -adjThickness(), adjThickness(), adjThickness());
    resShape.addRoundedRect(shRect, adjThickness() / 2, adjThickness() / 2);
Ilia Ryabokon's avatar
Ilia Ryabokon committed
95 96 97 98 99 100 101 102 103 104 105 106

    if (rect().width() > 1 && rect().height() > 1) {
        QPainterPath extruded;
        extruded.addRect(ownRect);
        resShape = resShape.subtracted(extruded);
    }

    return resShape;
}

void UBSelectionFrame::setEnclosedItems(const QList<QGraphicsItem*> pGraphicsItems)
{
107 108
    mButtons.clear();
    mButtons.append(mDeleteButton);
109
    mRotationAngle = 0;
110

111
    QRegion resultRegion;
112
    UBGraphicsFlags resultFlags;
Ilia Ryabokon's avatar
Ilia Ryabokon committed
113
    mEnclosedtems.clear();
114 115 116 117 118

    // If at least one of the enclosed items is locked, the entire selection is
    // considered to be locked.
    mIsLocked = false;

Ilia Ryabokon's avatar
Ilia Ryabokon committed
119 120 121
    foreach (QGraphicsItem *nextItem, pGraphicsItems) {
        UBGraphicsItemDelegate *nextDelegate = UBGraphicsItem::Delegate(nextItem);
        if (nextDelegate) {
122
            mIsLocked = (mIsLocked || nextDelegate->isLocked());
Ilia Ryabokon's avatar
Ilia Ryabokon committed
123
            mEnclosedtems.append(nextDelegate);
124
            resultRegion |= nextItem->boundingRegion(nextItem->sceneTransform());
125
            resultFlags |= nextDelegate->ubflags();
Ilia Ryabokon's avatar
Ilia Ryabokon committed
126 127 128
        }
    }

129
    QRectF resultRect = resultRegion.boundingRect();
Ilia Ryabokon's avatar
Ilia Ryabokon committed
130 131
    setRect(resultRect);

132
    mButtons = buttonsForFlags(resultFlags);
133 134
    placeButtons();

Ilia Ryabokon's avatar
Ilia Ryabokon committed
135 136 137
    if (resultRect.isEmpty()) {
        hide();
    }
138 139 140 141 142 143 144 145

    if (mIsLocked) {
        QColor baseColor = UBSettings::paletteColor;
        baseColor.setAlphaF(baseColor.alphaF() / 3);
        setLocalBrush(QBrush(baseColor));
    }
    else
        setLocalBrush(QBrush(UBSettings::paletteColor));
Ilia Ryabokon's avatar
Ilia Ryabokon committed
146 147 148 149
}

void UBSelectionFrame::updateRect()
{
150
    QRegion resultRegion;
Ilia Ryabokon's avatar
Ilia Ryabokon committed
151
    foreach (UBGraphicsItemDelegate *curDelegateItem, mEnclosedtems) {
152
        resultRegion |= curDelegateItem->delegated()->boundingRegion(curDelegateItem->delegated()->sceneTransform());
Ilia Ryabokon's avatar
Ilia Ryabokon committed
153 154
    }

155
    QRectF result = resultRegion.boundingRect();
Ilia Ryabokon's avatar
Ilia Ryabokon committed
156 157
    setRect(result);

158 159
    placeButtons();

Ilia Ryabokon's avatar
Ilia Ryabokon committed
160 161 162 163 164 165 166 167 168 169
    if (result.isEmpty()) {
        setVisible(false);
    }
}

void UBSelectionFrame::updateScale()
{
    setScale(-UBApplication::boardController->currentZoom());
}

170 171 172 173
void UBSelectionFrame::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    mPressedPos = mLastMovedPos = event->pos();
    mLastTranslateOffset = QPointF();
Ilia Ryabokon's avatar
Ilia Ryabokon committed
174
    mRotationAngle = 0;
175

176
    if (scene()->itemAt(event->scenePos(), transform()) == mRotateButton) {
177 178 179 180
        mOperationMode = om_rotating;
    } else {
        mOperationMode = om_moving;
    }
181 182 183 184
}

void UBSelectionFrame::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
185 186 187
    if (mIsLocked)
        return;

188
    QPointF dp = event->pos() - mPressedPos;
Ilia Ryabokon's avatar
Ilia Ryabokon committed
189
    QPointF rotCenter = mapToScene(rect().center());
190 191 192

    foreach (UBGraphicsItemDelegate *curDelegate, mEnclosedtems) {

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
        switch (static_cast<int>(mOperationMode)) {
        case om_moving : {
            QGraphicsItem *item = curDelegate->delegated();
            QTransform ownTransform = item->transform();
            QTransform dTransform(
                        ownTransform.m11()
                        , ownTransform.m12()
                        , ownTransform.m13()

                        , ownTransform.m21()
                        , ownTransform.m22()
                        , ownTransform.m23()

                        , ownTransform.m31() + (dp - mLastTranslateOffset).x()
                        , ownTransform.m32() + (dp - mLastTranslateOffset).y()
                        , ownTransform.m33()
                        );

            item->setTransform(dTransform);
        } break;

        case om_rotating : {
            QLineF startLine(sceneBoundingRect().center(), event->lastScenePos());
            QLineF currentLine(sceneBoundingRect().center(), event->scenePos());
            qreal dAngle = startLine.angleTo(currentLine);

            QGraphicsItem *item = curDelegate->delegated();
            QTransform ownTransform = item->transform();

Ilia Ryabokon's avatar
Ilia Ryabokon committed
222 223 224 225 226

            QPointF nextRotCenter = item->mapFromScene(rotCenter);

            qreal cntrX = nextRotCenter.x();
            qreal cntrY = nextRotCenter.y();
227

228 229
            ownTransform.translate(cntrX, cntrY);
            mRotationAngle -= dAngle;
Ilia Ryabokon's avatar
Ilia Ryabokon committed
230
            ownTransform.rotate(-dAngle);
231
            ownTransform.translate(-cntrX, -cntrY);
232

Ilia Ryabokon's avatar
Ilia Ryabokon committed
233 234 235 236
            item->update();
            item->setTransform(ownTransform, false);

            qDebug() << "curAngle" << mRotationAngle;
237 238 239
        } break;

        }
240 241 242 243 244 245 246 247 248 249

    }

    updateRect();
    mLastMovedPos = event->pos();
    mLastTranslateOffset = dp;
}

void UBSelectionFrame::mouseReleaseEvent(QGraphicsSceneMouseEvent */*event*/)
{
250
    mPressedPos = mLastMovedPos = mLastTranslateOffset = QPointF();
251 252

    if (mOperationMode == om_moving || mOperationMode == om_rotating) {
253
        UBApplication::undoStack->beginMacro(UBSettings::undoCommandTransactionName);
254 255 256 257 258 259 260
        foreach (UBGraphicsItemDelegate *d, mEnclosedtems) {
            d->commitUndoStep();
        }
        UBApplication::undoStack->endMacro();
    }
    mOperationMode = om_idle;

261 262
}

Ilia Ryabokon's avatar
Ilia Ryabokon committed
263 264
void UBSelectionFrame::onZoomChanged(qreal pZoom)
{
Ilia Ryabokon's avatar
Ilia Ryabokon committed
265 266
    mAntiscaleRatio = 1 / (UBApplication::boardController->systemScaleFactor() * pZoom);

267 268 269 270
}

void UBSelectionFrame::remove()
{
271
    UBApplication::undoStack->beginMacro(UBSettings::undoCommandTransactionName);
272 273 274
    foreach (UBGraphicsItemDelegate *d, mEnclosedtems) {
        d->remove(true);
    }
275 276 277 278 279
    UBApplication::undoStack->endMacro();

    updateRect();
}

Craig Watson's avatar
Craig Watson committed
280 281 282 283 284 285
static bool sortByZ(UBGraphicsItemDelegate* A, UBGraphicsItemDelegate* B)
{
    return (A->delegated()->data(UBGraphicsItemData::ItemOwnZValue).toReal()
            < B->delegated()->data(UBGraphicsItemData::ItemOwnZValue).toReal() );
}

286 287
void UBSelectionFrame::duplicate()
{
288
    UBApplication::undoStack->beginMacro(UBSettings::undoCommandTransactionName);
Craig Watson's avatar
Craig Watson committed
289 290 291 292 293

    // The mEnclosedtems list items are in order of selection. To avoid losing their
    // relative zValues when duplicating, we re-order the list.
    std::sort(mEnclosedtems.begin(), mEnclosedtems.end(), sortByZ);

294 295 296 297
    foreach (UBGraphicsItemDelegate *d, mEnclosedtems) {
        d->duplicate();
    }
    UBApplication::undoStack->endMacro();
298 299

    updateRect();
300
}
Ilia Ryabokon's avatar
Ilia Ryabokon committed
301

302 303
void UBSelectionFrame::increaseZlevelUp()
{
304 305 306 307 308 309
    QList<QGraphicsItem*> selItems = sortedByZ(scene()->selectedItems());

    QList<QGraphicsItem*>::iterator itemIt = selItems.end();
    while(itemIt != selItems.begin()){
        itemIt--;
        QGraphicsItem* item = *itemIt;
310 311
        ubscene()->changeZLevelTo(item, UBZLayerController::up);
    }
312 313

    addSelectionUndo(selItems, UBZLayerController::up);
314 315 316 317
}

void UBSelectionFrame::increaseZlevelTop()
{
318 319
    QList<QGraphicsItem*> selItems = sortedByZ(scene()->selectedItems());
    foreach (QGraphicsItem *item, selItems) {
320 321
        ubscene()->changeZLevelTo(item, UBZLayerController::top);
    }
322
    addSelectionUndo(selItems, UBZLayerController::top);
323 324 325 326
}

void UBSelectionFrame::increaseZlevelDown()
{
327 328
    QList<QGraphicsItem*> selItems = sortedByZ(scene()->selectedItems());
    foreach (QGraphicsItem *item, selItems) {
329 330
        ubscene()->changeZLevelTo(item, UBZLayerController::down);
    }
331
    addSelectionUndo(selItems, UBZLayerController::down);
332 333 334 335
}

void UBSelectionFrame::increaseZlevelBottom()
{
336 337
    QList<QGraphicsItem*> selItems = sortedByZ(scene()->selectedItems());
    QListIterator<QGraphicsItem*> iter(selItems);
338 339 340
    iter.toBack();
    while (iter.hasPrevious()) {
        ubscene()->changeZLevelTo(iter.previous(), UBZLayerController::bottom);
341
    }
342
    addSelectionUndo(selItems, UBZLayerController::bottom);
343 344
}

345 346 347 348 349 350 351 352 353
void UBSelectionFrame::groupItems()
{
    UBGraphicsGroupContainerItem *groupItem = ubscene()->createGroup(enclosedGraphicsItems());

    groupItem->setSelected(true);
    UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector);
    qDebug() << "Grouping items";
}

354 355 356 357 358 359 360 361
void UBSelectionFrame::addSelectionUndo(QList<QGraphicsItem*> items, UBZLayerController::moveDestination dest){
    if(!items.empty()){
        qreal topItemLevel = items.at(0)->data(UBGraphicsItemData::ItemOwnZValue).toReal();
        UBGraphicsItemZLevelUndoCommand* cmd = new UBGraphicsItemZLevelUndoCommand(ubscene(), items, topItemLevel, dest);
        UBApplication::undoStack->push(cmd);
    }
}

362 363
void UBSelectionFrame::translateItem(QGraphicsItem */*item*/, const QPointF &/*translatePoint*/)
{
Ilia Ryabokon's avatar
Ilia Ryabokon committed
364
}
365

366 367
void UBSelectionFrame::placeButtons()
{
368 369 370 371
    if (!mButtons.count()) {
        return;
    }

372
    QTransform tr;
Ilia Ryabokon's avatar
Ilia Ryabokon committed
373
    tr.scale(mAntiscaleRatio, mAntiscaleRatio);
374
    mDeleteButton->setParentItem(this);
Ilia Ryabokon's avatar
Ilia Ryabokon committed
375
    mDeleteButton->setTransform(tr);
376

Ilia Ryabokon's avatar
Ilia Ryabokon committed
377
    QRectF frRect = boundingRect();
378

Ilia Ryabokon's avatar
Ilia Ryabokon committed
379 380
    qreal topX = frRect.left() - mDeleteButton->renderer()->viewBox().width() * mAntiscaleRatio / 2;
    qreal topY = frRect.top() - mDeleteButton->renderer()->viewBox().height() * mAntiscaleRatio / 2;
381

Ilia Ryabokon's avatar
Ilia Ryabokon committed
382 383
    qreal bottomX = topX;
    qreal bottomY = frRect.bottom() - mDeleteButton->renderer()->viewBox().height() * mAntiscaleRatio / 2;
384

Ilia Ryabokon's avatar
Ilia Ryabokon committed
385
    mDeleteButton->setPos(topX, topY);
386 387
    mDeleteButton->show();

Ilia Ryabokon's avatar
Ilia Ryabokon committed
388 389 390 391 392 393 394 395 396 397 398 399
    int i = 1, j = 0, k = 0;
    while ((i + j + k) < mButtons.size())  {
        DelegateButton* button = mButtons[i + j];

        if (button->getSection() == Qt::TopLeftSection) {
            button->setParentItem(this);
            button->setPos(topX + (i++ * 1.6 * adjThickness()), topY);
            button->setTransform(tr);
        } else if (button->getSection() == Qt::BottomLeftSection) {
            button->setParentItem(this);
            button->setPos(bottomX + (++j * 1.6 * adjThickness()), bottomY);
            button->setTransform(tr);
400 401 402 403
        } else if (button->getSection() == Qt::NoSection) {
            button->setParentItem(this);
            placeExceptionButton(button, tr);
            k++;
Ilia Ryabokon's avatar
Ilia Ryabokon committed
404 405 406 407 408
        } else {
            ++k;
        }
            button->show();
    }
409 410
}

411 412 413 414 415 416 417 418 419 420 421 422
void UBSelectionFrame::placeExceptionButton(DelegateButton *pButton, QTransform pTransform)
{
    QRectF frRect = boundingRect();

    if (pButton == mRotateButton) {
        qreal topX = frRect.right() - (mRotateButton->renderer()->viewBox().width()) * mAntiscaleRatio - 5;
        qreal topY = frRect.top() + 5;
        mRotateButton->setPos(topX, topY);
        mRotateButton->setTransform(pTransform);
    }
}

423 424 425 426 427 428 429 430 431 432 433
void UBSelectionFrame::clearButtons()
{
    foreach (DelegateButton *b, mButtons)
    {
        b->setParentItem(0);
        b->hide();
    }

    mButtons.clear();
}

434 435 436 437 438
inline UBGraphicsScene *UBSelectionFrame::ubscene()
{
    return qobject_cast<UBGraphicsScene*>(scene());
}

Ilia Ryabokon's avatar
Ilia Ryabokon committed
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
void UBSelectionFrame::setCursorFromAngle(QString angle)
{
    QWidget *controlViewport = UBApplication::boardController->controlView()->viewport();

    QSize cursorSize(45,30);


    QImage mask_img(cursorSize, QImage::Format_Mono);
    mask_img.fill(0xff);
    QPainter mask_ptr(&mask_img);
    mask_ptr.setBrush( QBrush( QColor(0, 0, 0) ) );
    mask_ptr.drawRoundedRect(0,0, cursorSize.width()-1, cursorSize.height()-1, 6, 6);
    QBitmap bmpMask = QBitmap::fromImage(mask_img);


    QPixmap pixCursor(cursorSize);
    pixCursor.fill(QColor(Qt::white));

    QPainter painter(&pixCursor);

    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    painter.setBrush(QBrush(Qt::white));
    painter.setPen(QPen(QColor(Qt::black)));
    painter.drawRoundedRect(1,1,cursorSize.width()-2,cursorSize.height()-2,6,6);
    painter.setFont(QFont("Arial", 10));
    painter.drawText(1,1,cursorSize.width(),cursorSize.height(), Qt::AlignCenter, angle.append(QChar(176)));
    painter.end();

    pixCursor.setMask(bmpMask);
    controlViewport->setCursor(pixCursor);
}

471 472 473
QList<QGraphicsItem*> UBSelectionFrame::sortedByZ(const QList<QGraphicsItem *> &pItems)
{
    //select only items wiht the same z-level as item's one and push it to sortedItems QMultiMap
474
    // It means: keep only the selected items and remove the selection frame from the list
475 476 477 478 479 480 481 482 483 484 485
    QMultiMap<qreal, QGraphicsItem*> sortedItems;
    foreach (QGraphicsItem *tmpItem, pItems) {
        if (tmpItem->type() == Type) {
            continue;
        }
        sortedItems.insert(tmpItem->data(UBGraphicsItemData::ItemOwnZValue).toReal(), tmpItem);
    }

    return sortedItems.values();
}

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
QList<DelegateButton*> UBSelectionFrame::buttonsForFlags(UBGraphicsFlags fls) {

    QList<DelegateButton*> result;

    if (!mDeleteButton) {
        mDeleteButton = new DelegateButton(":/images/close.svg", this, 0, Qt::TopLeftSection);
        connect(mDeleteButton, SIGNAL(clicked()), this, SLOT(remove()));
    }
    result << mDeleteButton;

    if (fls | GF_DUPLICATION_ENABLED) {
        if (!mDuplicateButton) {
            mDuplicateButton = new DelegateButton(":/images/duplicate.svg", this, 0, Qt::TopLeftSection);
            connect(mDuplicateButton, SIGNAL(clicked(bool)), this, SLOT(duplicate()));
        }
        result <<  mDuplicateButton;
    }

504 505
    if (mEnclosedtems.count() >= 1) {
        if (!mGroupButton) {
-f's avatar
-f committed
506
            mGroupButton = new DelegateButton(":/images/groupItems.svg", this, 0, Qt::TopLeftSection);
507 508 509 510 511 512
            mGroupButton->setShowProgressIndicator(false);
            connect(mGroupButton, SIGNAL(clicked()), this, SLOT(groupItems()));
        }
        result << mGroupButton;
    }

513 514 515 516
    if (fls | GF_ZORDER_MANIPULATIONS_ALLOWED) {
        if (!mZOrderUpButton) {
            mZOrderUpButton = new DelegateButton(":/images/z_layer_up.svg", this, 0, Qt::BottomLeftSection);
            mZOrderUpButton->setShowProgressIndicator(true);
Ilia Ryabokon's avatar
Ilia Ryabokon committed
517
            connect(mZOrderUpButton, SIGNAL(clicked()), this, SLOT(increaseZlevelUp()));
518
            connect(mZOrderUpButton, SIGNAL(longClicked()), this, SLOT(increaseZlevelTop()));
519 520 521 522 523
        }

        if (!mZOrderDownButton) {
            mZOrderDownButton = new DelegateButton(":/images/z_layer_down.svg", this, 0, Qt::BottomLeftSection);
            mZOrderDownButton->setShowProgressIndicator(true);
524 525
            connect(mZOrderDownButton, SIGNAL(clicked()), this, SLOT(increaseZlevelDown()));
            connect(mZOrderDownButton, SIGNAL(longClicked()), this, SLOT(increaseZlevelBottom()));
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
        }

        result << mZOrderUpButton;
        result << mZOrderDownButton;
    }

    if (fls | GF_REVOLVABLE) {
        if (!mRotateButton) {
            mRotateButton = new DelegateButton(":/images/rotate.svg", this, 0, Qt::NoSection);
            mRotateButton->setCursor(UBResources::resources()->rotateCursor);
            mRotateButton->setShowProgressIndicator(false);
            mRotateButton->setTransparentToMouseEvent(true);
        }
        result << mRotateButton;
    }

    return result;
}

545 546 547 548 549 550 551 552 553 554
QList<QGraphicsItem*> UBSelectionFrame::enclosedGraphicsItems()
{
    QList<QGraphicsItem*> result;
    foreach (UBGraphicsItemDelegate *d, mEnclosedtems) {
        result << d->delegated();
    }

    return result;
}

555