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