Commit 04fc630a authored by roangel's avatar roangel
Browse files

Added support for grabbers. Next step: actually resize rectangles when pressing grabbers

parent af27decc
#include "cornergrabber.h"
CornerGrabber::CornerGrabber(QGraphicsItem *parent, int corner) :
QGraphicsItem(parent),
mouseDownX(0),
mouseDownY(0),
_outterborderColor(Qt::black),
_outterborderPen(),
_width(6),
_height(6),
_corner(corner),
_mouseButtonState(kMouseReleased),
_is_active(false)
{
setParentItem(parent);
_outterborderPen.setWidth(2);
_outterborderPen.setColor(_outterborderColor);
this->setAcceptHoverEvents(true);
}
qreal CornerGrabber::getHeight()
{
return _height;
}
qreal CornerGrabber::getWidth()
{
return _width;
}
void CornerGrabber::setMouseState(int s)
{
_mouseButtonState = s;
}
int CornerGrabber::getMouseState()
{
return _mouseButtonState;
}
int CornerGrabber::getCorner()
{
return _corner;
}
bool CornerGrabber::isActive()
{
return _is_active;
}
// we have to implement the mouse events to keep the linker happy,
// but just set accepted to false since are not actually handling them
void CornerGrabber::mouseMoveEvent(QGraphicsSceneDragDropEvent *event)
{
event->setAccepted(false);
}
void CornerGrabber::mousePressEvent(QGraphicsSceneDragDropEvent *event)
{
event->setAccepted(false);
}
void CornerGrabber::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
event->setAccepted(false);
}
void CornerGrabber::mousePressEvent ( QGraphicsSceneMouseEvent * event )
{
event->setAccepted(false);
}
void CornerGrabber::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
{
event->setAccepted(false);
}
// change the color on hover events to indicate to the use the object has
// been captured by the mouse
void CornerGrabber::hoverLeaveEvent ( QGraphicsSceneHoverEvent * )
{
_outterborderColor = Qt::black;
_is_active = false;
this->update(0,0,_width,_height);
}
void CornerGrabber::hoverEnterEvent ( QGraphicsSceneHoverEvent * )
{
_outterborderColor = Qt::red;
_is_active = true;
this->update(0,0,_width,_height);
}
QRectF CornerGrabber::boundingRect() const
{
return QRectF(0,0,_width,_height);
}
void CornerGrabber::paint (QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
// fill the box with solid color, use sharp corners
_outterborderPen.setCapStyle(Qt::SquareCap);
_outterborderPen.setStyle(Qt::SolidLine);
painter->setPen(_outterborderPen);
QPointF topLeft (0, 0);
QPointF bottomRight ( _width, _height);
QRectF rect (topLeft, bottomRight);
QBrush brush (Qt::SolidPattern);
brush.setColor (_outterborderColor);
painter->fillRect(rect,brush);
}
#ifndef CORNERGRABBER_H
#define CORNERGRABBER_H
#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QColor>
#include <QPainter>
#include <QPen>
#include <QPointF>
class CornerGrabber : public QGraphicsItem
{
public:
explicit CornerGrabber(QGraphicsItem *parent = 0, int corner = 0);
int getCorner(); ///< allows the owner to find out which coner this is
void setMouseState(int); ///< allows the owner to record the current mouse state
int getMouseState(); ///< allows the owner to get the current mouse state
qreal getHeight();
qreal getWidth();
bool isActive();
qreal mouseDownX;
qreal mouseDownY;
enum {kMouseReleased=0, kMouseDown, kMouseMoving}; ///< define the mouse states
enum {bottomLeft, topLeft, topRight, bottomRight};
private:
virtual QRectF boundingRect() const; ///< must be re-implemented in this class to provide the diminsions of the box to the QGraphicsView
virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); ///< must be re-implemented here to pain the box on the paint-event
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover enter events
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover leave events
// once the hover event handlers are implemented in this class,
// the mouse events must allow be implemented because of
// some linkage issue - apparrently there is some connection
// between the hover events and mouseMove/Press/Release
// events which triggers a vtable issue
virtual void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );
virtual void mouseMoveEvent(QGraphicsSceneDragDropEvent *event);
virtual void mousePressEvent (QGraphicsSceneMouseEvent * event );
virtual void mousePressEvent(QGraphicsSceneDragDropEvent *event);
virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent * event );
QColor _outterborderColor; ///< the hover event handlers will toggle this between red and black
QPen _outterborderPen; ///< the pen is used to paint the red/black border
qreal _width;
qreal _height;
int _corner;// 0,1,2,3 - starting at x=0,y=0 and moving clockwise around the box
bool _is_active;
int _mouseButtonState;
};
#endif // CORNERGRABBER_H
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <QString> #include <QString>
#define N_MAX_CRAZYFLIES 20 // protection number #define N_MAX_CRAZYFLIES 20 // protection number
#ifndef DEBUG_GUI #ifndef DEBUG_GUI
...@@ -58,13 +57,15 @@ void MainGUIWindow::_init() ...@@ -58,13 +57,15 @@ void MainGUIWindow::_init()
scene = new myGraphicsScene(ui->frame_drawing); scene = new myGraphicsScene(ui->frame_drawing);
//scene->setSceneRect(QRectF(QPointF(-100, 100), QSizeF(200, 200))); //scene->setSceneRect(QRectF(QPointF(-100, 100), QSizeF(200, 200)));
ui->graphicsView->setScene(scene); ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
item1 = new QGraphicsRectItem(0,0,100,100); item1 = new QGraphicsRectItem(0,0,100,100);
item1->setBrush(QBrush(Qt::blue)); item1->setBrush(QBrush(Qt::blue));
scene->addText("Hello world!"); scene->addText("Hello world!");
// scene->addRect(rect, QPen(Qt::black), QBrush(Qt::blue)); // scene->addRect(rect, QPen(Qt::black), QBrush(Qt::blue));
scene->addItem(item1); scene->addItem(item1);
ui->graphicsView->setScene(scene);
ui->spinBoxNumCrazyflies->setMaximum(N_MAX_CRAZYFLIES); ui->spinBoxNumCrazyflies->setMaximum(N_MAX_CRAZYFLIES);
_refresh_tabs(); _refresh_tabs();
} }
......
/****************************************************************************
** Meta object code from reading C++ file 'renderarea.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include "renderarea.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'renderarea.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.7.0. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
QT_BEGIN_MOC_NAMESPACE
struct qt_meta_stringdata_RenderArea_t {
QByteArrayData data[13];
char stringdata0[113];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_RenderArea_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
static const qt_meta_stringdata_RenderArea_t qt_meta_stringdata_RenderArea = {
{
QT_MOC_LITERAL(0, 0, 10), // "RenderArea"
QT_MOC_LITERAL(1, 11, 8), // "setShape"
QT_MOC_LITERAL(2, 20, 0), // ""
QT_MOC_LITERAL(3, 21, 5), // "Shape"
QT_MOC_LITERAL(4, 27, 5), // "shape"
QT_MOC_LITERAL(5, 33, 6), // "setPen"
QT_MOC_LITERAL(6, 40, 3), // "pen"
QT_MOC_LITERAL(7, 44, 8), // "setBrush"
QT_MOC_LITERAL(8, 53, 5), // "brush"
QT_MOC_LITERAL(9, 59, 14), // "setAntialiased"
QT_MOC_LITERAL(10, 74, 11), // "antialiased"
QT_MOC_LITERAL(11, 86, 14), // "setTransformed"
QT_MOC_LITERAL(12, 101, 11) // "transformed"
},
"RenderArea\0setShape\0\0Shape\0shape\0"
"setPen\0pen\0setBrush\0brush\0setAntialiased\0"
"antialiased\0setTransformed\0transformed"
};
#undef QT_MOC_LITERAL
static const uint qt_meta_data_RenderArea[] = {
// content:
7, // revision
0, // classname
0, 0, // classinfo
5, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: name, argc, parameters, tag, flags
1, 1, 39, 2, 0x0a /* Public */,
5, 1, 42, 2, 0x0a /* Public */,
7, 1, 45, 2, 0x0a /* Public */,
9, 1, 48, 2, 0x0a /* Public */,
11, 1, 51, 2, 0x0a /* Public */,
// slots: parameters
QMetaType::Void, 0x80000000 | 3, 4,
QMetaType::Void, QMetaType::QPen, 6,
QMetaType::Void, QMetaType::QBrush, 8,
QMetaType::Void, QMetaType::Bool, 10,
QMetaType::Void, QMetaType::Bool, 12,
0 // eod
};
void RenderArea::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
RenderArea *_t = static_cast<RenderArea *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: _t->setShape((*reinterpret_cast< Shape(*)>(_a[1]))); break;
case 1: _t->setPen((*reinterpret_cast< const QPen(*)>(_a[1]))); break;
case 2: _t->setBrush((*reinterpret_cast< const QBrush(*)>(_a[1]))); break;
case 3: _t->setAntialiased((*reinterpret_cast< bool(*)>(_a[1]))); break;
case 4: _t->setTransformed((*reinterpret_cast< bool(*)>(_a[1]))); break;
default: ;
}
}
}
const QMetaObject RenderArea::staticMetaObject = {
{ &QWidget::staticMetaObject, qt_meta_stringdata_RenderArea.data,
qt_meta_data_RenderArea, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
};
const QMetaObject *RenderArea::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *RenderArea::qt_metacast(const char *_clname)
{
if (!_clname) return Q_NULLPTR;
if (!strcmp(_clname, qt_meta_stringdata_RenderArea.stringdata0))
return static_cast<void*>(const_cast< RenderArea*>(this));
return QWidget::qt_metacast(_clname);
}
int RenderArea::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QWidget::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 5)
qt_static_metacall(this, _c, _id, _a);
_id -= 5;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 5)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 5;
}
return _id;
}
QT_END_MOC_NAMESPACE
#include "myGraphicsRectItem.h"
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsRectItem>
#include <QPen>
#include <QBrush>
#include <QApplication>
#include <QVariant>
myGraphicsRectItem::myGraphicsRectItem(const QRectF & rect, QGraphicsItem * parent)
: QGraphicsRectItem(rect, parent)
{
this->setFlag(QGraphicsItem::ItemIsSelectable);
this->setFlag(QGraphicsItem::ItemIsMovable);
pen = new QPen(Qt::red);
brush = new QBrush(Qt::red);
tmp_rect = 0;
_grabbers_created = false;
// this->setAcceptHoverEvents(true);
}
void myGraphicsRectItem::deleteGrabbers()
{
_bottomLeft_corner->setParentItem(NULL);
_topLeft_corner->setParentItem(NULL);
_topRight_corner->setParentItem(NULL);
_bottomRight_corner->setParentItem(NULL);
delete _bottomLeft_corner;
delete _topLeft_corner;
delete _topRight_corner;
delete _bottomRight_corner;
_grabbers_created = false;
}
QVariant myGraphicsRectItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == QGraphicsItem::ItemSelectedChange)
{
if (value == true)
{
qDebug("selected!");
createGrabbers();
}
else
{
qDebug("unselected!");
deleteGrabbers();
}
}
return QGraphicsItem::itemChange(change, value);
}
bool myGraphicsRectItem::grabbersAreCreated()
{
return _grabbers_created;
}
void myGraphicsRectItem::setCornerPositions()
{
QRectF rect = this->rect();
_bottomLeft_corner->setPos(rect.bottomLeft().x(), rect.bottomLeft().y() - _bottomLeft_corner->getHeight());
_topLeft_corner->setPos(rect.topLeft().x(), rect.topLeft().y());
_topRight_corner->setPos(rect.topRight().x() - _topRight_corner->getWidth(), rect.topRight().y());
_bottomRight_corner->setPos(rect.bottomRight().x() - _bottomRight_corner->getWidth(), rect.bottomRight().y() - _bottomRight_corner->getHeight());
}
void myGraphicsRectItem::createGrabbers()
{
if(!grabbersAreCreated())
{
_bottomLeft_corner = new CornerGrabber(this, CornerGrabber::bottomLeft);
_topLeft_corner = new CornerGrabber(this, CornerGrabber::topLeft);
_topRight_corner = new CornerGrabber(this, CornerGrabber::topRight);
_bottomRight_corner = new CornerGrabber(this, CornerGrabber::topRight);
_bottomLeft_corner->installSceneEventFilter(this);
_topLeft_corner->installSceneEventFilter(this);
_topRight_corner->installSceneEventFilter(this);
_bottomRight_corner->installSceneEventFilter(this);
_grabbers_created = true;
setCornerPositions();
}
}
int myGraphicsRectItem::checkCornerGrabbers()
{
// we return the first active found. Hopefully we never have two at the same time.
if(_bottomLeft_corner->isActive())
return CornerGrabber::bottomLeft;
else if(_topLeft_corner->isActive())
return CornerGrabber::topLeft;
else if (_topRight_corner->isActive())
return CornerGrabber::topRight;
else if( _bottomRight_corner->isActive())
return CornerGrabber::bottomRight;
else
return 20;
}
void myGraphicsRectItem::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (mouseEvent->button() != Qt::LeftButton)
return;
createGrabbers(); //This is just in case they have not been created by now.
switch(checkCornerGrabbers())
{
case CornerGrabber::bottomLeft:
qDebug("bottomLeft");
mouseEvent->setAccepted(true);
break;
case CornerGrabber::topLeft:
qDebug("topLeft");
mouseEvent->setAccepted(true);
break;
case CornerGrabber::topRight:
qDebug("topRight");
mouseEvent->setAccepted(true);
break;
case CornerGrabber::bottomRight:
qDebug("bottomRight");
mouseEvent->setAccepted(true);
break;
default:
qDebug("No corner");
// Normal case here, mouse not in corner grabbers
QGraphicsRectItem::mousePressEvent(mouseEvent);
break;
}
// TODO: check if over handlers, if, resize mode
}
void myGraphicsRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
this->prepareGeometryChange();
QGraphicsRectItem::mouseMoveEvent(mouseEvent);
}
void myGraphicsRectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (mouseEvent->button() != Qt::LeftButton)
return;
// TODO: stop resize mode
QGraphicsRectItem::mouseReleaseEvent(mouseEvent);
}
#ifndef MYGRAPHICSRECTITEM_H
#define MYGRAPHICSRECTITEM_H
#include <vector>
#include <QGraphicsRectItem>
#include "cornergrabber.h"
class QGraphicsSceneMouseEvent;
class QPointF;
class QColor;
class myGraphicsRectItem : public QGraphicsRectItem
{
public:
explicit myGraphicsRectItem(const QRectF & rect, QGraphicsItem * parent = 0);
public slots:
signals:
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
private:
void setCornerPositions();
int checkCornerGrabbers();
void createGrabbers();
bool grabbersAreCreated();
void deleteGrabbers();
QPen* pen;
QBrush* brush;
QRectF* tmp_rect;
QGraphicsRectItem* tmp_rect_item;
QPointF* p1;
QPointF* p2;
CornerGrabber* _bottomLeft_corner;
CornerGrabber* _topLeft_corner;
CornerGrabber* _topRight_corner;
CornerGrabber* _bottomRight_corner;
bool _grabbers_created;
};
#endif