1 // Copyright (c) 2008 GeometryFactory Sarl (France).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/GraphicsView/include/CGAL/Qt/GraphicsViewPolylineInput_impl.h $
7 // $Id: GraphicsViewPolylineInput_impl.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com>
12 // Laurent Rineau <Laurent.Rineau@geometryfactory.com>
13
14 #ifdef CGAL_HEADER_ONLY
15 #define CGAL_INLINE_FUNCTION inline
16
17 #include <CGAL/license/GraphicsView.h>
18
19 #else
20 #define CGAL_INLINE_FUNCTION
21 #endif
22
23 #include <QGraphicsItem>
24 #include <QGraphicsPathItem>
25 #include <QGraphicsScene>
26 #include <QGraphicsSceneMouseEvent>
27 #include <QPainter>
28 #include <QPolygonF>
29 #include <QPainterPath>
30 #include <QEvent>
31 #include <QKeyEvent>
32
33 namespace CGAL {
34 namespace Qt {
35
36 CGAL_INLINE_FUNCTION
37 GraphicsViewPolylineInput_non_templated_base::
GraphicsViewPolylineInput_non_templated_base(QObject * parent,QGraphicsScene * s,int n,bool closed)38 GraphicsViewPolylineInput_non_templated_base(QObject* parent,
39 QGraphicsScene* s,
40 int n,
41 bool closed)
42 : GraphicsViewInput(parent), closed_(closed), path_item(nullptr), b(nullptr), e(nullptr), n_(n), scene_(s)
43 {}
44
45
46 CGAL_INLINE_FUNCTION
47 bool
mousePressEvent(QGraphicsSceneMouseEvent * event)48 GraphicsViewPolylineInput_non_templated_base::mousePressEvent(QGraphicsSceneMouseEvent *event)
49 {
50 if( event->modifiers() ){
51 return false;
52 }
53 if( event->button() != ::Qt::RightButton
54 && event->button() != ::Qt::LeftButton ){
55 return false;
56 }
57 polygon.push_back(event->scenePos());
58 if(path_item){
59 scene_->removeItem(path_item);
60 delete path_item;
61 path_item = nullptr;
62 }
63 if( (event->button() == ::Qt::RightButton) || (polygon.size() == n_) ){
64 // call the virtual function generate_polygon(), that emit a
65 // CGAL::Object containing a list of points
66 generate_polygon();
67 polygon.clear();
68 if(b){
69 scene_->removeItem(b);
70 delete b;
71 b = nullptr;
72 }
73 if(e){
74 scene_->removeItem(e);
75 delete e;
76 e = nullptr;
77 }
78 return true;
79 }
80 if(event->button() == ::Qt::LeftButton){
81 QPainterPath qpp;
82 qpp.addPolygon(polygon);
83 path_item = new QGraphicsPathItem(qpp);
84 path_item->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin));
85 scene_->addItem(path_item);
86 return true;
87 }
88 return false;
89 }
90
91
92 CGAL_INLINE_FUNCTION
93 void
rubberbands(const QPointF & p)94 GraphicsViewPolylineInput_non_templated_base::rubberbands(const QPointF& p)
95 {
96 if(polygon.empty()){
97 return;
98 }
99 if(!b && closed_ ){
100 b = new QGraphicsLineItem();
101 b->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin));
102 scene_->addItem(b);
103 }
104 if( !e){
105 e = new QGraphicsLineItem();
106 e->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin));
107 scene_->addItem(e);
108 }
109 if(closed_){
110 QLineF bLine(polygon.front(), p);
111 b->setLine(bLine);
112 }
113 QLineF eLine(polygon.back(), p);
114 e->setLine(eLine);
115 }
116
117
118 CGAL_INLINE_FUNCTION
119 void
mouseMoveEvent(QGraphicsSceneMouseEvent * event)120 GraphicsViewPolylineInput_non_templated_base::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
121 {
122 sp = event->scenePos();
123 rubberbands(sp);
124 }
125
126
127 CGAL_INLINE_FUNCTION
128 bool
keyPressEvent(QKeyEvent * event)129 GraphicsViewPolylineInput_non_templated_base::keyPressEvent ( QKeyEvent * event )
130 {
131 if( event->modifiers() )
132 return false;
133
134 switch(event->key())
135 {
136 case ::Qt::Key_Delete:
137 case ::Qt::Key_Escape:
138 case ::Qt::Key_Backspace:
139 break;
140 default:
141 return false;
142 }
143 if(polygon.empty()){
144 return true;
145 }
146 polygon.pop_back();
147 if(polygon.empty()){
148 if(b){
149 scene_->removeItem(b);
150 delete b;
151 b = nullptr;
152 }
153 if(e){
154 scene_->removeItem(e);
155 delete e;
156 e = nullptr;
157 }
158 return true;
159 }
160 if(path_item){
161 scene_->removeItem(path_item);
162 delete path_item;
163 path_item = nullptr;
164 }
165 QPainterPath qpp;
166 qpp.addPolygon(polygon);
167 path_item = new QGraphicsPathItem(qpp);
168 path_item->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin));
169 scene_->addItem(path_item);
170 rubberbands(sp);
171 return true;
172 }
173
174
175
176 CGAL_INLINE_FUNCTION
177 bool
eventFilter(QObject * obj,QEvent * event)178 GraphicsViewPolylineInput_non_templated_base::eventFilter(QObject *obj, QEvent *event)
179 {
180 if (event->type() == QEvent::GraphicsSceneMousePress) {
181 QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
182 if(!mousePressEvent(mouseEvent)) {
183 // standard event processing if mousePressEvent has returned false
184 return QObject::eventFilter(obj, event);
185 }
186 } else if (event->type() == QEvent::GraphicsSceneMouseMove) {
187 QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
188 mouseMoveEvent(mouseEvent);
189 return QObject::eventFilter(obj, event);
190 } else if (event->type() == QEvent::KeyPress) {
191 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
192 if(!keyPressEvent(keyEvent)) {
193 return QObject::eventFilter(obj, event);
194 }
195 }
196 // standard event processing if keyPressEvent has returned false
197 return QObject::eventFilter(obj, event);
198 }
199
200 } // namespace Qt
201 } // namespace CGAL
202