OpenWalnut  1.5.0dev
WQtNetworkEditorView.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <QMouseEvent>
26 #include <QScrollBar>
27 #include <QWheelEvent>
28 #include <QGraphicsItem>
29 
30 #include "core/common/WLogger.h"
31 #include "core/kernel/WModuleFactory.h"
32 #include "../WQtCombinerActionList.h"
33 #include "../WQtGui.h"
34 #include "../WMainWindow.h"
35 #include "../guiElements/WQtMenuFiltered.h"
36 
37 #include "WQtNetworkEditorGlobals.h"
38 #include "WQtNetworkEditorView.h"
39 
41  QGraphicsView( parent )
42 {
43  m_panning = false;
44 
45  setDragMode( QGraphicsView::NoDrag );
46  setRenderHint( QPainter::Antialiasing );
47  setMinimumSize( 20, 20 );
48 
49  setResizeAnchor( QGraphicsView::AnchorUnderMouse );
50  setAcceptDrops( true );
51 
52  m_addMenu = NULL;
53 
54  m_autoPanTimer = new QTimeLine( WNETWORKITEM_VIEWPAN_DURATION );
55  connect( m_autoPanTimer, SIGNAL( valueChanged( qreal ) ), this, SLOT( autoPanTick( qreal ) ) );
56 }
57 
59 {
60  m_addMenu = menu;
61 }
62 
64 {
65  ensureVisibleSmooth( item );
66  // centerOn( item );
67 }
68 
69 void WQtNetworkEditorView::ensureVisibleSmooth( QGraphicsItem* item , int xmargin, int ymargin )
70 {
71  // rect of the item inside the scene -> convert from scene to viewport
72  QRectF viewRect = mapFromScene( item->sceneBoundingRect() ).boundingRect();
73 
74  // actually visible area
75  qreal top = verticalScrollBar()->value();
76  qreal left = horizontalScrollBar()->value();
77  qreal width = viewport()->width();
78  qreal height = viewport()->height();
79 
80  m_autoPanOrig = QPoint( left, top );
81  m_autoPanTarget = QPoint();
82 
83  // our rect somehow outside the left
84  if( viewRect.left() < xmargin )
85  {
86  m_autoPanTarget.rx() = viewRect.left() - xmargin;
87  }
88  // ... the right
89  if( viewRect.right() + xmargin > width )
90  {
91  m_autoPanTarget.rx() = viewRect.right() + xmargin - width;
92  }
93  // ... above
94  if( viewRect.top() < ymargin )
95  {
96  m_autoPanTarget.ry() = viewRect.top() - ymargin;
97  }
98 
99  // ... below
100  if( viewRect.bottom() + ymargin > height )
101  {
102  m_autoPanTarget.ry() = viewRect.bottom() + ymargin - height;
103  }
104 
105  m_autoPanTimer->stop();
106  m_autoPanTimer->start();
107 }
108 
110 {
111  moveTo( m_autoPanOrig + value * m_autoPanTarget );
112 }
113 
114 void WQtNetworkEditorView::moveBy( const QPointF& delta )
115 {
116  QScrollBar* horiz = horizontalScrollBar();
117  QScrollBar* vert = verticalScrollBar();
118  horiz->setValue( horiz->value() - delta.x() );
119  vert->setValue( vert->value() - delta.y() );
120 }
121 
122 void WQtNetworkEditorView::moveTo( const QPointF& target )
123 {
124  horizontalScrollBar()->setValue( target.x() );
125  verticalScrollBar()->setValue( target.y() );
126 }
127 
129 {
130  // are we in pan mode?
131  if( !m_lastPanPoint.isNull() )
132  {
133  // if the widget is left by the mouse during pan: deactivate pan
134  m_lastPanPoint = QPoint();
135  }
136 
137  // forward
138  QGraphicsView::leaveEvent( event );
139 }
140 
142 {
143  // only apply if no item is hit
144  if( items( event->pos() ).size() != 0 )
145  {
146  QGraphicsView::mouseDoubleClickEvent( event );
147  return;
148  }
149 
150  // open the add menu when a modifier was pressed
151  if( ( event->modifiers() == Qt::ShiftModifier ) ||
152  ( event->modifiers() == Qt::ControlModifier )
153  )
154  {
155  if( m_addMenu )
156  {
157  m_addMenu->popup( event->globalPos() );
158  }
159  }
160  else if( event->modifiers() == Qt::NoModifier )
161  {
162  // plain double-click -> open file
163  emit loadAction();
164  }
165 }
166 
167 void WQtNetworkEditorView::mousePressEvent( QMouseEvent* event )
168 {
169  // only pan if no element is hit
170  if( items( event->pos() ).size() != 0 )
171  {
172  QGraphicsView::mousePressEvent( event );
173  return;
174  }
175 
176  // also ignore middle mouse button
177  if( event->button() == Qt::MiddleButton )
178  {
179  event->accept();
180  return;
181  }
182 
183  if( event->button() == Qt::LeftButton )
184  {
185  // for panning the view
186  m_lastPanPoint = event->pos();
187  m_panning = true;
188  setCursor( Qt::ClosedHandCursor );
189  }
190  QGraphicsView::mousePressEvent( event );
191 }
192 
193 void WQtNetworkEditorView::mouseReleaseEvent( QMouseEvent* event )
194 {
195  // middle mouse button release: open add-menu
196  if( event->button() == Qt::MiddleButton )
197  {
198  if( m_addMenu )
199  {
200  m_addMenu->popup( event->globalPos() );
201  }
202  return;
203  }
204 
205  setCursor( Qt::ArrowCursor );
206  m_lastPanPoint = QPoint();
207  m_panning = false;
208  QGraphicsView::mouseReleaseEvent( event );
209 }
210 
211 void WQtNetworkEditorView::mouseMoveEvent( QMouseEvent* event )
212 {
213  // are we in pan mode?
214  if( m_panning )
215  {
216  // get how much we panned
217  QPointF delta = mapToScene( m_lastPanPoint ) - mapToScene( event->pos() );
218  m_lastPanPoint = event->pos();
219 
220  // update the center ie. do the pan
221  moveBy( -delta );
222 
223  // during pan, avoid anyone else to handle this event
224  event->accept();
225  return;
226  }
227  QGraphicsView::mouseMoveEvent( event );
228 }
229 
230 void WQtNetworkEditorView::wheelEvent( QWheelEvent* event )
231 {
232  // scale the view ie. do the zoom
233  double scaleFactor = 1.15;
234 
235  if( event->angleDelta().y() > 0 )
236  {
237  // zoom in
238  scale( scaleFactor, scaleFactor );
239  }
240  // We check both because smaller AND larger than zero because
241  // we want to handle y events and ignore x events
242  else if( event->angleDelta().y() < 0 )
243  {
244  // zooming out
245  scale( 1.0 / scaleFactor, 1.0 / scaleFactor );
246  }
247 
248  // we do not forward this event to avoid the scrollbox to scroll around while zooming
249  event->accept();
250 }
251 
252 void WQtNetworkEditorView::resizeEvent( QResizeEvent* event )
253 {
254  // call the subclass resize so the scrollbars are updated correctly
255  QGraphicsView::resizeEvent( event );
256 }
257 
258 void WQtNetworkEditorView::keyPressEvent( QKeyEvent *event )
259 {
260  // scale the view ie. do the zoom
261  double scaleFactor = 1.15;
262  if( event->matches( QKeySequence::ZoomIn ) )
263  {
264  // zoom in
265  scale( scaleFactor, scaleFactor );
266  }
267  if( event->matches( QKeySequence::ZoomOut ) )
268  {
269  // zooming out
270  scale( 1.0 / scaleFactor, 1.0 / scaleFactor );
271  }
272  QGraphicsView::keyPressEvent( event );
273 }
274 
275 void WQtNetworkEditorView::dropEvent( QDropEvent* event )
276 {
277  // strangely this does not communicate down to WMainWindow although all parents are set properly. Even more strange is the fact that the
278  // dropEvent does not get fired inside the WQtNetworkScene.
279  emit dragDrop( event );
280  QGraphicsView::dropEvent( event );
281 }
QPoint m_autoPanTarget
Auto-pan vector.
void ensureVisibleSmooth(QGraphicsItem *item, int xmargin=50, int ymargin=50)
Improved version of QGraphicsView::ensureVisible for smooth scrolling.
virtual void mouseReleaseEvent(QMouseEvent *event)
Mouse button released.
virtual void wheelEvent(QWheelEvent *event)
Mouse wheel used.
void focusOn(QGraphicsItem *item)
The Item to focus on.
virtual void mousePressEvent(QMouseEvent *event)
Mouse button pressed.
void moveBy(const QPointF &delta)
Move scene in the view by delta units.
virtual void mouseDoubleClickEvent(QMouseEvent *event)
Double clicked into the view.
void dragDrop(QDropEvent *event)
Emitted whenever the user drops something into the widget.
QMenu * m_addMenu
The menu containing the add actions in m_addModuleActionList.
QPoint m_autoPanOrig
Origin of auto-pan movement for proper interpolation.
void moveTo(const QPointF &target)
Move scrollarea to absolute position.
virtual void dropEvent(QDropEvent *event)
Handles the drop event for a tree item.
void loadAction()
Emitted whenever the user caused a load event.
void leaveEvent(QEvent *event)
Mouse leaves the widget.
virtual void resizeEvent(QResizeEvent *event)
View resized.
QTimeLine * m_autoPanTimer
Auto-pan timer.
WQtNetworkEditorView(QWidget *parent=NULL)
Constructs empty view.
void keyPressEvent(QKeyEvent *event)
Key pressed.
QPoint m_lastPanPoint
To keep track of mouse movement, cache last known mouse event point.
void autoPanTick(qreal value)
Called every tick of the auto pan timer.
bool m_panning
If true, we are in pan mode.
void setGlobalAddMenu(QMenu *menu)
Set the given menu as new global add-modules menu.
virtual void mouseMoveEvent(QMouseEvent *event)
Mouse moved.