1 /*
2  For general Scribus (>=1.3.2) copyright and licensing information please refer
3  to the COPYING file provided with the program. Following this notice may exist
4  a copyright and/or license notice that predates the release of Scribus 1.3.2
5  for which a new license (GPL+exception) is in place.
6  */
7 /***************************************************************************
8 *                                                                         *
9 *   This program is free software; you can redistribute it and/or modify  *
10 *   it under the terms of the GNU General Public License as published by  *
11 *   the Free Software Foundation; either version 2 of the License, or     *
12 *   (at your option) any later version.                                   *
13 *                                                                         *
14 ***************************************************************************/
15 
16 
17 #include "canvasmode_normal.h"
18 
19 #include <QApplication>
20 #include <QButtonGroup>
21 #include <QCheckBox>
22 #include <QCursor>
23 #include <QEvent>
24 #include <QMessageBox>
25 #include <QMouseEvent>
26 #include <QPainterPath>
27 #include <QPoint>
28 #include <QRect>
29 #include <QTimer>
30 #include <QToolTip>
31 #include <QWidgetAction>
32 #include <QDrag>
33 #include <QDebug>
34 
35 #include "appmodes.h"
36 #include "canvas.h"
37 #include "canvasgesture_linemove.h"
38 #include "canvasgesture_resize.h"
39 #include "canvasgesture_rulermove.h"
40 #include "fileloader.h"
41 #include "fpoint.h"
42 #include "fpointarray.h"
43 #include "hyphenator.h"
44 #include "iconmanager.h"
45 #include "loadsaveplugin.h"
46 #include "pageitem_arc.h"
47 #include "pageitem_line.h"
48 #include "pageitem_regularpolygon.h"
49 #include "plugins/formatidlist.h"
50 #include "prefscontext.h"
51 #include "prefsfile.h"
52 #include "prefsmanager.h"
53 #include "scmimedata.h"
54 #include "scraction.h"
55 #include "scribus.h"
56 #include "scribusXml.h"
57 #include "scribusdoc.h"
58 #include "scribusview.h"
59 #include "selection.h"
60 #include "ui/aligndistribute.h"
61 #include "ui/contextmenu.h"
62 #include "ui/customfdialog.h"
63 #include "ui/insertTable.h"
64 #include "ui/pageselector.h"
65 #include "ui/polyprops.h"
66 #include "ui/propertiespalette.h"
67 #include "ui/propertiespalette_line.h"
68 #include "ui/propertiespalette_text.h"
69 #include "ui/propertiespalette_xyz.h"
70 #include "undomanager.h"
71 #include "util.h"
72 #include "util_math.h"
73 
CanvasMode_Normal(ScribusView * view)74 CanvasMode_Normal::CanvasMode_Normal(ScribusView* view) : CanvasMode(view), m_ScMW(view->m_ScMW)
75 {
76 }
77 
GetItem(PageItem ** pi)78 inline bool CanvasMode_Normal::GetItem(PageItem** pi)
79 {
80 	*pi = m_doc->m_Selection->itemAt(0);
81 	return (*pi) != nullptr;
82 }
83 
drawControls(QPainter * p)84 void CanvasMode_Normal::drawControls(QPainter* p)
85 {
86 //	qDebug() << "CanvasMode_Normal::drawControls";
87 	if (m_canvas->m_viewMode.operItemMoving)
88 		drawOutline(p, m_objectDeltaPos.x(), m_objectDeltaPos.y());
89 	else
90 		drawSelection(p, !m_doc->drawAsPreview);
91 }
92 
enterEvent(QEvent * e)93 void CanvasMode_Normal::enterEvent(QEvent *e)
94 {
95 	if (!m_canvas->m_viewMode.m_MouseButtonPressed)
96 	{
97 		setModeCursor();
98 	}
99 }
100 
leaveEvent(QEvent * e)101 void CanvasMode_Normal::leaveEvent(QEvent *e)
102 {
103 }
104 
105 
activate(bool fromGesture)106 void CanvasMode_Normal::activate(bool fromGesture)
107 {
108 //	qDebug() << "CanvasMode_Normal::activate" << fromGesture;
109 	CanvasMode::activate(fromGesture);
110 
111 	m_canvas->m_viewMode.m_MouseButtonPressed = false;
112 	m_canvas->resetRenderMode();
113 	m_doc->DragP = false;
114 	m_doc->leaveDrag = false;
115 	m_canvas->m_viewMode.operItemMoving = false;
116 	m_canvas->m_viewMode.operItemResizing = false;
117 	m_view->MidButt = false;
118 	m_mousePressPoint.setXY(0, 0);
119 	m_mouseCurrentPoint.setXY(0, 0);
120 	m_mouseSavedPoint.setXY(0, 0);
121 	m_objectDeltaPos.setXY(0,0 );
122 	m_frameResizeHandle = -1;
123 	m_shiftSelItems = false;
124 	m_hoveredItem = nullptr;
125 	setModeCursor();
126 	if (fromGesture)
127 	{
128 		m_view->update();
129 	}
130 }
131 
deactivate(bool forGesture)132 void CanvasMode_Normal::deactivate(bool forGesture)
133 {
134 //	qDebug() << "CanvasMode_Normal::deactivate" << forGesture;
135 	m_view->setRedrawMarkerShown(false);
136 	CanvasMode::deactivate(forGesture);
137 }
138 
mouseDoubleClickEvent(QMouseEvent * m)139 void CanvasMode_Normal::mouseDoubleClickEvent(QMouseEvent *m)
140 {
141 	PageItem *currItem = nullptr;
142 	m->accept();
143 	m_canvas->m_viewMode.m_MouseButtonPressed = false;
144 	if (m_doc->drawAsPreview)
145 	{
146 		if (GetItem(&currItem))
147 		{
148 			if (currItem->isAnnotation())
149 			{
150 				if (currItem->annotation().Type() == Annotation::Text)
151 				{
152 					currItem->annotation().setOpen(!currItem->annotation().IsOpen());
153 					currItem->asTextFrame()->setTextAnnotationOpen(currItem->annotation().IsOpen());
154 					currItem->update();
155 					m_view->updateContents();
156 				}
157 			}
158 		}
159 		return;
160 	}
161 	m_canvas->resetRenderMode();
162 //	m_view->stopDragTimer();
163 	if (m_doc->m_Selection->isMultipleSelection())
164 	{
165 		if (GetItem(&currItem))
166 		{
167 			/* CB: old code, removing this as shift-alt select on an unselected table selects a cell now.
168 			//#6789 is closed by sorting this.
169 			if (currItem->isTableItem)
170 			{
171 				m_view->Deselect(false);
172 				m_doc->m_Selection->addItem(currItem);
173 				currItem->isSingleSel = true;
174 				//CB FIXME don't call this if the added item is item 0
175 				if (!m_doc->m_Selection->primarySelectionIs(currItem))
176 					currItem->emitAllToGUI();
177 				m_view->updateContents(currItem->getRedrawBounding(m_canvas->scale()));
178 			}*/
179 		}
180 		return;
181 	}
182 	if (GetItem(&currItem))
183 	{
184 		if (currItem->isLatexFrame())
185 		{
186 			if (currItem->locked()) // || (!currItem->ScaleType))
187 			{
188 				return;
189 			}
190 			if (currItem->imageVisible())
191 				m_view->requestMode(modeEdit);
192 		}
193 		else if (currItem->isOSGFrame())
194 		{
195 			m_view->requestMode(submodeEditExternal);
196 		}
197 		else if ((currItem->itemType() == PageItem::Polygon) || (currItem->itemType() == PageItem::PolyLine) || (currItem->itemType() == PageItem::Group) || (currItem->itemType() == PageItem::ImageFrame) || (currItem->itemType() == PageItem::PathText))
198 		{
199 			if (currItem->locked()) //|| (!currItem->ScaleType))
200 			{
201 				//mousePressEvent(m);
202 				return;
203 			}
204 			//If we double click on an image frame and theres no image assigned, open the
205 			//load picture dialog, else put it into edit mode if the frame is set to show the image
206 			if (currItem->itemType() == PageItem::ImageFrame)
207 			{
208 				if (currItem->Pfile.isEmpty())
209 					m_view->requestMode(submodeLoadPic);
210 				else if (!currItem->imageIsAvailable)
211 					m_view->requestMode(submodeStatusPic);
212 				else if (currItem->imageVisible())
213 					m_view->requestMode(modeEdit);
214 			}
215 			else if (currItem->itemType() == PageItem::TextFrame)
216 			{
217 				m_view->requestMode(modeEdit);
218 			}
219 			else
220 			{
221 				m_view->requestMode(modeEditClip);
222 				m_ScMW->scrActions["itemUngroup"]->setEnabled(false);
223 			}
224 		}
225 		else if (currItem->itemType() == PageItem::TextFrame)
226 		{
227 			// See if double click was on a frame handle
228 			FPoint p = m_canvas->globalToCanvas(m->globalPos());
229 			Canvas::FrameHandle fh = m_canvas->frameHitTest(QPointF(p.x(),p.y()), currItem);
230 			//CB if annotation, open the annotation dialog
231 			if (currItem->isAnnotation())
232 			{
233 				m_view->requestMode(submodeAnnotProps);
234 				//mousePressEvent(m);
235 			}
236 			else if (fh == Canvas::SOUTH)
237 				currItem->asTextFrame()->setTextFrameHeight();
238 			//else if not in mode edit, set mode edit
239 			else if (m_doc->appMode != modeEdit)
240 			{
241 				m_view->requestMode(modeEdit);
242 				m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
243 				//used for updating Notes Styles Editor and menu actions for marks
244 				//if cursor is in mark`s place
245 				m_ScMW->setTBvals(currItem);
246 				//CB ignore the double click and go with a single one
247 				//if we werent in mode edit before.
248 				//unsure if this is correct, but its ok given we had no
249 				//double click select until now.
250 //				mousePressEvent(m);
251 			}
252 		}
253 		else if (currItem->isSymbol())
254 		{
255 			if (!m_doc->symbolEditMode())
256 				m_view->requestMode(submodeEditSymbol);
257 		}
258 		else if (currItem->isArc())
259 		{
260 			m_view->requestMode(modeEditArc);
261 		}
262 		else if (currItem->isRegularPolygon())
263 		{
264 			m_view->requestMode(modeEditPolygon);
265 		}
266 		else if (currItem->isSpiral())
267 		{
268 			m_view->requestMode(modeEditSpiral);
269 		}
270 		else if (currItem->isTable())
271 		{
272 			m_view->requestMode(modeEditTable);
273 			m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
274 			m_ScMW->setTBvals(currItem);
275 		}
276 	}
277 }
278 
279 
mouseMoveEvent(QMouseEvent * m)280 void CanvasMode_Normal::mouseMoveEvent(QMouseEvent *m)
281 {
282 // 	qDebug()<<"CanvasMode_Normal::mouseMoveEvent";
283 // 	const double mouseX = m->globalX();
284 // 	const double mouseY = m->globalY();
285 	const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
286 
287 	bool wasLastPostOverGuide = m_lastPosWasOverGuide;
288 	m_lastPosWasOverGuide = false;
289 	PageItem *currItem=nullptr;
290 	bool erf = false;
291 	m->accept();
292 //	qDebug() << "legacy mode move:" << m->x() << m->y() << m_canvas->globalToCanvas(m->globalPos()).x() << m_canvas->globalToCanvas(m->globalPos()).y();
293 //	emit MousePos(m->x()/m_canvas->scale(),// + m_doc->minCanvasCoordinate.x(),
294 //				  m->y()/m_canvas->scale()); // + m_doc->minCanvasCoordinate.y());
295 
296 	if (commonMouseMove(m))
297 		return;
298 //	m_mouseCurrentPoint = mousePointDoc;
299 	bool movingOrResizing = (m_canvas->m_viewMode.operItemMoving || m_canvas->m_viewMode.operItemResizing);
300 	bool mouseIsOnPage    = (m_doc->OnPage(mousePointDoc.x(), mousePointDoc.y()) != -1);
301 	if ((m_doc->guidesPrefs().guidesShown) && (!m_doc->GuideLock) && (!movingOrResizing) && (mouseIsOnPage))
302 	{
303 		// #9002: Resize points undraggable when object is aligned to a guide
304 		// Allow item resize when guides are aligned to item while preserving
305 		// ability to drag guide when guis is in foreground and inside selection
306 		bool enableGuideGesture(false);
307 		Canvas::FrameHandle frameResizeHandle(Canvas::OUTSIDE);
308 		if (m_doc->m_Selection->count() > 0)
309 		{
310 			double gx = 0.0;
311 			double gy = 0.0;
312 			double gw = 0.0;
313 			double gh = 0.0;
314 			m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
315 			frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(), mousePointDoc.y()), QRectF(gx, gy, gw, gh));
316 		}
317 		else
318 		{
319 			PageItem* hoveredItem = m_canvas->itemUnderCursor(m->globalPos(), nullptr, m->modifiers());
320 			if (hoveredItem)
321 				frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(), mousePointDoc.y()), hoveredItem);
322 		}
323 		enableGuideGesture |= (frameResizeHandle == Canvas::OUTSIDE);
324 		enableGuideGesture |= ((m_doc->guidesPrefs().renderStackOrder.indexOf(3) > m_doc->guidesPrefs().renderStackOrder.indexOf(4)) && ((frameResizeHandle == Canvas::INSIDE) && (m->modifiers() != SELECT_BENEATH)));
325 		enableGuideGesture |= ((m_doc->guidesPrefs().renderStackOrder.indexOf(3) < m_doc->guidesPrefs().renderStackOrder.indexOf(4)) && ((frameResizeHandle == Canvas::INSIDE) && (m->modifiers() == SELECT_BENEATH)));
326 		if (enableGuideGesture)
327 		{
328 			if (!m_guideMoveGesture)
329 			{
330 				m_guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
331 				connect(m_guideMoveGesture, SIGNAL(guideInfo(int,qreal)), m_ScMW->alignDistributePalette, SLOT(setGuide(int,qreal)));
332 			}
333 			if (m_guideMoveGesture->mouseHitsGuide(mousePointDoc))
334 			{
335 				m_lastPosWasOverGuide = true;
336 				switch (m_guideMoveGesture->getMode())
337 				{
338 					case RulerGesture::HORIZONTAL:
339 						m_view->setCursor(QCursor(Qt::SplitVCursor));
340 						break;
341 					case RulerGesture::VERTICAL:
342 						m_view->setCursor(QCursor(Qt::SplitHCursor));
343 						break;
344 					default:
345 						m_view->setCursor(QCursor(Qt::ArrowCursor));
346 				}
347 				return;
348 			}
349 			m_view->setCursor(QCursor(Qt::ArrowCursor));
350 		}
351 		if (wasLastPostOverGuide)
352 		{
353 			Qt::CursorShape cursorShape = m_view->cursor().shape();
354 			if ((cursorShape == Qt::SplitHCursor) || (cursorShape == Qt::SplitVCursor))
355 				m_view->setCursor(QCursor(Qt::ArrowCursor));
356 		}
357 	}
358 	else if (!mouseIsOnPage)
359 	{
360 		Qt::CursorShape cursorShape = m_view->cursor().shape();
361 		if ((cursorShape == Qt::SplitHCursor) || (cursorShape == Qt::SplitVCursor))
362 			m_view->setCursor(QCursor(Qt::ArrowCursor));
363 	}
364 
365 	//<<#10116 Show overflow counter HUD
366 	if (!movingOrResizing && mouseIsOnPage)
367 	{
368 		PageItem* hoveredItem = nullptr;
369 		hoveredItem = m_canvas->itemUnderCursor(m->globalPos(), hoveredItem, m->modifiers());
370 		if (hoveredItem)
371 		{
372 			if (m_doc->drawAsPreview)
373 			{
374 				if (hoveredItem->isAnnotation())
375 				{
376 					QString toolT = "";
377 					if (!hoveredItem->annotation().ToolTip().isEmpty())
378 						toolT = hoveredItem->annotation().ToolTip();
379 					if (hoveredItem->annotation().Type() == Annotation::Button)
380 					{
381 						if (!hoveredItem->annotation().RollOver().isEmpty())
382 							toolT = hoveredItem->annotation().RollOver();
383 						else if (!hoveredItem->annotation().Down().isEmpty())
384 							toolT = hoveredItem->annotation().Down();
385 					}
386 					else if (hoveredItem->annotation().Type() == Annotation::Link)
387 					{
388 						if (hoveredItem->annotation().ActionType() == Annotation::Action_GoTo)
389 							toolT = QString( tr("Go to Page %1").arg(hoveredItem->annotation().Ziel() + 1));
390 						else if (hoveredItem->annotation().ActionType() == Annotation::Action_URI)
391 							toolT = QString( tr("Go to URL %1").arg(hoveredItem->annotation().Extern()));
392 						else if ((hoveredItem->annotation().ActionType() == Annotation::Action_GoToR_FileAbs) || (hoveredItem->annotation().ActionType() == Annotation::Action_GoToR_FileRel))
393 							toolT = QString( tr("Go to Page %1 in File %2").arg(hoveredItem->annotation().Ziel() + 1).arg(hoveredItem->annotation().Extern()));
394 						m_view->setCursor(QCursor(Qt::PointingHandCursor));
395 					}
396 					if (toolT.isEmpty())
397 						toolT = hoveredItem->itemText.plainText();
398 					if (!toolT.isEmpty())
399 						QToolTip::showText(m->globalPos() + QPoint(5, 5), toolT, m_canvas);
400 					if (hoveredItem != m_hoveredItem)
401 					{
402 						if (m_hoveredItem)
403 							handleMouseLeave(m_hoveredItem);
404 						handleMouseEnter(hoveredItem);
405 					}
406 					m_hoveredItem = hoveredItem;
407 					if ((hoveredItem->annotation().Type() == Annotation::Text) && (hoveredItem->annotation().IsOpen()))
408 					{
409 						if (m_view->moveTimerElapsed() && m_canvas->m_viewMode.m_MouseButtonPressed && (m->buttons() & Qt::LeftButton) && (!hoveredItem->locked()))
410 						{
411 							double dx = mousePointDoc.x() - m_mouseCurrentPoint.x();
412 							double dy = mousePointDoc.y() - m_mouseCurrentPoint.y();
413 							hoveredItem->setXYPos(hoveredItem->xPos() + dx, hoveredItem->yPos() + dy, true);
414 							m_mouseCurrentPoint = mousePointDoc;
415 							m_canvas->resetRenderMode();
416 							m_canvas->setRenderModeUseBuffer(false);
417 							m_canvas->repaint();
418 						}
419 					}
420 				}
421 				else
422 				{
423 					if (QToolTip::isVisible())
424 						QToolTip::hideText();
425 					m_hoveredItem = nullptr;
426 				}
427 			}
428 			else
429 			{
430 				if (hoveredItem->isTextFrame() && hoveredItem->frameOverflows())
431 				{
432 					if (m_canvas->cursorOverTextFrameControl(m->globalPos(), hoveredItem))
433 					{
434 						QToolTip::showText(m->globalPos() + QPoint(5, 5), tr("Overflow Characters: %1 (%2 White Spaces)\nClick to link to existing text frame or auto-create new linked text frame").arg(hoveredItem->frameOverflowCount()).arg(hoveredItem->frameOverflowBlankCount()), m_canvas);
435 					}
436 				}
437 				else
438 					if (QToolTip::isVisible())
439 						QToolTip::hideText();
440 			}
441 		}
442 		else
443 		{
444 			if (QToolTip::isVisible())
445 				QToolTip::hideText();
446 			if (m_doc->drawAsPreview)
447 			{
448 				if (m_hoveredItem)
449 					handleMouseLeave(m_hoveredItem);
450 				m_hoveredItem = nullptr;
451 			}
452 		}
453 	}
454 
455 	//>>#10116
456 	if (m_doc->drawAsPreview)
457 		return;
458 	m_mouseCurrentPoint = mousePointDoc;
459 	if ((GetItem(&currItem)) && (!m_shiftSelItems))
460 	{
461 		double newX = qRound(mousePointDoc.x()); //m_view->translateToDoc(m->x(), m->y()).x());
462 		double newY = qRound(mousePointDoc.y()); //m_view->translateToDoc(m->x(), m->y()).y());
463 		// #0007865
464 		if (/*(((m_view->dragTimerElapsed()) && (m->buttons() & Qt::LeftButton)) ||*/
465 			(m_view->moveTimerElapsed())
466 			&& (m->buttons() & Qt::RightButton)
467 			&& (m_canvas->m_viewMode.m_MouseButtonPressed)
468 			&& (!m_doc->DragP)
469 			&& (!(currItem->isSingleSel)))
470 		{
471 			// start drag
472 //			m_view->stopDragTimer();
473 			if ((fabs(m_mousePressPoint.x() - newX) > 10) || (fabs(m_mousePressPoint.y() - newY) > 10))
474 			{
475 				m_canvas->setRenderMode(Canvas::RENDER_NORMAL);
476 //				m_view->resetDragTimer();
477 				m_doc->DragP = true;
478 				m_doc->leaveDrag = false;
479 				m_doc->DraggedElem = currItem;
480 				m_doc->DragElements.clear();
481 				for (int dre=0; dre<m_doc->m_Selection->count(); ++dre)
482 					m_doc->DragElements.append(m_doc->m_Selection->itemAt(dre));
483 				ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_doc, m_doc->m_Selection);
484 				QDrag* dr = new QDrag(m_view);
485 				dr->setMimeData(md);
486 				const QPixmap& pm = IconManager::instance().loadPixmap("dragpix.png");
487 				dr->setPixmap(pm);
488 			//	dr->setDragCursor(pm, Qt::CopyAction);
489 			//	dr->setDragCursor(pm, Qt::MoveAction);
490 			//	dr->setDragCursor(pm, Qt::LinkAction);
491 				dr->exec();
492 				m_doc->DragP = false;
493 				m_doc->leaveDrag = false;
494 				m_canvas->m_viewMode.m_MouseButtonPressed = false;
495 				m_doc->DraggedElem = nullptr;
496 				m_doc->DragElements.clear();
497 				m_view->setCursor(QCursor(Qt::ArrowCursor));
498 				m_view->updateContents();
499 			}
500 			return;
501 		}
502 		if (m_doc->DragP)
503 			return;
504 
505 		//Operations run here:
506 		//Item resize, esp after creating a new one
507 		if (m_view->moveTimerElapsed() && m_canvas->m_viewMode.m_MouseButtonPressed && (m->buttons() & Qt::LeftButton) &&
508 			((m_doc->appMode == modeNormal)) && (!currItem->locked()))
509 		{
510 //			m_view->stopDragTimer();
511 			if (!m_canvas->m_viewMode.operItemResizing)
512 			{
513 				//Dragging an item (plus more?)
514 				newX = mousePointDoc.x(); //static_cast<int>(m->x()/sc);
515 				newY = mousePointDoc.y(); //static_cast<int>(m->y()/sc);
516 				m_canvas->m_viewMode.operItemMoving = true;
517 				if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
518 					m_view->setCursor(Qt::ClosedHandCursor);
519 				else
520 					m_view->setCursor(QCursor(Qt::ArrowCursor));
521 				erf = false;
522 				int dX = qRound(newX - m_mousePressPoint.x()), dY = qRound(newY - m_mousePressPoint.y());
523 				if (!m_doc->m_Selection->isMultipleSelection())
524 				{
525 					erf = true;
526 					currItem = m_doc->m_Selection->itemAt(0);
527 					//Control Alt drag image in frame without being in edit mode
528 					if ((currItem->isImageFrame()) && (m->modifiers() & Qt::ControlModifier) && (m->modifiers() & Qt::AltModifier))
529 					{
530 						QTransform mm1 = currItem->getTransform();
531 						QTransform mm2 = mm1.inverted();
532 						QPointF rota = mm2.map(QPointF(newX, newY)) - mm2.map(QPointF(m_mouseSavedPoint.x(), m_mouseSavedPoint.y()));
533 						currItem->moveImageInFrame(rota.x() / currItem->imageXScale(), rota.y() / currItem->imageYScale());
534 						currItem->update();
535 						m_mouseSavedPoint.setXY(newX, newY);
536 					}
537 					else
538 					{
539 						//Dragging orthogonally - Ctrl Drag
540 						if ((m->modifiers() & Qt::ControlModifier) && !(m->modifiers() & Qt::ShiftModifier) && !(m->modifiers() & Qt::AltModifier))
541 						{
542 							if (abs(dX) > abs(dY))
543 								dY = 0;
544 							else if (abs(dY) > abs(dX))
545 								dX = 0;
546 							erf = false;
547 							dX += qRound(m_dragConstrainInitPtX - currItem->xPos());
548 							dY += qRound(m_dragConstrainInitPtY - currItem->yPos());
549 						}
550 						double gx, gy, gh, gw;
551 						m_objectDeltaPos.setXY(dX, dY);
552 					//	m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
553 						m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
554 						// #10677 : temporary hack : we need to introduce the
555 						// concept of item snapping points to handle better
556 						// the various types of items
557 						if (currItem->isLine())
558 						{
559 							QPointF startPoint = currItem->asLine()->startPoint();
560 							QPointF endPoint   = currItem->asLine()->endPoint();
561 							gx = qMin(startPoint.x(), endPoint.x());
562 							gy = qMin(startPoint.y(), endPoint.y());
563 							gw = fabs(startPoint.x() - endPoint.x());
564 							gh = fabs(startPoint.y() - endPoint.y());
565 						}
566 						if (m_doc->SnapGuides)
567 						{
568 							double nx = gx + m_objectDeltaPos.x();
569 							double ny = gy + m_objectDeltaPos.y();
570 							double nxo = nx, nyo = ny;
571 							m_doc->ApplyGuides(&nx, &ny);
572 							m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
573 							nx = nxo = gx + gw + m_objectDeltaPos.x();
574 							ny = nyo = gy + gh + m_objectDeltaPos.y();
575 							m_doc->ApplyGuides(&nx, &ny);
576 							m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
577 							if (false)
578 							{
579 								nx = nxo = gx + gw / 2 + m_objectDeltaPos.x();
580 								ny = nyo = gy + gh / 2 + m_objectDeltaPos.y();
581 								m_doc->ApplyGuides(&nx, &ny);
582 								m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
583 							}
584 						}
585 						if (m_doc->SnapElement)
586 						{
587 							xSnap = 0;
588 							ySnap = 0;
589 							double snapWidth[] = { 0, gw, gw / 2 };
590 							double snapHeight[] = { 0, gh, gh / 2 };
591 							if (m_objectDeltaPos.x() < 0)
592 								std::swap(snapWidth[0], snapWidth[2]);
593 							if (m_objectDeltaPos.y() < 0)
594 								std::swap(snapHeight[0], snapHeight[2]);
595 							double nx,ny,nyo,nxo;
596 							for (int i = 0; i < 3; i++)
597 							{
598 								nx = gx + snapWidth[i] + m_objectDeltaPos.x();
599 								ny = gy + snapHeight[i] + m_objectDeltaPos.y();
600 								nxo = nx, nyo = ny;
601 								m_doc->ApplyGuides(&nx, &ny,true);
602 								m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
603 								if (ny != nyo)
604 									ySnap = ny;
605 								if (nx != nxo)
606 									xSnap = nx;
607 							}
608 						}
609 						if (m_doc->SnapGrid)
610 						{
611 							double gx, gy, gh, gw, gxo, gyo;
612 							m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
613 							gx += m_objectDeltaPos.x();
614 							gy += m_objectDeltaPos.y();
615 							gxo = gx;
616 							gyo = gy;
617 							QRectF nr  = m_doc->ApplyGridF(QRectF(gx, gy, gw, gh));
618 							gx = nr.x();
619 							gy = nr.y();
620 							if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
621 								m_objectDeltaPos += FPoint(gx - gxo, gy - gyo);
622 						}
623 					}
624 				}
625 				else
626 				{
627 					double gx, gy, gh, gw;
628 					m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
629 					int dX = qRound(newX - m_mousePressPoint.x()), dY = qRound(newY - m_mousePressPoint.y());
630 					erf = true;
631 					if (m->modifiers() & Qt::ControlModifier)
632 					{
633 						if (abs(dX) > abs(dY))
634 							dY = 0;
635 						else if (abs(dY) > abs(dX))
636 							dX = 0;
637 						erf = false;
638 						dX += m_dragConstrainInitPtX-qRound(gx);
639 						dY += m_dragConstrainInitPtY-qRound(gy);
640 					}
641 					m_objectDeltaPos.setXY(dX, dY);
642 					if (m_doc->SnapGuides)
643 					{
644 						double nx = gx + m_objectDeltaPos.x();
645 						double ny = gy + m_objectDeltaPos.y();
646 						double nxo = nx, nyo = ny;
647 						m_doc->ApplyGuides(&nx, &ny);
648 						m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
649 						nx = nxo = gx + gw + m_objectDeltaPos.x();
650 						ny = nyo = gy + gh + m_objectDeltaPos.y();
651 						m_doc->ApplyGuides(&nx, &ny);
652 						m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
653 						if (false)
654 						{
655 							nx = nxo = gx + gw/2 + m_objectDeltaPos.x();
656 							ny = nyo = gy + gh/2 + m_objectDeltaPos.y();
657 							m_doc->ApplyGuides(&nx, &ny);
658 							m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
659 						}
660 					}
661 					if (m_doc->SnapElement)
662 					{
663 						xSnap = 0;
664 						ySnap = 0;
665 						double snapWidth[] = { 0, gw, gw / 2 };
666 						double snapHeight[] = { 0, gh, gh / 2 };
667 						if (m_objectDeltaPos.x() <0 )
668 							std::swap(snapWidth[0], snapWidth[2]);
669 						if (m_objectDeltaPos.y() < 0)
670 							std::swap(snapHeight[0], snapHeight[2]);
671 						double nx,ny,nyo,nxo;
672 						for (int i = 0; i < 3; i++)
673 						{
674 							nx = gx + snapWidth[i] + m_objectDeltaPos.x();
675 							ny = gy + snapHeight[i] + m_objectDeltaPos.y();
676 							nxo = nx, nyo = ny;
677 							m_doc->ApplyGuides(&nx, &ny,true);
678 							m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
679 							if (ny != nyo)
680 								ySnap = ny;
681 							if (nx != nxo)
682 								xSnap = nx;
683 						}
684 					}
685 					if (m_doc->SnapGrid)
686 					{
687 						double gx, gy, gh, gw, gxo, gyo;
688 						m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
689 						gx += m_objectDeltaPos.x();
690 						gy += m_objectDeltaPos.y();
691 						gxo = gx;
692 						gyo = gy;
693 						QRectF nr = m_doc->ApplyGridF(QRectF(gx, gy, gw, gh));
694 						gx = nr.x();
695 						gy = nr.y();
696 						if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
697 							m_objectDeltaPos += FPoint(gx - gxo, gy - gyo);
698 					}
699 				}
700 				if (erf)
701 				{
702 					m_mouseCurrentPoint.setXY(newX, newY);
703 				}
704 
705 				{
706 					double gx, gy, gh, gw;
707 					m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
708 					m_doc->adjustCanvas(FPoint(gx,gy), FPoint(gx + gw, gy + gh));
709 					QPoint selectionCenter = m_canvas->canvasToLocal(QPointF(gx + gw / 2, gy + gh / 2));
710 					QPoint localMousePos = m_canvas->canvasToLocal(mousePointDoc);
711 					int localwidth = static_cast<int>(gw * m_canvas->scale());
712 					int localheight = static_cast<int>(gh * m_canvas->scale());
713 					if (localwidth > 200)
714 					{
715 						localwidth = 0;
716 						selectionCenter.setX(localMousePos.x());
717 					}
718 					if (localheight > 200)
719 					{
720 						localheight = 0;
721 						selectionCenter.setY(localMousePos.y());
722 					}
723 					m_view->ensureVisible(selectionCenter.x(), selectionCenter.y(), localwidth / 2 + 20, localheight / 2 + 20);
724 					m_canvas->repaint();
725 					m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
726 					m_canvas->displayCorrectedXYHUD(m->globalPos(), gx + m_objectDeltaPos.x(), gy + m_objectDeltaPos.y());
727 				}
728 			}
729 		}
730 
731 		// move page item
732 		if ((!m_canvas->m_viewMode.m_MouseButtonPressed) && (m_doc->appMode != modeDrawBezierLine))
733 		{
734 			if (m_doc->m_Selection->isMultipleSelection())
735 			{
736 				double gx, gy, gh, gw;
737 				m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
738 				int how = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
739 				if (how >= 0)
740 				{
741 					if (how > 0)
742 						setResizeCursor(how);
743 					else
744 						m_view->setCursor(QCursor(Qt::OpenHandCursor));
745 				}
746 				else
747 				{
748 					setModeCursor();
749 				}
750 				return;
751 			}
752 			for (int a = 0; a < m_doc->m_Selection->count(); ++a)
753 			{
754 				currItem = m_doc->m_Selection->itemAt(a);
755 				if (currItem->locked())
756 					break;
757 				QTransform p;
758 				m_canvas->Transform(currItem, p);
759 				QRect mpo = QRect(m->x() - m_doc->guidesPrefs().grabRadius, m->y() - m_doc->guidesPrefs().grabRadius, m_doc->guidesPrefs().grabRadius * 2, m_doc->guidesPrefs().grabRadius * 2);
760 				if ((QRegion(p.map(QPolygon(QRect(-3, -3, static_cast<int>(currItem->width() + 6), static_cast<int>(currItem->height() + 6))))).contains(mpo)))
761 				{
762 					QRect tx = p.mapRect(QRect(0, 0, static_cast<int>(currItem->width()), static_cast<int>(currItem->height())));
763 					if ((tx.intersects(mpo)) && (!currItem->locked()))
764 					{
765 						Qt::CursorShape cursorShape = Qt::OpenHandCursor;
766 						if (!currItem->sizeLocked())
767 							cursorShape = m_view->getResizeCursor(currItem, mpo, cursorShape);
768 						m_view->setCursor(QCursor(cursorShape));
769 					}
770 				}
771 			}
772 			if (GetItem(&currItem) && (m_doc->appMode == modeNormal))
773 			{
774 				int how = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
775 				if (how > 0)
776 				{
777 					if (currItem->isLine())
778 						m_view->setCursor(QCursor(Qt::SizeAllCursor));
779 					else if (!currItem->locked() && !currItem->sizeLocked())
780 					{
781 						if ((!currItem->sizeHLocked() && !currItem->sizeVLocked()) || (currItem->sizeHLocked() && (how == Canvas::SOUTH || how == Canvas::NORTH))
782 							|| (currItem->sizeVLocked() && (how == Canvas::EAST || how == Canvas::WEST)))
783 						setResizeCursor(how, currItem->rotation());
784 					}
785 				}
786 				else if (how == 0)
787 				{
788 					if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
789 						m_view->setCursor(QCursor(Qt::OpenHandCursor));
790 					else
791 						m_view->setCursor(QCursor(Qt::ArrowCursor));
792 				}
793 				else
794 				{
795 					m_view->setCursor(QCursor(Qt::ArrowCursor));
796 				}
797 			}
798 		}
799 	}
800 	else
801 	{
802 		if ((m_canvas->m_viewMode.m_MouseButtonPressed) && (m->buttons() & Qt::LeftButton))
803 		{
804 			double newX = qRound(mousePointDoc.x());
805 			double newY = qRound(mousePointDoc.y());
806 			m_mouseSavedPoint.setXY(newX, newY);
807 			QPoint startP = m_canvas->canvasToGlobal(m_mousePressPoint);
808 			m_view->redrawMarker->setGeometry(QRect(m_view->mapFromGlobal(startP), m_view->mapFromGlobal(m->globalPos())).normalized());
809 			m_view->setRedrawMarkerShown(true);
810 			m_view->HaveSelRect = true;
811 			return;
812 		}
813 	}
814 }
815 
mousePressEvent(QMouseEvent * m)816 void CanvasMode_Normal::mousePressEvent(QMouseEvent *m)
817 {
818 //	qDebug("CanvasMode_Normal::mousePressEvent");
819 	const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
820 	PageItem *currItem;
821 
822 	m_objectDeltaPos  = FPoint(0, 0);
823 	m_mousePressPoint = m_mouseCurrentPoint = mousePointDoc;
824 	m_mouseSavedPoint = mousePointDoc;
825 	m_canvas->m_viewMode.m_MouseButtonPressed = true;
826 	m_canvas->m_viewMode.operItemMoving = false;
827 	m_view->HaveSelRect = false;
828 	m_doc->DragP = false;
829 	m_doc->leaveDrag = false;
830 	m->accept();
831 	m_view->registerMousePress(m->globalPos());
832 
833 	if (m->button() == Qt::MidButton)
834 	{
835 		m_view->MidButt = true;
836 		if (m->modifiers() & Qt::ControlModifier)
837 			m_view->DrawNew();
838 		return;
839 	}
840 
841 	if ((GetItem(&currItem)) && (!m_lastPosWasOverGuide))
842 	{
843 		if ((currItem->isLine()) && (!m_doc->m_Selection->isMultipleSelection()) && (!m_doc->drawAsPreview))
844 		{
845 			if (!m_lineMoveGesture)
846 				m_lineMoveGesture = new LineMove(this);
847 
848 			m_lineMoveGesture->mousePressEvent(m);
849 			if (m_lineMoveGesture->haveLineItem())
850 			{
851 				m_view->startGesture(m_lineMoveGesture);
852 				return;
853 			}
854 		}
855 		else
856 		{
857 			bool isMS=m_doc->m_Selection->isMultipleSelection();
858 			if ((isMS || (!isMS && (!currItem->locked() && !currItem->sizeLocked()))) && (!m_doc->drawAsPreview))
859 			{
860 				if (!m_resizeGesture)
861 					m_resizeGesture = new ResizeGesture(this);
862 
863 				m_resizeGesture->mousePressEvent(m);
864 				if (m_resizeGesture->frameHandle() > 0)
865 				{
866 					m_view->startGesture(m_resizeGesture);
867 					return;
868 				}
869 			}
870 //#7928			else
871 //#7928				return;
872 		}
873 		if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
874 			m_view->setCursor(Qt::ClosedHandCursor);
875 		else
876 			m_view->setCursor(QCursor(Qt::ArrowCursor));
877 #if 1
878 		// normal edit mode
879 		m_canvas->PaintSizeRect(QRect());
880 		double gx, gy, gh, gw;
881 		bool shiftSel = true;
882 		m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
883 		m_dragConstrainInitPtX = qRound(gx);
884 		m_dragConstrainInitPtY = qRound(gy);
885 		m_frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
886 		if (m_frameResizeHandle == Canvas::OUTSIDE ||
887 			(m_frameResizeHandle == Canvas::INSIDE && m->modifiers() != Qt::NoModifier))
888 		{
889 			m_frameResizeHandle = 0;
890 			m_doc->m_Selection->delaySignalsOn();
891 			m_view->updatesOn(false);
892 			shiftSel = SeleItem(m);
893 			m_view->updatesOn(true);
894 			m_doc->m_Selection->delaySignalsOff();
895 		}
896 		if (((m_doc->m_Selection->isEmpty()) || (!shiftSel)) && (m->modifiers() == Qt::ShiftModifier))
897 		{
898 			m_shiftSelItems = true;
899 			m_mouseCurrentPoint = m_mousePressPoint = m_mouseSavedPoint = mousePointDoc;
900 		}
901 		else
902 			m_shiftSelItems = false;
903 		m_canvas->setRenderModeFillBuffer();
904 #endif
905 	}
906 	else // !GetItem()
907 	{
908 		SeleItem(m);
909 		if (m_doc->m_Selection->isEmpty())
910 		{
911 			m_mouseCurrentPoint = m_mousePressPoint = m_mouseSavedPoint = mousePointDoc;
912 			m_view->redrawMarker->setGeometry(m->globalPos().x(), m->globalPos().y(), 1, 1);
913 			m_view->setRedrawMarkerShown(true);
914 		}
915 		else
916 		{
917 			if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
918 				m_canvas->setRenderModeFillBuffer();
919 		}
920 	}
921 /*	if (m->button() == MidButton)
922 	{
923 		MidButt = true;
924 		if (m_doc->m_Selection->count() != 0)
925 			m_view->Deselect(true);
926 		DrawNew();
927 	} */
928 	if ((m_doc->m_Selection->count() != 0) && (m->button() == Qt::RightButton))
929 	{
930 		m_canvas->m_viewMode.m_MouseButtonPressed = true;
931 		m_mousePressPoint = m_mouseCurrentPoint;
932 	}
933 	if (m_doc->drawAsPreview && !m_doc->editOnPreview)
934 	{
935 		m_canvas->setRenderModeUseBuffer(false);
936 		if (m_doc->m_Selection->count() == 1)
937 		{
938 			currItem = m_doc->m_Selection->itemAt(0);
939 			if (currItem->isAnnotation())
940 			{
941 				if (currItem->annotation().Type() == Annotation::Checkbox)
942 					handleCheckBoxPress(currItem);
943 				else if (currItem->annotation().Type() == Annotation::RadioButton)
944 					handleRadioButtonPress(currItem);
945 				else if (currItem->annotation().Type() == Annotation::Button)
946 					handlePushButtonPress(currItem);
947 			}
948 		}
949 	}
950 // Commented out to fix bug #7865
951 //	if ((m_doc->m_Selection->count() != 0) && (m->button() == Qt::LeftButton) && (frameResizeHandle == 0))
952 //	{
953 //		m_view->startDragTimer();
954 //	}
955 	m_canvas->PaintSizeRect(QRect());
956 }
957 
958 
mouseReleaseEvent(QMouseEvent * m)959 void CanvasMode_Normal::mouseReleaseEvent(QMouseEvent *m)
960 {
961 //	qDebug("CanvasMode_Normal::mouseReleaseEvent");
962 #ifdef GESTURE_FRAME_PREVIEW
963 	clearPixmapCache();
964 #endif // GESTURE_FRAME_PREVIEW
965 	const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
966 	PageItem *currItem;
967 	m_canvas->m_viewMode.m_MouseButtonPressed = false;
968 	m_canvas->resetRenderMode();
969 	m->accept();
970 	m_view->setRedrawMarkerShown(false);
971 //	m_view->stopDragTimer();
972 	//m_canvas->update(); //ugly in a mouseReleaseEvent!!!!!!!
973 
974 	// right click
975 	// opens context menu
976 	if (m->button() == Qt::RightButton && (!m_doc->DragP) )
977 	{
978 		if ((!GetItem(&currItem)) && (!m_doc->drawAsPreview))
979 		{
980 			createContextMenu(nullptr, mousePointDoc.x(), mousePointDoc.y());
981 			return;
982 		}
983 		if ((GetItem(&currItem)) && (!(m_doc->drawAsPreview && !m_doc->editOnPreview)))
984 		{
985 			createContextMenu(currItem, mousePointDoc.x(), mousePointDoc.y());
986 			return;
987 		}
988 	}
989 
990 	// link text frames
991 	//<<#10116: Click on overflow icon to get into link frame mode
992 	PageItem* clickedItem = nullptr;
993 	clickedItem = m_canvas->itemUnderCursor(m->globalPos(), clickedItem, m->modifiers());
994 	if (clickedItem && clickedItem->isTextFrame() && (!clickedItem->isAnnotation()) && (!m_doc->drawAsPreview))
995 	{
996 		if (clickedItem->frameOverflows())
997 		{
998 			if (m_canvas->cursorOverTextFrameControl(m->globalPos(), clickedItem))
999 			{
1000 				m_view->requestMode(modeLinkFrames);
1001 				return;
1002 			}
1003 		}
1004 	}
1005 
1006 	// drag move?
1007 	//>>#10116
1008 	if (m_view->moveTimerElapsed() && (GetItem(&currItem)))
1009 	{
1010 //		m_view->stopDragTimer();
1011 		m_canvas->setRenderModeUseBuffer(false);
1012 		if (!m_doc->m_Selection->isMultipleSelection())
1013 		{
1014 			m_doc->setRedrawBounding(currItem);
1015 			currItem->OwnPage = m_doc->OnPage(currItem);
1016 			m_canvas->m_viewMode.operItemResizing = false;
1017 			if (currItem->isLine())
1018 				m_view->updateContents();
1019 		}
1020 		if (m_canvas->m_viewMode.operItemMoving)
1021 		{
1022 			// we want to invalidate all frames under the moved frame
1023 			// hm, I will try to be more explicit :) - pm
1024 			int itemIndex = m_doc->Items->count();
1025 			PageItem* underItem( m_canvas->itemUnderItem(currItem, itemIndex) );
1026 			while (underItem)
1027 			{
1028 				if (underItem->isTextFrame())
1029 					underItem->asTextFrame()->invalidateLayout(false);
1030 				else
1031 					underItem->invalidateLayout();
1032 
1033 				underItem =  m_canvas->itemUnderItem(currItem, itemIndex);
1034 			}
1035 
1036 			m_view->updatesOn(false);
1037 			if (!m_view->groupTransactionStarted())
1038 			{
1039 				m_view->startGroupTransaction(Um::Move, "", Um::IMove);
1040 			}
1041 			if (m_doc->m_Selection->isMultipleSelection())
1042 			{
1043 				m_doc->moveGroup(m_objectDeltaPos.x(), m_objectDeltaPos.y());
1044 				double gx, gy, gh, gw;
1045 				m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
1046 				double nx = gx;
1047 				double ny = gy;
1048 				if (!m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
1049 				{
1050 					QRectF nr  = m_doc->ApplyGridF(QRectF(gx, gy, gw, gh));
1051 					nx = nr.x();
1052 					ny = nr.y();
1053 				}
1054 				m_doc->moveGroup(nx - gx, ny - gy);
1055 				m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
1056 				nx = gx + gw;
1057 				ny = gy + gh;
1058 				if (m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
1059 					m_doc->moveGroup(nx - (gx + gw), ny - (gy + gh));
1060 				m_doc->m_Selection->setGroupRect();
1061 			}
1062 			else
1063 			{
1064 				currItem = m_doc->m_Selection->itemAt(0);
1065 				m_doc->moveItem(m_objectDeltaPos.x(), m_objectDeltaPos.y(), currItem);
1066 				if (m_doc->SnapGrid)
1067 				{
1068 					double nx = currItem->xPos();
1069 					double ny = currItem->yPos();
1070 					if (!m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
1071 					{
1072 						double gx, gy, gh, gw, gxo, gyo;
1073 						m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
1074 						gxo = gx;
1075 						gyo = gy;
1076 						QRectF nr = m_doc->ApplyGridF(QRectF(gx, gy, gw, gh));
1077 						gx = nr.x();
1078 						gy = nr.y();
1079 						if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
1080 						{
1081 							nx += (gx - gxo);
1082 							ny += (gy - gyo);
1083 						}
1084 					}
1085 					m_doc->moveItem(nx-currItem->xPos(), ny-currItem->yPos(), currItem);
1086 				}
1087 			}
1088 			m_canvas->m_viewMode.operItemMoving = false;
1089 			if (m_doc->m_Selection->isMultipleSelection())
1090 			{
1091 				double gx, gy, gh, gw;
1092 				m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
1093 				FPoint maxSize(gx + gw + m_doc->scratch()->right(), gy + gh + m_doc->scratch()->bottom());
1094 				FPoint minSize(gx - m_doc->scratch()->left(), gy - m_doc->scratch()->top());
1095 				m_doc->adjustCanvas(minSize, maxSize);
1096 			}
1097 			m_doc->setRedrawBounding(currItem);
1098 			currItem->OwnPage = m_doc->OnPage(currItem);
1099 			if (currItem->OwnPage != -1)
1100 			{
1101 				m_doc->setCurrentPage(m_doc->Pages->at(currItem->OwnPage));
1102 				m_view->m_ScMW->slotSetCurrentPage(currItem->OwnPage);
1103 			}
1104 			//CB done with emitAllToGUI
1105 			//emit HaveSel();
1106 			//EmitValues(currItem);
1107 			//CB need this for? a moved item will send its new data with the new xpos/ypos emits
1108 			//CB TODO And what if we have dragged to a new page. Items X&Y are not updated anyway now
1109 			//currItem->emitAllToGUI();
1110 			m_view->updatesOn(true);
1111 			m_view->updateContents();
1112 			m_doc->changed();
1113 		}
1114 	}
1115 
1116 
1117 	//CB Drag selection performed here
1118 	if (((m_doc->m_Selection->isEmpty()) && (m_view->HaveSelRect) && (!m_view->MidButt)) || ((m_shiftSelItems) && (m_view->HaveSelRect) && (!m_view->MidButt)))
1119 	{
1120 		// get newly selection rectangle
1121 		double dx = m_mouseSavedPoint.x() - m_mousePressPoint.x();
1122 		double dy = m_mouseSavedPoint.y() - m_mousePressPoint.y();
1123 		QRectF canvasSele = QRectF(m_mousePressPoint.x(), m_mousePressPoint.y(), dx, dy).normalized();
1124 		QRectF localSele  = m_canvas->canvasToLocalF(canvasSele).normalized();
1125 		if (!m_doc->masterPageMode())
1126 		{
1127 			uint docPagesCount = m_doc->Pages->count();
1128 			uint docCurrPageNo = m_doc->currentPageNumber();
1129 			for (uint i = 0; i < docPagesCount; ++i)
1130 			{
1131 				ScPage*  page = m_doc->Pages->at(i);
1132 				QRectF pageRect(page->xOffset(), page->yOffset(), page->width(), page->height());
1133 				if (pageRect.intersects(canvasSele))
1134 				{
1135 					if (docCurrPageNo != i)
1136 					{
1137 						m_doc->setCurrentPage(m_doc->Pages->at(i));
1138 						m_view->m_ScMW->slotSetCurrentPage(i);
1139 					}
1140 					break;
1141 				}
1142 			}
1143 			m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
1144 		}
1145 		int docItemCount = m_doc->Items->count();
1146 		if (docItemCount != 0)
1147 		{
1148 			m_doc->m_Selection->delaySignalsOn();
1149 
1150 			// modifier keys
1151 			bool altPressed = m->modifiers() & Qt::AltModifier;
1152 			bool shiftPressed = m->modifiers() & Qt::ShiftModifier;
1153 
1154 			for (int a = 0; a < docItemCount; ++a)
1155 			{
1156 				PageItem* docItem = m_doc->Items->at(a);
1157 				if ((m_doc->masterPageMode()) && (docItem->OnMasterPage != m_doc->currentPage()->pageName()))
1158 					continue;
1159 				if (m_doc->canSelectItemOnLayer(docItem->m_layerID))
1160 				{
1161 					// get current item rect/bounding box
1162 					QRectF apr2 = m_canvas->canvasToLocalF( docItem->getCurrentBoundingRect(docItem->lineWidth()) );
1163 
1164 					bool is_selected = docItem->isSelected();
1165 
1166 					// alt selection
1167 					bool select = altPressed ? localSele.intersects(apr2) :
1168 					                           localSele.contains(apr2);
1169 
1170 					// make selection
1171 					if (!is_selected && select)
1172 						m_doc->m_Selection->addItem(docItem);
1173 					else if (is_selected && shiftPressed && select) // shift selection - invert selection
1174 						m_doc->m_Selection->removeItem(docItem);
1175 				}
1176 			}
1177 			m_doc->m_Selection->delaySignalsOff();
1178 			if (m_doc->m_Selection->count() > 1)
1179 			{
1180 				double x, y, w, h;
1181 				m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
1182 				m_view->getGroupRectScreen(&x, &y, &w, &h);
1183 			}
1184 		}
1185 		m_view->HaveSelRect = false;
1186 		m_shiftSelItems = false;
1187 //		m_view->redrawMarker->hide();
1188 		m_view->updateContents();
1189 	}
1190 	if (m_doc->appMode != modeEdit)
1191 	{
1192 		if (!PrefsManager::instance().appPrefs.uiPrefs.stickyTools)
1193 			m_view->requestMode(modeNormal);
1194 		else
1195 		{
1196 			int appMode = m_doc->appMode;
1197 			m_view->requestMode(appMode);
1198 		}
1199 	}
1200 	if (GetItem(&currItem))
1201 	{
1202 		if (m_doc->m_Selection->count() > 1)
1203 		{
1204 			double x, y, w, h;
1205 			m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
1206 			m_canvas->m_viewMode.operItemMoving = false;
1207 			m_canvas->m_viewMode.operItemResizing = false;
1208 			m_view->updateContents(QRect(static_cast<int>(x - 5), static_cast<int>(y - 5), static_cast<int>(w + 10), static_cast<int>(h + 10)));
1209 		}
1210 		/*else
1211 			currItem->emitAllToGUI();*/
1212 	}
1213 	else
1214 		m_view->deselectItems(true);
1215 
1216 	xSnap = ySnap = 0;
1217 	m_canvas->setRenderModeUseBuffer(false);
1218 	m_doc->DragP = false;
1219 	m_doc->leaveDrag = false;
1220 	m_canvas->m_viewMode.operItemMoving = false;
1221 	m_canvas->m_viewMode.operItemResizing = false;
1222 	m_view->MidButt = false;
1223 	m_shiftSelItems = false;
1224 	if (m_view->groupTransactionStarted())
1225 	{
1226 		for (int i = 0; i < m_doc->m_Selection->count(); ++i)
1227 			m_doc->m_Selection->itemAt(i)->checkChanges(true);
1228 		m_view->endGroupTransaction();
1229 	}
1230 	for (int i = 0; i < m_doc->m_Selection->count(); ++i)
1231 		m_doc->m_Selection->itemAt(i)->checkChanges(true);
1232 
1233 	//Commit drag created items to undo manager.
1234 	if (m_doc->m_Selection->count() > 0)
1235 	{
1236 		if (m_doc->m_Selection->itemAt(0)!=nullptr)
1237 		{
1238 			m_doc->itemAddCommit(m_doc->m_Selection->itemAt(0));
1239 		}
1240 	}
1241 
1242 	//Make sure the Zoom spinbox and page selector don't have focus if we click on the canvas
1243 	m_view->m_ScMW->zoomSpinBox->clearFocus();
1244 	m_view->m_ScMW->pageSelector->clearFocus();
1245 	if (m_doc->m_Selection->count() > 0)
1246 	{
1247 		if (m_doc->m_Selection->itemAt(0) != nullptr) // is there the old clip stored for the undo action
1248 		{
1249 			currItem = m_doc->m_Selection->itemAt(0);
1250 			m_doc->nodeEdit.finishTransaction(currItem);
1251 		}
1252 	}
1253 	if (m_doc->drawAsPreview && !m_doc->editOnPreview)
1254 	{
1255 		if (m_doc->m_Selection->count() == 1)
1256 		{
1257 			currItem = m_doc->m_Selection->itemAt(0);
1258 			if (currItem->isAnnotation())
1259 			{
1260 				if (currItem->annotation().Type() == Annotation::Text)
1261 				{
1262 					if (currItem->annotation().IsOpen())
1263 					{
1264 						if (m_canvas->cursorOverFrameControl(m->globalPos(), QRectF(245, 20, 11, 11), currItem))
1265 						{
1266 							currItem->annotation().setOpen(false);
1267 							currItem->asTextFrame()->setTextAnnotationOpen(false);
1268 							currItem->update();
1269 							m_view->updateContents();
1270 						}
1271 					}
1272 				}
1273 				if (currItem->annotation().Type() == Annotation::Link)
1274 					handleLinkAnnotation(currItem);
1275 				else if (currItem->annotation().Type() == Annotation::Checkbox)
1276 					handleCheckBoxRelease(currItem);
1277 				else if (currItem->annotation().Type() == Annotation::RadioButton)
1278 					handleRadioButtonRelease(currItem);
1279 				else if (currItem->annotation().Type() == Annotation::Button)
1280 					handlePushButtonRelease(currItem);
1281 			}
1282 		}
1283 	}
1284 }
1285 
handleCheckBoxPress(PageItem * currItem)1286 void CanvasMode_Normal::handleCheckBoxPress(PageItem* currItem)
1287 {
1288 	m_view->m_AnnotChanged = true;
1289 	currItem->annotation().setOnState(true);
1290 	currItem->update();
1291 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1292 		handleJavaAction(currItem, Annotation::Java_PressButton);
1293 	m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
1294 }
1295 
handlePushButtonPress(PageItem * currItem)1296 void CanvasMode_Normal::handlePushButtonPress(PageItem* currItem)
1297 {
1298 	currItem->annotation().setOnState(true);
1299 	currItem->update();
1300 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1301 		handleJavaAction(currItem, Annotation::Java_PressButton);
1302 	m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
1303 }
1304 
handleRadioButtonPress(PageItem * currItem)1305 void CanvasMode_Normal::handleRadioButtonPress(PageItem* currItem)
1306 {
1307 	m_view->m_AnnotChanged = true;
1308 	if (currItem->isGroupChild())
1309 	{
1310 		PageItem *group = currItem->Parent->asGroupFrame();
1311 		for (int a = 0; a < group->groupItemList.count(); a++)
1312 		{
1313 			PageItem *gItem = group->groupItemList[a];
1314 			if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton))
1315 			{
1316 				gItem->update();
1317 			}
1318 		}
1319 	}
1320 	else
1321 	{
1322 		int op = currItem->OwnPage;
1323 		uint docItemCount = m_doc->Items->count();
1324 		for (uint i = 0; i < docItemCount; ++i)
1325 		{
1326 			PageItem *gItem = m_doc->Items->at(i);
1327 			if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton) && (gItem->OwnPage == op))
1328 			{
1329 				gItem->update();
1330 			}
1331 		}
1332 	}
1333 	currItem->annotation().setOnState(true);
1334 	currItem->update();
1335 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1336 		handleJavaAction(currItem, Annotation::Java_PressButton);
1337 	m_view->updateContents();
1338 }
1339 
handleCheckBoxRelease(PageItem * currItem)1340 void CanvasMode_Normal::handleCheckBoxRelease(PageItem* currItem)
1341 {
1342 	m_view->m_AnnotChanged = true;
1343 	currItem->annotation().setOnState(false);
1344 	currItem->annotation().setCheckState(!currItem->annotation().IsChecked());
1345 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1346 		handleJavaAction(currItem, Annotation::Java_ReleaseButton);
1347 	currItem->update();
1348 	m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
1349 }
1350 
handlePushButtonRelease(PageItem * currItem)1351 void CanvasMode_Normal::handlePushButtonRelease(PageItem* currItem)
1352 {
1353 	m_view->m_AnnotChanged = true;
1354 	currItem->annotation().setOnState(false);
1355 	currItem->update();
1356 	switch (currItem->annotation().ActionType())
1357 	{
1358 		case Annotation::Action_JavaScript:
1359 			handleJavaAction(currItem, Annotation::Java_ReleaseButton);
1360 			break;
1361 		case Annotation::Action_GoTo:
1362 		case Annotation::Action_URI:
1363 		case Annotation::Action_GoToR_FileAbs:
1364 		case Annotation::Action_GoToR_FileRel:
1365 			handleLinkAnnotation(currItem);
1366 			break;
1367 		case Annotation::Action_ResetForm:
1368 			m_doc->ResetFormFields();
1369 			break;
1370 		case Annotation::Action_ImportData:
1371 			m_doc->ImportData();
1372 			break;
1373 		case Annotation::Action_SubmitForm:
1374 			m_doc->SubmitForm();
1375 			break;
1376 		case Annotation::Action_Named:
1377 			handleNamedAction(currItem);
1378 		default:
1379 			break;
1380 	}
1381 }
1382 
handleRadioButtonRelease(PageItem * currItem)1383 void CanvasMode_Normal::handleRadioButtonRelease(PageItem* currItem)
1384 {
1385 	m_view->m_AnnotChanged = true;
1386 	if (currItem->isGroupChild())
1387 	{
1388 		PageItem *group = currItem->Parent->asGroupFrame();
1389 		for (int a = 0; a < group->groupItemList.count(); a++)
1390 		{
1391 			PageItem *gItem = group->groupItemList[a];
1392 			if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton))
1393 			{
1394 				gItem->annotation().setCheckState(false);
1395 				gItem->update();
1396 			}
1397 		}
1398 	}
1399 	else
1400 	{
1401 		int op = currItem->OwnPage;
1402 		uint docItemCount = m_doc->Items->count();
1403 		for (uint i = 0; i < docItemCount; ++i)
1404 		{
1405 			PageItem *gItem = m_doc->Items->at(i);
1406 			if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton) && (gItem->OwnPage == op))
1407 			{
1408 				gItem->annotation().setCheckState(false);
1409 				gItem->update();
1410 			}
1411 		}
1412 	}
1413 	currItem->annotation().setCheckState(true);
1414 	currItem->annotation().setOnState(false);
1415 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1416 		handleJavaAction(currItem, Annotation::Java_ReleaseButton);
1417 	currItem->update();
1418 	m_view->updateContents();
1419 }
1420 
handleJavaAction(PageItem * currItem,int event)1421 void CanvasMode_Normal::handleJavaAction(PageItem* currItem, int event)
1422 {
1423 	QString scriptCode = "";
1424 	switch (event)
1425 	{
1426 		case Annotation::Java_PressButton:
1427 			scriptCode = currItem->annotation().D_act();
1428 			break;
1429 		case Annotation::Java_ReleaseButton:
1430 			scriptCode = currItem->annotation().Action();
1431 			break;
1432 		case Annotation::Java_EnterWidget:
1433 			scriptCode = currItem->annotation().E_act();
1434 			break;
1435 		case Annotation::Java_LeaveWidget:
1436 			scriptCode = currItem->annotation().X_act();
1437 			break;
1438 		case Annotation::Java_FocusIn:
1439 			scriptCode = currItem->annotation().Fo_act();
1440 			break;
1441 		case Annotation::Java_FocusOut:
1442 			scriptCode = currItem->annotation().Bl_act();
1443 			break;
1444 		case Annotation::Java_SelectionChg:
1445 			scriptCode = currItem->annotation().K_act();
1446 			break;
1447 		case Annotation::Java_FieldFormat:
1448 			scriptCode = currItem->annotation().F_act();
1449 			break;
1450 		case Annotation::Java_FieldValidate:
1451 			scriptCode = currItem->annotation().V_act();
1452 			break;
1453 		case Annotation::Java_FieldCalculate:
1454 			scriptCode = currItem->annotation().C_act();
1455 			break;
1456 		default:
1457 			break;
1458 	}
1459 	if (!scriptCode.isEmpty())
1460 	{
1461 		// Execute the JavasScript Code
1462 //		qDebug() << "JavaScript:" << scriptCode;
1463 	}
1464 }
1465 
handleNamedAction(PageItem * currItem)1466 void CanvasMode_Normal::handleNamedAction(PageItem* currItem)
1467 {
1468 	m_view->deselectItems(true);
1469 	QString name = currItem->annotation().Action();
1470 	if (name == "FirstPage")
1471 		m_view->GotoPage(0);
1472 	else if (name == "PrevPage")
1473 		m_view->GotoPage(qMax(0, m_doc->currentPageNumber()-1));
1474 	else if (name == "NextPage")
1475 		m_view->GotoPage(qMin(m_doc->currentPageNumber()+1, m_doc->Pages->count()-1));
1476 	else if (name == "LastPage")
1477 		m_view->GotoPage(m_doc->Pages->count()-1);
1478 	else if (name == "Print")
1479 		m_ScMW->slotFilePrint();
1480 	else if (name == "Close")
1481 		m_ScMW->slotFileClose();
1482 	else if (name == "Quit")
1483 		m_ScMW->slotFileQuit();
1484 	else if (name == "FitHeight")
1485 		m_ScMW->slotZoom(-100);
1486 	else if (name == "FitWidth")
1487 		m_ScMW->slotZoom(-200);
1488 }
1489 
handleLinkAnnotation(PageItem * currItem)1490 void CanvasMode_Normal::handleLinkAnnotation(PageItem* currItem)
1491 {
1492 	if (currItem->annotation().ActionType() == Annotation::Action_GoTo)
1493 	{
1494 		m_view->deselectItems(true);
1495 		if (currItem->annotation().Ziel() < m_doc->Pages->count())
1496 			m_view->GotoPage(currItem->annotation().Ziel());
1497 		else
1498 		{
1499 			QString message = tr("Page %1 does not exist!").arg(currItem->annotation().Ziel() + 1);
1500 			ScMessageBox::warning(m_view, CommonStrings::trWarning, message);
1501 		}
1502 	}
1503 	else if (currItem->annotation().ActionType() == Annotation::Action_URI)
1504 	{
1505 		QString message = tr("Link Target is Web URL.\nURL: %1").arg(currItem->annotation().Extern());
1506 		ScMessageBox::information(m_view, tr("Information"), message);
1507 	}
1508 	else if ((currItem->annotation().ActionType() == Annotation::Action_GoToR_FileAbs) || (currItem->annotation().ActionType() == Annotation::Action_GoToR_FileRel))
1509 	{
1510 		QString message = tr("Link Target is external File.\nFile: %1\nPage: %2").arg(currItem->annotation().Extern()).arg(currItem->annotation().Ziel() + 1);
1511 		ScMessageBox::information(m_view, tr("Information"), message);
1512 	}
1513 }
1514 
handleFocusOut(PageItem * currItem)1515 void CanvasMode_Normal::handleFocusOut(PageItem* currItem)
1516 {
1517 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1518 		handleJavaAction(currItem, Annotation::Java_FocusOut);
1519 }
1520 
handleFocusIn(PageItem * currItem)1521 void CanvasMode_Normal::handleFocusIn(PageItem* currItem)
1522 {
1523 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1524 		handleJavaAction(currItem, Annotation::Java_FocusIn);
1525 }
1526 
handleMouseLeave(PageItem * currItem)1527 void CanvasMode_Normal::handleMouseLeave(PageItem* currItem)
1528 {
1529 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1530 		handleJavaAction(currItem, Annotation::Java_LeaveWidget);
1531 }
1532 
handleMouseEnter(PageItem * currItem)1533 void CanvasMode_Normal::handleMouseEnter(PageItem* currItem)
1534 {
1535 	if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
1536 		handleJavaAction(currItem, Annotation::Java_EnterWidget);
1537 }
1538 
keyPressEvent(QKeyEvent * e)1539 void CanvasMode_Normal::keyPressEvent(QKeyEvent *e)
1540 {
1541 	commonkeyPressEvent_NormalNodeEdit(e);
1542 }
1543 
keyReleaseEvent(QKeyEvent * e)1544 void CanvasMode_Normal::keyReleaseEvent(QKeyEvent *e)
1545 {
1546 	commonkeyReleaseEvent(e);
1547 }
1548 
1549 //CB-->Doc/Fix
SeleItem(QMouseEvent * m)1550 bool CanvasMode_Normal::SeleItem(QMouseEvent *m)
1551 {
1552 	PageItem *previousSelectedItem = nullptr;
1553 	if (m_doc->m_Selection->count() != 0)
1554 		previousSelectedItem = m_doc->m_Selection->itemAt(0);
1555 	m_canvas->m_viewMode.operItemSelecting = true;
1556 
1557 	QTransform p;
1558 	PageItem *currItem;
1559 	m_canvas->m_viewMode.m_MouseButtonPressed = true;
1560 	FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
1561 	m_mouseCurrentPoint  = mousePointDoc;
1562 //	double grabRadius = m_doc->guidesPrefs().grabRadius / m_canvas->scale();
1563 	int MxpS = static_cast<int>(mousePointDoc.x()); //m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
1564 	int MypS = static_cast<int>(mousePointDoc.y()); //m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
1565 //	QRectF mpo(m_mouseCurrentPoint.x()-grabRadius, m_mouseCurrentPoint.y()-grabRadius, grabRadius*2, grabRadius*2);
1566 	m_doc->nodeEdit.deselect();
1567 
1568 	 // Guides are on foreground and want to be processed first
1569 	if ((m_doc->guidesPrefs().guidesShown) && (m_doc->OnPage(MxpS, MypS) != -1))
1570 	{
1571 		// #9002: Resize points undraggable when object is aligned to a guide
1572 		// Allow item resize when guides are aligned to item while preserving
1573 		// ability to drag guide when guis is in foreground and inside selection
1574 		bool enableGuideGesture(false);
1575 		Canvas::FrameHandle frameResizeHandle(Canvas::OUTSIDE);
1576 		if (m_doc->m_Selection->count() > 0)
1577 		{
1578 			double gx(0.0), gy(0.0), gw(0.0), gh(0.0);
1579 			m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
1580 			frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(), mousePointDoc.y()), QRectF(gx, gy, gw, gh));
1581 		}
1582 		else
1583 		{
1584 			PageItem* hoveredItem = m_canvas->itemUnderCursor(m->globalPos(), nullptr, m->modifiers());
1585 			if (hoveredItem)
1586 				frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(), mousePointDoc.y()), hoveredItem);
1587 		}
1588 		enableGuideGesture |= (frameResizeHandle == Canvas::OUTSIDE);
1589 		enableGuideGesture |= ((m_doc->guidesPrefs().renderStackOrder.indexOf(3) > m_doc->guidesPrefs().renderStackOrder.indexOf(4)) && ((frameResizeHandle == Canvas::INSIDE) && (m->modifiers() != SELECT_BENEATH)));
1590 		enableGuideGesture |= ((m_doc->guidesPrefs().renderStackOrder.indexOf(3) < m_doc->guidesPrefs().renderStackOrder.indexOf(4)) && ((frameResizeHandle == Canvas::INSIDE) && (m->modifiers() == SELECT_BENEATH)));
1591 		if (enableGuideGesture)
1592 		{
1593 			if (!m_guideMoveGesture)
1594 			{
1595 				m_guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
1596 				connect(m_guideMoveGesture, SIGNAL(guideInfo(int,qreal)), m_ScMW->alignDistributePalette,SLOT(setGuide(int,qreal)));
1597 			}
1598 			if ((!m_doc->GuideLock) && m_guideMoveGesture->mouseHitsGuide(mousePointDoc))
1599 			{
1600 				m_view->startGesture(m_guideMoveGesture);
1601 				m_guideMoveGesture->mouseMoveEvent(m);
1602 				m_doc->m_Selection->connectItemToGUI();
1603 			//	qDebug()<<"Out Of SeleItem"<<__LINE__;
1604 				return true;
1605 			}
1606 			// If we call startGesture now, a new guide is created each time.
1607 			// ### could be a weakness to avoid calling it tho.
1608 	 		//	m_view->startGesture(guideMoveGesture);
1609 			m_guideMoveGesture->mouseSelectGuide(m);
1610 		}
1611 	}
1612 
1613 	bool pageChanged(false);
1614 	if (!m_doc->masterPageMode())
1615 	{
1616 		int pgNum = -1;
1617 		int docPageCount = m_doc->Pages->count() - 1;
1618 		MarginStruct pageBleeds;
1619 		bool drawBleed = false;
1620 		if (!m_doc->bleeds()->isNull() && m_doc->guidesPrefs().showBleed)
1621 			drawBleed = true;
1622 		for (int i = docPageCount; i > -1; i--)
1623 		{
1624 			if (drawBleed)
1625 				m_doc->getBleeds(i, pageBleeds);
1626 			int x = static_cast<int>(m_doc->Pages->at(i)->xOffset() - pageBleeds.left());
1627 			int y = static_cast<int>(m_doc->Pages->at(i)->yOffset() - pageBleeds.top());
1628 			int w = static_cast<int>(m_doc->Pages->at(i)->width() + pageBleeds.left() + pageBleeds.right());
1629 			int h = static_cast<int>(m_doc->Pages->at(i)->height() + pageBleeds.bottom() + pageBleeds.top());
1630 			if (QRect(x, y, w, h).contains(MxpS, MypS))
1631 			{
1632 				pgNum = i;
1633 				if (drawBleed)  // check again if its really on the correct page
1634 				{
1635 					for (int j = docPageCount; j > -1; j--)
1636 					{
1637 						int xn = static_cast<int>(m_doc->Pages->at(j)->xOffset());
1638 						int yn = static_cast<int>(m_doc->Pages->at(j)->yOffset());
1639 						int wn = static_cast<int>(m_doc->Pages->at(j)->width());
1640 						int hn = static_cast<int>(m_doc->Pages->at(j)->height());
1641 						if (QRect(xn, yn, wn, hn).contains(MxpS, MypS))
1642 						{
1643 							pgNum = j;
1644 							break;
1645 						}
1646 					}
1647 				}
1648 				break;
1649 			}
1650 		}
1651 		if (pgNum >= 0)
1652 		{
1653 			if (m_doc->currentPageNumber() != pgNum)
1654 			{
1655 				m_doc->setCurrentPage(m_doc->Pages->at(pgNum));
1656 				m_view->m_ScMW->slotSetCurrentPage(pgNum);
1657 				pageChanged = true;
1658 			}
1659 		}
1660 		m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
1661 	}
1662 
1663 	currItem = nullptr;
1664 	if ((m->modifiers() & SELECT_BENEATH) != 0)
1665 	{
1666 		for (int i = 0; i < m_doc->m_Selection->count(); ++i)
1667 		{
1668 			if (m_canvas->frameHitTest(QPointF(mousePointDoc.x(), mousePointDoc.y()), m_doc->m_Selection->itemAt(i)) >= 0)
1669 			{
1670 				currItem = m_doc->m_Selection->itemAt(i);
1671 				m_doc->m_Selection->removeItem(currItem);
1672 				break;
1673 			}
1674 		}
1675 	}
1676 	else if ( (m->modifiers() & SELECT_MULTIPLE) == Qt::NoModifier)
1677 	{
1678 		m_view->deselectItems(false);
1679 	}
1680 
1681 	currItem = m_canvas->itemUnderCursor(m->globalPos(), currItem, ((m->modifiers() & SELECT_IN_GROUP) || (m_doc->drawAsPreview && !m_doc->editOnPreview)));
1682 	if (currItem)
1683 	{
1684 		m_doc->m_Selection->delaySignalsOn();
1685 		if (m_doc->m_Selection->containsItem(currItem))
1686 		{
1687 			m_doc->m_Selection->removeItem(currItem);
1688 		}
1689 		else
1690 		{
1691 			//CB: If we have a selection but the user clicks with control on another item that is not below the current
1692 			//then clear and select the new item
1693 			if ((m->modifiers() == SELECT_BENEATH) && m_canvas->frameHitTest(QPointF(mousePointDoc.x(), mousePointDoc.y()), currItem) >= 0)
1694 				m_doc->m_Selection->clear();
1695 			//CB: #7186: This was prependItem, does not seem to need to be anymore with current select code
1696 			if (m_doc->drawAsPreview && !m_doc->editOnPreview)
1697 				m_doc->m_Selection->clear();
1698 			m_doc->m_Selection->addItem(currItem);
1699 			if (((m->modifiers() & SELECT_IN_GROUP) || (m_doc->drawAsPreview && !m_doc->editOnPreview)) && (!currItem->isGroup()))
1700 			{
1701 				currItem->isSingleSel = true;
1702 			}
1703 		}
1704 		if (pageChanged)
1705 		{
1706 			m_canvas->setForcedRedraw(true);
1707 			m_canvas->update();
1708 		}
1709 		else
1710 			m_canvas->update();
1711 
1712 		m_doc->m_Selection->delaySignalsOff();
1713 		if (m_doc->m_Selection->count() > 1)
1714 		{
1715 			m_doc->beginUpdate();
1716 			for (int aa = 0; aa < m_doc->m_Selection->count(); ++aa)
1717 			{
1718 				PageItem *bb = m_doc->m_Selection->itemAt(aa);
1719 				bb->update();
1720 			}
1721 			m_doc->endUpdate();
1722 			double x, y, w, h;
1723 			m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
1724 			m_view->getGroupRectScreen(&x, &y, &w, &h);
1725 		}
1726 		if (previousSelectedItem != nullptr)
1727 		{
1728 			if (currItem != previousSelectedItem)
1729 			{
1730 				handleFocusOut(previousSelectedItem);
1731 				handleFocusIn(currItem);
1732 			}
1733 		}
1734 		else
1735 			handleFocusIn(currItem);
1736 		return true;
1737 	}
1738 
1739 	// Guide selection for case where items are in front of guide
1740 	// Code below looks unnecessary after fixing #15989
1741 	/*if ((m_doc->guidesPrefs().guidesShown) && (m_doc->OnPage(MxpS, MypS) != -1))
1742 	{
1743 		bool enableGuideGesture(false);
1744 		Canvas::FrameHandle frameResizeHandle(Canvas::OUTSIDE);
1745 		if (m_doc->m_Selection->count() > 0)
1746 		{
1747 			double gx(0.0), gy(0.0), gw(0.0), gh(0.0);
1748 			m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
1749 			frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(), mousePointDoc.y()), QRectF(gx, gy, gw, gh));
1750 		}
1751 		else
1752 		{
1753 			PageItem* hoveredItem = m_canvas->itemUnderCursor(m->globalPos(), nullptr, m->modifiers());
1754 			if (hoveredItem)
1755 				frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(), mousePointDoc.y()), hoveredItem);
1756 		}
1757 		enableGuideGesture |= (frameResizeHandle == Canvas::OUTSIDE);
1758 		enableGuideGesture |= ((frameResizeHandle == Canvas::INSIDE) && (m->modifiers() == SELECT_BENEATH));
1759 		if (enableGuideGesture)
1760 		{
1761 			if (!m_guideMoveGesture)
1762 			{
1763 				m_guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
1764 				connect(m_guideMoveGesture, SIGNAL(guideInfo(int,qreal)), m_ScMW->alignDistributePalette, SLOT(setGuide(int,qreal)));
1765 			}
1766 			if ( (!m_doc->GuideLock) && (m_guideMoveGesture->mouseHitsGuide(mousePointDoc)) )
1767 			{
1768 				m_view->startGesture(m_guideMoveGesture);
1769 				m_guideMoveGesture->mouseMoveEvent(m);
1770 				m_doc->m_Selection->connectItemToGUI();
1771 				return true;
1772 			}
1773 			// If we call startGesture now, a new guide is created each time.
1774 			// ### could be a weakness to avoid calling it tho.
1775 			// m_view->startGesture(guideMoveGesture);
1776 			m_guideMoveGesture->mouseSelectGuide(m);
1777 		}
1778 	}*/
1779 
1780 	m_doc->m_Selection->connectItemToGUI();
1781 	if ( !(m->modifiers() & SELECT_MULTIPLE))
1782 	{
1783 		if (m_doc->m_Selection->isEmpty())
1784 		{
1785 			m_canvas->setForcedRedraw(true);
1786 			m_canvas->update();
1787 		}
1788 		else
1789 			m_view->deselectItems(true);
1790 	}
1791 	if (previousSelectedItem != nullptr)
1792 		handleFocusOut(previousSelectedItem);
1793 	return false;
1794 }
1795 
importToPage()1796 void CanvasMode_Normal::importToPage()
1797 {
1798 	QString fileName;
1799 	QString allFormats = tr("All Supported Formats")+" (";
1800 	QStringList formats;
1801 	int fmtCode = FORMATID_FIRSTUSER;
1802 	const FileFormat *fmt = LoadSavePlugin::getFormatById(fmtCode);
1803 	while (fmt != nullptr)
1804 	{
1805 		if (fmt->load)
1806 		{
1807 			formats.append(fmt->filter);
1808 			int an = fmt->filter.indexOf("(");
1809 			int en = fmt->filter.indexOf(")");
1810 			while (an != -1)
1811 			{
1812 				allFormats += fmt->filter.mid(an+1, en-an-1)+" ";
1813 				an = fmt->filter.indexOf("(", en);
1814 				en = fmt->filter.indexOf(")", an);
1815 			}
1816 		}
1817 		fmtCode++;
1818 		fmt = LoadSavePlugin::getFormatById(fmtCode);
1819 	}
1820 	allFormats += "*.sce *.SCE);;";
1821 	formats.append("Scribus Objects (*.sce *.SCE)");
1822 	formats.sort();
1823 	allFormats += formats.join(";;");
1824 	PrefsContext* dirs = PrefsManager::instance().prefsFile->getContext("dirs");
1825 	QString wdir = dirs->get("pastefile", ".");
1826 	FPoint pastePoint = m_mouseCurrentPoint;
1827 	CustomFDialog dia(m_view, wdir, tr("Open"), allFormats, fdExistingFiles | fdShowImportOptions | fdDisableOk);
1828 	if (dia.exec() == QDialog::Accepted)
1829 		fileName = dia.selectedFile();
1830 	else
1831 		return;
1832 	if (!fileName.isEmpty())
1833 	{
1834 		PrefsManager::instance().prefsFile->getContext("dirs")->set("pastefile", fileName.left(fileName.lastIndexOf("/")));
1835 		m_doc->setLoading(true);
1836 		QFileInfo fi(fileName);
1837 		bool savedAlignGrid = m_doc->SnapGrid;
1838 		bool savedAlignGuides = m_doc->SnapGuides;
1839 		bool savedAlignElement = m_doc->SnapElement;
1840 		m_doc->SnapElement = false;
1841 		m_doc->SnapGrid = false;
1842 		m_doc->SnapGuides = false;
1843 		if (fi.suffix().toLower() == "sce")
1844 			m_ScMW->slotElemRead(fileName, pastePoint.x(), pastePoint.y(), true, false, m_doc, m_doc->view());
1845 		else
1846 		{
1847 			m_doc->dontResize = true;
1848 			FileLoader *fileLoader = new FileLoader(fileName);
1849 			int testResult = fileLoader->testFile();
1850 			delete fileLoader;
1851 			if ((testResult != -1) && (testResult >= FORMATID_FIRSTUSER))
1852 			{
1853 				const FileFormat * fmt = LoadSavePlugin::getFormatById(testResult);
1854 				if (fmt)
1855 				{
1856 					fmt->loadFile(fileName, LoadSavePlugin::lfUseCurrentPage|LoadSavePlugin::lfInteractive|LoadSavePlugin::lfScripted);
1857 				}
1858 			}
1859 			m_doc->dontResize = false;
1860 		}
1861 		for (int a = 0; a < m_doc->m_Selection->count(); ++a)
1862 		{
1863 			PageItem *currItem = m_doc->m_Selection->itemAt(a);
1864 			currItem->m_layerID = m_doc->activeLayer();
1865 		}
1866 		if (m_doc->m_Selection->count() > 0)
1867 		{
1868 			PageItem *newItem = m_doc->m_Selection->itemAt(0);
1869 			if (dia.currentOptionIndex() == 1)
1870 			{
1871 				if ((newItem->width() > m_doc->currentPage()->width()) || (newItem->height() > m_doc->currentPage()->height()))
1872 					m_doc->rescaleGroup(newItem, qMin(qMin(m_doc->currentPage()->width() / newItem->width(), m_doc->currentPage()->height() / newItem->height()), 1.0));
1873 			}
1874 			else if (dia.currentOptionIndex() == 2)
1875 			{
1876 				m_doc->rescaleGroup(newItem, qMax(qMin(m_doc->currentPage()->width() / newItem->width(), m_doc->currentPage()->height() / newItem->height()), 1.0));
1877 			}
1878 			double x2, y2, w, h;
1879 			m_doc->m_Selection->getGroupRect(&x2, &y2, &w, &h);
1880 			m_doc->moveGroup(pastePoint.x() - x2, pastePoint.y() - y2);
1881 			m_ScMW->requestUpdate(reqColorsUpdate | reqSymbolsUpdate | reqLineStylesUpdate | reqTextStylesUpdate);
1882 		}
1883 		m_doc->SnapGrid = savedAlignGrid;
1884 		m_doc->SnapGuides = savedAlignGuides;
1885 		m_doc->SnapElement = savedAlignElement;
1886 		m_doc->setLoading(false);
1887 		m_doc->view()->DrawNew();
1888 		if (m_doc->m_Selection->count() > 0)
1889 		{
1890 			m_doc->m_Selection->connectItemToGUI();
1891 			m_ScMW->HaveNewSel();
1892 		}
1893 	}
1894 }
1895 
createContextMenu(PageItem * currItem,double mx,double my)1896 void CanvasMode_Normal::createContextMenu(PageItem* currItem, double mx, double my)
1897 {
1898 	ContextMenu* cmen=nullptr;
1899 //	qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
1900 	m_view->setObjectUndoMode();
1901 	m_mouseCurrentPoint.setXY(mx, my);
1902 	if (currItem!=nullptr)
1903 		cmen = new ContextMenu(*(m_doc->m_Selection), m_ScMW, m_doc);
1904 	else
1905 		cmen = new ContextMenu(m_ScMW, m_doc, mx, my);
1906 	if (cmen)
1907 		cmen->exec(QCursor::pos());
1908 	m_view->setGlobalUndoMode();
1909 	delete cmen;
1910 }
1911