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_create.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 <QWidgetAction>
30 
31 #include "appmodes.h"
32 #include "canvas.h"
33 #include "fpoint.h"
34 #include "fpointarray.h"
35 #include "hyphenator.h"
36 #include "pageitem_table.h"
37 #include "pageitem_textframe.h"
38 #include "prefscontext.h"
39 #include "prefsfile.h"
40 #include "prefsmanager.h"
41 #include "scraction.h"
42 #include "scribus.h"
43 #include "scribusXml.h"
44 #include "scribusdoc.h"
45 #include "scribusview.h"
46 #include "selection.h"
47 #include "text/frect.h"
48 #include "ui/basepointwidget.h"
49 #include "ui/hruler.h"
50 #include "ui/insertTable.h"
51 #include "ui/pageselector.h"
52 #include "ui/propertiespalette.h"
53 #include "ui/scrapbookpalette.h"
54 #include "ui/vruler.h"
55 #include "undomanager.h"
56 #include "units.h"
57 #include "util.h"
58 #include "util_math.h"
59 
CreateMode(ScribusView * view)60 CreateMode::CreateMode(ScribusView* view) : CanvasMode(view)
61 {
62 	canvasPressCoord.setXY(-1.0, -1.0);
63 	mouseGlobalCoord.setXY(-1.0, -1.0);
64 }
65 
drawControls(QPainter * p)66 void CreateMode::drawControls(QPainter* p)
67 {
68 	if (!inItemCreation) return;
69 
70 	QPointF topLeft(createObjectPos.x(), createObjectPos.y());
71 	QPointF btRight(canvasCurrCoord.x(), canvasCurrCoord.y());
72 	QColor  drawColor = qApp->palette().color(QPalette::Active, QPalette::Highlight);
73 
74 	if (createObjectMode != modeDrawLine)
75 	{
76 		QRectF bounds = QRectF(topLeft, btRight).normalized();
77 		//Lock Height to Width for Control Modifier for region drawing
78 		if (modifiers==Qt::ControlModifier)
79 		{
80 			bounds.setHeight(bounds.width());
81 			if (btRight.y()<topLeft.y())
82 				bounds.moveBottom(topLeft.y());
83 			if (btRight.x()<topLeft.x() && btRight.y()>topLeft.y())
84 				bounds.moveTop(topLeft.y());
85 		}
86 		QRect localRect = m_canvas->canvasToLocal(bounds);
87 		if (localRect.width() <= 0 || localRect.height() <= 0)
88 			return;
89 		p->setRenderHint(QPainter::Antialiasing);
90 
91 		p->save();
92 		p->setPen(QPen(drawColor, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
93 		drawColor.setAlpha(64);
94 		p->setBrush(drawColor);
95 		p->drawRect(localRect);
96 
97 		drawColor.setAlpha(255);
98 		p->setBrush(Qt::NoBrush);
99 		p->setPen(QPen(drawColor, 1, Qt::DashLine, Qt::FlatCap, Qt::MiterJoin));
100 
101 		int frameType = 0, itemType = 0;
102 		getFrameItemTypes(itemType, frameType);
103 		if (frameType == PageItem::Ellipse)
104 		{
105 			p->drawEllipse(localRect);
106 		}
107 		else if (createObjectMode == modeDrawArc)
108 		{
109 			QPainterPath path;
110 			path.moveTo(localRect.width() / 2.0, localRect.height() / 2.0);
111 			path.arcTo(0.0, 0.0, localRect.width(), localRect.height(), m_doc->itemToolPrefs().arcStartAngle, m_doc->itemToolPrefs().arcSweepAngle);
112 			path.closeSubpath();
113 			p->translate(localRect.left(), localRect.top());
114 			p->drawPath(path);
115 		}
116 		else if (createObjectMode == modeDrawRegularPolygon)
117 		{
118 			QPainterPath path = regularPolygonPath(localRect.width(), localRect.height(), m_doc->itemToolPrefs().polyCorners, m_doc->itemToolPrefs().polyUseFactor, m_doc->itemToolPrefs().polyFactor, m_doc->itemToolPrefs().polyRotation, m_doc->itemToolPrefs().polyCurvature, m_doc->itemToolPrefs().polyInnerRot, m_doc->itemToolPrefs().polyOuterCurvature);
119 			p->translate(localRect.left(), localRect.top());
120 			p->drawPath(path);
121 		}
122 		else if (createObjectMode == modeDrawSpiral)
123 		{
124 			QPainterPath path = spiralPath(localRect.width(), localRect.height(), m_doc->itemToolPrefs().spiralStartAngle, m_doc->itemToolPrefs().spiralEndAngle, m_doc->itemToolPrefs().spiralFactor);
125 			p->translate(localRect.left(), localRect.top());
126 			p->drawPath(path);
127 		}
128 		else if ((createObjectMode == modeDrawShapes) && (createObjectSubMode > 1))
129 		{
130 			FPointArray poly;
131 			int valCount = m_doc->ValCount;
132 			double *vals = m_doc->ShapeValues;
133 			for (int a = 0; a < valCount-3; a += 4)
134 			{
135 				if (vals[a] < 0)
136 				{
137 					poly.setMarker();
138 					continue;
139 				}
140 				double x1 = localRect.width()  * vals[a] / 100.0;
141 				double y1 = localRect.height() * vals[a+1] / 100.0;
142 				double x2 = localRect.width()  * vals[a+2] / 100.0;
143 				double y2 = localRect.height() * vals[a+3] / 100.0;
144 				poly.addPoint(x1, y1);
145 				poly.addPoint(x2, y2);
146 			}
147 			QPainterPath path = poly.toQPainterPath(false);
148 			p->translate(localRect.left(), localRect.top());
149 			p->drawPath(path);
150 		}
151 		p->restore();
152 	}
153 	else
154 	{
155 		QPoint p1 = m_canvas->canvasToLocal(topLeft);
156 		QPoint p2 = m_canvas->canvasToLocal(btRight);
157 
158 		p->save();
159 		p->setPen(QPen(drawColor, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
160 		p->setBrush(drawColor);
161 		p->drawLine(p1, p2);
162 		p->restore();
163 	}
164 }
165 
GetItem(PageItem ** pi)166 inline bool CreateMode::GetItem(PageItem** pi)
167 {
168 	*pi = m_doc->m_Selection->itemAt(0);
169 	return (*pi) != nullptr;
170 }
171 
172 // the following code was moved from scribusview.cpp:
173 
174 
enterEvent(QEvent * e)175 void CreateMode::enterEvent(QEvent *e)
176 {
177 	if (!m_MouseButtonPressed)
178 	{
179 		setModeCursor();
180 	}
181 }
182 
183 
leaveEvent(QEvent * e)184 void CreateMode::leaveEvent(QEvent *e)
185 {
186 }
187 
188 
activate(bool fromGesture)189 void CreateMode::activate(bool fromGesture)
190 {
191 //	qDebug() << "CreateMode::activate" << fromGesture;
192 	CanvasMode::activate(fromGesture);
193 
194 	PageItem* currItem;
195 	if (!fromGesture || !GetItem(&currItem) || !m_createTransaction)
196 	{
197 		if (m_createTransaction)
198 		{
199 //			qDebug() << "canceling left over create Transaction";
200 			m_createTransaction.cancel();
201 			m_createTransaction.reset();
202 		}
203 		canvasPressCoord.setXY(-1.0, -1.0);
204 		mouseGlobalCoord.setXY(-1.0, -1.0);
205 		inItemCreation = false;
206 	}
207 	setModeCursor();
208 }
209 
deactivate(bool forGesture)210 void CreateMode::deactivate(bool forGesture)
211 {
212 //	qDebug() << "CreateMode::deactivate" << forGesture;
213 	if (!forGesture)
214 	{
215 		if (m_createTransaction)
216 		{
217 //			qDebug() << "CreateMode::deactivate: canceling left over create Transaction";
218 			m_createTransaction.cancel();
219 			m_createTransaction.reset();
220 		}
221 	}
222 
223 	CanvasMode::deactivate(forGesture);
224 }
225 
keyPressEvent(QKeyEvent * e)226 void CreateMode::keyPressEvent(QKeyEvent *e)
227 {
228 	commonkeyPressEvent_Default(e);
229 }
230 
keyReleaseEvent(QKeyEvent * e)231 void CreateMode::keyReleaseEvent(QKeyEvent *e)
232 {
233 	commonkeyReleaseEvent(e);
234 }
235 
mouseDoubleClickEvent(QMouseEvent * m)236 void CreateMode::mouseDoubleClickEvent(QMouseEvent *m)
237 {
238 	m->accept();
239 	m_MouseButtonPressed = false;
240 	m_canvas->resetRenderMode();
241 }
242 
mouseMoveEvent(QMouseEvent * m)243 void CreateMode::mouseMoveEvent(QMouseEvent *m)
244 {
245 	const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
246 	modifiers = m->modifiers();
247 
248 	double newX, newY;
249 	PageItem *currItem;
250 	QPainter p;
251 //	QRect tx;
252 	m->accept();
253 //	qDebug() << "legacy mode move:" << m->x() << m->y() << m_canvas->globalToCanvas(m->globalPos()).x() << m_canvas->globalToCanvas(m->globalPos()).y();
254 //	emit MousePos(m->x()/m_canvas->scale(),// + m_doc->minCanvasCoordinate.x(),
255 //				  m->y()/m_canvas->scale()); // + m_doc->minCanvasCoordinate.y());
256 
257 	if (commonMouseMove(m))
258 		return;
259 	if (GetItem(&currItem))
260 	{
261 //		newX = mousePointDoc.x(); //m_view->translateToDoc(m->x(), m->y()).x());
262 //		newY = mousePointDoc.y(); //m_view->translateToDoc(m->x(), m->y()).y());
263 		return;
264 	}
265 	if ((!m_MouseButtonPressed) || !(m->buttons() & Qt::LeftButton))
266 	{
267 		m_canvas->displayCorrectedXYHUD(m->globalPos(), mousePointDoc.x(), mousePointDoc.y());
268 		return;
269 	}
270 
271 	newX = mousePointDoc.x();
272 	newY = mousePointDoc.y();
273 	if (createObjectMode == modeDrawLine)
274 	{
275 		if (m_doc->SnapGrid)
276 		{
277 			newX = qRound(newX / m_doc->guidesPrefs().minorGridSpacing) * m_doc->guidesPrefs().minorGridSpacing;
278 			newY = qRound(newY / m_doc->guidesPrefs().minorGridSpacing) * m_doc->guidesPrefs().minorGridSpacing;
279 		}
280 		if (m->modifiers() & Qt::ControlModifier)
281 		{
282 			QRectF bounds(QPointF(createObjectPos.x(), createObjectPos.y()), QPointF(newX, newY));
283 			double newRot = xy2Deg(bounds.width(), bounds.height());
284 			if (newRot < 0.0)
285 				newRot += 360;
286 			newRot = constrainAngle(newRot, m_doc->opToolPrefs().constrain);
287 			double len = qMax(0.01, distance(bounds.width(), bounds.height()));
288 			bounds.setSize(len * QSizeF(cosd(newRot), sind(newRot)));
289 			newX = bounds.right();
290 			newY = bounds.bottom();
291 		}
292 	}
293 	//CB: #8099: Readd snapping for drag creation of lines by commenting this else..
294 	//else
295 	//{
296 		FPoint np2 = m_doc->ApplyGridF(FPoint(newX, newY));
297 		double nx = np2.x();
298 		double ny = np2.y();
299 		m_doc->ApplyGuides(&nx, &ny);
300 		m_doc->ApplyGuides(&nx, &ny,true);
301 		if (nx != np2.x())
302 			xSnap = nx;
303 		if (ny != np2.y())
304 			ySnap = ny;
305 		// #8959 : suppress qRound here as this prevent drawing line with angle constrain
306 		// precisely and does not allow to stick precisely to grid or guides
307 		newX = /*qRound(*/nx/*)*/;
308 		newY = /*qRound(*/ny/*)*/;
309 	//}
310 
311 	canvasCurrCoord.setXY(newX, newY);
312 	m_view->HaveSelRect = true;
313 
314 	double wSize = canvasCurrCoord.x() - createObjectPos.x();
315 	double hSize = canvasCurrCoord.y() - createObjectPos.y();
316 	QRectF createObjectRect(createObjectPos.x(), createObjectPos.y(), wSize, hSize);
317 	createObjectRect = createObjectRect.normalized();
318 	if (createObjectMode != modeDrawLine)
319 	{
320 		if (modifiers == Qt::ControlModifier)
321 			hSize = wSize;
322 		m_canvas->displaySizeHUD(m->globalPos(), wSize, hSize, false);
323 	}
324 	else
325 	{
326 		double angle = -xy2Deg(wSize, hSize);
327 		if (angle < 0.0)
328 			angle = angle + 360;
329 		double trueLength = sqrt(pow(createObjectRect.width(), 2) + pow(createObjectRect.height(), 2));
330 		m_canvas->displaySizeHUD(m->globalPos(), trueLength, angle, true);
331 	}
332 
333 	// Necessary for drawControls to be called
334 	m_canvas->repaint();
335 }
336 
mousePressEvent(QMouseEvent * m)337 void CreateMode::mousePressEvent(QMouseEvent *m)
338 {
339 	const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
340 	modifiers = m->modifiers();
341 
342 	double Rxp = 0, Ryp = 0;
343 	m_MouseButtonPressed = true;
344 	m_view->HaveSelRect = false;
345 	m_doc->DragP = false;
346 	m_doc->leaveDrag = false;
347 	inItemCreation = false;
348 //	oldClip = 0;
349 	m->accept();
350 	m_view->registerMousePress(m->globalPos());
351 //	QRect mpo(m->x()-m_doc->guidesPrefs().grabRadius, m->y()-m_doc->guidesPrefs().grabRadius, m_doc->guidesPrefs().grabRadius*2, m_doc->guidesPrefs().grabRadius*2);
352 //	mpo.moveBy(qRound(m_doc->minCanvasCoordinate.x() * m_canvas->scale()), qRound(m_doc->minCanvasCoordinate.y() * m_canvas->scale()));
353 	canvasPressCoord = mousePointDoc;
354 	createObjectMode = m_doc->appMode;
355 	createObjectSubMode = m_doc->SubMode;
356 	createObjectPos  = m_doc->ApplyGridF(canvasPressCoord);
357 
358 	Rxp  = m_doc->ApplyGridF(canvasPressCoord).x();
359 	canvasPressCoord.setX(qRound(Rxp));
360 	Ryp  = m_doc->ApplyGridF(canvasPressCoord).y();
361 	canvasPressCoord.setXY(qRound(Rxp), qRound(Ryp));
362 
363 	canvasCurrCoord = canvasPressCoord;
364 	m_doc->ApplyGuides(&Rxp, &Ryp);
365 	m_doc->ApplyGuides(&Rxp, &Ryp,true);
366 	createObjectPos.setXY(Rxp, Ryp);
367 
368 	if (m->button() == Qt::MidButton)
369 	{
370 		m_view->MidButt = true;
371 		if (m->modifiers() & Qt::ControlModifier)
372 			m_view->DrawNew();
373 		return;
374 	}
375 
376 	if (m->button() == Qt::RightButton)
377 	{
378 		m_view->requestMode(modeNormal);
379 		return;
380 	}
381 	if (m->button() != Qt::LeftButton)
382 		return;
383 	selectPage(m);
384 
385 	switch (m_doc->appMode)
386 	{
387 		case modeDrawTable2:
388 			m_view->deselectItems(false);
389 			break;
390 	}
391 
392 	inItemCreation = true;
393 }
394 
mouseReleaseEvent(QMouseEvent * m)395 void CreateMode::mouseReleaseEvent(QMouseEvent *m)
396 {
397 	modifiers = m->modifiers();
398 
399 	PageItem *currItem;
400 	m_MouseButtonPressed = false;
401 	m_canvas->resetRenderMode();
402 	m->accept();
403 //	m_view->stopDragTimer();
404 
405 	m_createTransaction = Um::instance()->beginTransaction("creating");
406 	currItem = doCreateNewObject();
407 	if (m_createTransaction && currItem)
408 	{
409 		m_view->resetMousePressed();
410 		currItem->checkChanges(true);
411 		QString targetName = Um::ScratchSpace;
412 		if (currItem->OwnPage > -1)
413 			targetName = m_doc->Pages->at(currItem->OwnPage)->getUName();
414 		m_createTransaction.commit(targetName, currItem->getUPixmap(),
415 									Um::Create + " " + currItem->getUName(),  "", Um::ICreate);
416 		m_createTransaction.reset();
417 		m_doc->changed();
418 		/*currItem->update();
419 		currItem->emitAllToGUI();*/
420 	}
421 	else if (m_createTransaction)
422 	{
423 		m_createTransaction.cancel();
424 		m_createTransaction.reset();
425 	}
426 	if (!PrefsManager::instance().appPrefs.uiPrefs.stickyTools)
427 	{
428 		m_view->requestMode(modeNormal);
429 	}
430 	else
431 	{
432 		m_view->updateCanvas();
433 		int appMode = m_doc->appMode;
434 		m_view->requestMode(appMode);
435 	}
436 	inItemCreation = false;
437 }
438 
selectPage(QMouseEvent * m)439 void CreateMode::selectPage(QMouseEvent *m)
440 {
441 	m_MouseButtonPressed = true;
442 	FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
443 	canvasPressCoord     = mousePointDoc;
444 //	QRect mpo(m->x()-m_doc->guidesPrefs().grabRadius, m->y()-m_doc->guidesPrefs().grabRadius, m_doc->guidesPrefs().grabRadius*2, m_doc->guidesPrefs().grabRadius*2);
445 //	mpo.moveBy(qRound(Doc->minCanvasCoordinate.x() * m_canvas->scale()), qRound(m_doc->minCanvasCoordinate.y() * m_canvas->scale()));
446 	m_doc->nodeEdit.deselect();
447 	m_view->deselectItems(false);
448 	if (!m_doc->masterPageMode())
449 	{
450 		int i = m_doc->OnPage(canvasPressCoord.x(), canvasPressCoord.y());
451 		if (i!=-1)
452 		{
453 			uint docCurrPageNo=m_doc->currentPageNumber();
454 			uint j=static_cast<uint>(i);
455 			if (docCurrPageNo != j)
456 			{
457 				m_doc->setCurrentPage(m_doc->Pages->at(j));
458 				m_view->m_ScMW->slotSetCurrentPage(j);
459 				m_view->DrawNew();
460 			}
461 		}
462 /*		uint docPagesCount=m_doc->Pages->count();
463 		uint docCurrPageNo=m_doc->currentPageNumber();
464 		for (uint i = 0; i < docPagesCount; ++i)
465 		{
466 			int x = static_cast<int>(m_doc->Pages->at(i)->xOffset() * m_canvas->scale());
467 			int y = static_cast<int>(m_doc->Pages->at(i)->yOffset() * m_canvas->scale());
468 			int w = static_cast<int>(m_doc->Pages->at(i)->width() * m_canvas->scale());
469 			int h = static_cast<int>(m_doc->Pages->at(i)->height() * m_canvas->scale());
470 			if (QRect(x, y, w, h).intersects(mpo))
471 			{
472 				if (docCurrPageNo != i)
473 				{
474 					m_doc->setCurrentPage(m_doc->Pages->at(i));
475 					setMenTxt(i);
476 					DrawNew();
477 				}
478 				break;
479 			}
480 		} */
481 
482 		//FIXME m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
483 	}
484 }
485 
SetupDrawNoResize(int nr)486 void CreateMode::SetupDrawNoResize(int nr)
487 {
488 	PageItem* currItem = m_doc->Items->at(nr);
489 	//	currItem->setFont(Doc->toolSettings.textFont);
490 	//	currItem->setFontSize(Doc->toolSettings.textSize);
491 	m_doc->m_Selection->delaySignalsOn();
492 	m_doc->m_Selection->clear();
493 	m_doc->m_Selection->addItem(currItem);
494 	m_doc->m_Selection->delaySignalsOff();
495 //	emit DocChanged();
496 	currItem->Sizing =  false /*currItem->asLine() ? false : true*/;
497 	//#6456 m_view->resetMoveTimer();
498 }
499 
getFrameItemTypes(int & itemType,int & frameType)500 void CreateMode::getFrameItemTypes(int& itemType, int& frameType)
501 {
502 	itemType  = (int) PageItem::Polygon;
503 	frameType = (int) PageItem::Rectangle;
504 	switch (createObjectMode)
505 	{
506 	case modeDrawShapes:
507 		switch (createObjectSubMode)
508 		{
509 		case 0:
510 			itemType  = (int) PageItem::Polygon;
511 			frameType = (int) PageItem::Rectangle;
512 			break;
513 		case 1:
514 			itemType  = (int) PageItem::Polygon;
515 			frameType = (int) PageItem::Ellipse;
516 			break;
517 		default:
518 			itemType  = (int) PageItem::Polygon;
519 			frameType = (int) PageItem::Unspecified;
520 			break;
521 		}
522 		break;
523 	case modeDrawLine:
524 		itemType  = (int) PageItem::Line;
525 		frameType = (int) PageItem::Unspecified;
526 		break;
527 	case modeDrawLatex:
528 		itemType  = (int) PageItem::LatexFrame;
529 		frameType = (int) PageItem::Unspecified;
530 		break;
531 	case modeDrawImage:
532 		itemType  = (int) PageItem::ImageFrame;
533 		frameType = (int) PageItem::Unspecified;
534 		break;
535 	case modeDrawText:
536 		itemType  = (int) PageItem::TextFrame;
537 		frameType = (int) PageItem::Unspecified;
538 		break;
539 	case modeDrawRegularPolygon:
540 		itemType  = (int) PageItem::RegularPolygon;
541 		frameType = (int) PageItem::Unspecified;
542 		break;
543 	case modeDrawArc:
544 		itemType  = (int) PageItem::Arc;
545 		frameType = (int) PageItem::Unspecified;
546 		break;
547 	case modeDrawSpiral:
548 		itemType  = (int) PageItem::Spiral;
549 		frameType = (int) PageItem::Unspecified;
550 		break;
551 	case modeInsertPDFButton:
552 	case modeInsertPDFRadioButton:
553 	case modeInsertPDFTextfield:
554 	case modeInsertPDFCheckbox:
555 	case modeInsertPDFCombobox:
556 	case modeInsertPDFListbox:
557 	case modeInsertPDFTextAnnotation:
558 	case modeInsertPDFLinkAnnotation:
559 		itemType  = (int) PageItem::TextFrame;
560 		frameType = (int) PageItem::Unspecified;
561 		break;
562 	case modeDrawTable2:
563 		itemType  = (int) PageItem::Table;
564 		frameType = (int) PageItem::Unspecified;
565 		break;
566 	case modeInsertPDF3DAnnotation:
567 		itemType  = (int) PageItem::OSGFrame;
568 		frameType = (int) PageItem::Unspecified;
569 		break;
570 	}
571 }
572 
doCreateNewObject()573 PageItem* CreateMode::doCreateNewObject()
574 {
575 	int z = -1;
576 	double rot, len;
577 
578 	double wSize = canvasCurrCoord.x() - createObjectPos.x();
579 	double hSize = canvasCurrCoord.y() - createObjectPos.y();
580 	bool   skipOneClick = (modifiers == Qt::ShiftModifier);
581 	if ((createObjectMode == modeDrawLine) || (createObjectMode == modeDrawTable2) ||
582 		(createObjectMode == modeInsertPDFButton) || (createObjectMode == modeInsertPDFTextfield) ||
583 		(createObjectMode == modeInsertPDFTextfield) || (createObjectMode == modeInsertPDFCheckbox) ||
584 		(createObjectMode == modeInsertPDFCombobox) || (createObjectMode == modeInsertPDFListbox) ||
585 		(createObjectMode == modeInsertPDFTextAnnotation) || (createObjectMode == modeInsertPDFLinkAnnotation) ||
586 		(createObjectMode == modeInsertPDF3DAnnotation) || (createObjectMode == modeInsertPDFRadioButton))
587 	{
588 		skipOneClick = false;
589 	}
590 	if (!skipOneClick)
591 	{
592 		if ((!m_view->moveTimerElapsed()) || ((fabs(wSize) < 2.0) && (fabs(hSize) < 2.0)))
593 		{
594 			if (!doOneClick(createObjectPos, canvasCurrCoord))
595 			{
596 				return nullptr;
597 			}
598 		}
599 	}
600 
601 	wSize = canvasCurrCoord.x() - createObjectPos.x();
602 	hSize = canvasCurrCoord.y() - createObjectPos.y();
603 	//Lock Height to Width for Control Modifier for final item creation
604 	if (createObjectMode != modeDrawLine)
605 	{
606 		if (modifiers == Qt::ControlModifier)
607 			hSize = wSize;
608 	}
609 
610 	PageItem *newObject = nullptr, *currItem = nullptr;
611 	// FIXME for modeDrawLine
612 	QRectF createObjectRect(createObjectPos.x(), createObjectPos.y(), wSize, hSize);
613 	if (createObjectMode != modeDrawLine)
614 	{
615 		createObjectRect = createObjectRect.normalized();
616 		if (modifiers==Qt::ControlModifier)
617 		{
618 			//bottom right and upper left are ok
619 			//upper right
620 			if (canvasCurrCoord.y() < createObjectPos.y() && createObjectPos.x()<canvasCurrCoord.x())
621 				createObjectRect.translate(0.0, -createObjectRect.height());
622 			//bottom left
623 			if (canvasCurrCoord.x()<createObjectPos.x() && canvasCurrCoord.y()>createObjectPos.y())
624 				createObjectRect.translate(0.0, createObjectRect.height());
625 		}
626 	}
627 	double Rxp  = createObjectRect.x();
628 	double Ryp  = createObjectRect.y();
629 	double Rxpd = createObjectRect.width();
630 	double Rypd = createObjectRect.height();
631 
632 	switch (createObjectMode)
633 	{
634 	case modeDrawShapes:
635 		switch (createObjectSubMode)
636 		{
637 			case 0:
638 				if (modifiers == Qt::ShiftModifier)
639 					z = m_doc->itemAddArea(PageItem::Polygon, PageItem::Rectangle, Rxp, Ryp, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().shapeLineColor);
640 				else
641 					z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().shapeLineColor);
642 				m_doc->Items->at(z)->FrameType = 0;
643 				break;
644 			case 1:
645 				if (modifiers == Qt::ShiftModifier)
646 					z = m_doc->itemAddArea(PageItem::Polygon, PageItem::Ellipse, Rxp, Ryp, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().shapeLineColor);
647 				else
648 					z = m_doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().shapeLineColor);
649 				m_doc->Items->at(z)->FrameType = 1;
650 				break;
651 			default:
652 				if (modifiers == Qt::ShiftModifier)
653 					z = m_doc->itemAddArea(PageItem::Polygon, PageItem::Unspecified, Rxp, Ryp, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().shapeLineColor);
654 				else
655 					z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().shapeLineColor);
656 				m_doc->Items->at(z)->SetFrameShape(m_doc->ValCount, m_doc->ShapeValues);
657 				m_doc->adjustItemSize(m_doc->Items->at(z));
658 				m_doc->setRedrawBounding(m_doc->Items->at(z));
659 				m_doc->Items->at(z)->FrameType = createObjectSubMode + 2;
660 				break;
661 		}
662 		break;
663 	case modeDrawLine:
664 		Rxp = createObjectPos.x();
665 		Ryp = createObjectPos.y();
666 		m_doc->ApplyGuides(&Rxp, &Ryp);
667 		m_doc->ApplyGuides(&Rxp, &Ryp,true);
668 		rot = xy2Deg(Rxpd, Rypd);
669 		if (rot < 0.0)
670 			rot += 360;
671 		len = qMax(0.01, distance(Rxpd, Rypd));
672 		z = m_doc->itemAdd(PageItem::Line, PageItem::Unspecified, Rxp, Ryp, len, 1, m_doc->itemToolPrefs().lineWidth, CommonStrings::None, m_doc->itemToolPrefs().lineColor);
673 		m_doc->Items->at(z)->setRotation(rot);
674 		m_doc->Items->at(z)->setRedrawBounding();
675 		break;
676 	case modeDrawLatex:
677 		if (modifiers == Qt::ShiftModifier)
678 			z = m_doc->itemAddArea(PageItem::LatexFrame, PageItem::Unspecified, Rxp, Ryp, 1, m_doc->itemToolPrefs().imageFillColor, m_doc->itemToolPrefs().imageStrokeColor);
679 		else
680 			z = m_doc->itemAdd(PageItem::LatexFrame, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().imageFillColor, m_doc->itemToolPrefs().imageStrokeColor);
681 		break;
682 	case modeDrawImage:
683 		if (modifiers == Qt::ShiftModifier)
684 			z = m_doc->itemAddArea(PageItem::ImageFrame, PageItem::Unspecified, Rxp, Ryp, 1, m_doc->itemToolPrefs().imageFillColor, m_doc->itemToolPrefs().imageStrokeColor);
685 		else
686 			z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().imageFillColor, m_doc->itemToolPrefs().imageStrokeColor);
687 		break;
688 	case modeDrawText:
689 		if (modifiers == Qt::ShiftModifier)
690 			z = m_doc->itemAddArea(PageItem::TextFrame, PageItem::Unspecified, Rxp, Ryp, m_doc->itemToolPrefs().shapeLineWidth, CommonStrings::None, m_doc->itemToolPrefs().textFont);
691 		else
692 			z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, CommonStrings::None, m_doc->itemToolPrefs().textFont);
693 		break;
694 	case modeDrawRegularPolygon:
695 		if (modifiers == Qt::ShiftModifier)
696 			z = m_doc->itemAddArea(PageItem::RegularPolygon, PageItem::Unspecified, Rxp, Ryp, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().lineColor);
697 		else
698 			z = m_doc->itemAdd(PageItem::RegularPolygon, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().lineColor);
699 		break;
700 	case modeDrawArc:
701 		if (modifiers == Qt::ShiftModifier)
702 			z = m_doc->itemAddArea(PageItem::Arc, PageItem::Unspecified, Rxp, Ryp, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().lineColor);
703 		else
704 			z = m_doc->itemAdd(PageItem::Arc, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().shapeFillColor, m_doc->itemToolPrefs().lineColor);
705 		m_doc->setRedrawBounding(m_doc->Items->at(z));
706 		break;
707 	case modeDrawSpiral:
708 		if (modifiers == Qt::ShiftModifier)
709 			z = m_doc->itemAddArea(PageItem::Spiral, PageItem::Unspecified, Rxp, Ryp, m_doc->itemToolPrefs().shapeLineWidth, CommonStrings::None, m_doc->itemToolPrefs().lineColor);
710 		else
711 			z = m_doc->itemAdd(PageItem::Spiral, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, CommonStrings::None, m_doc->itemToolPrefs().lineColor);
712 		m_doc->adjustItemSize(m_doc->Items->at(z));
713 		m_doc->setRedrawBounding(m_doc->Items->at(z));
714 		break;
715 	case modeInsertPDFButton:
716 	case modeInsertPDFRadioButton:
717 	case modeInsertPDFTextfield:
718 	case modeInsertPDFCheckbox:
719 	case modeInsertPDFCombobox:
720 	case modeInsertPDFListbox:
721 	case modeInsertPDFTextAnnotation:
722 	case modeInsertPDFLinkAnnotation:
723 		z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, CommonStrings::None, m_doc->itemToolPrefs().textColor);
724 		currItem = m_doc->Items->at(z);
725 		currItem->setIsAnnotation(true);
726 		currItem->AutoName = false;
727 		switch (m_doc->appMode)
728 		{
729 		case modeInsertPDFButton:
730 			currItem->annotation().setType(Annotation::Button);
731 			currItem->annotation().setFlag(Annotation::Flag_PushButton);
732 			currItem->setItemName( CommonStrings::itemName_PushButton + QString("%1").arg(m_doc->TotalItems));
733 			break;
734 		case modeInsertPDFRadioButton:
735 			currItem->annotation().setType(Annotation::RadioButton);
736 			currItem->annotation().setFlag(Annotation::Flag_Radio | Annotation::Flag_NoToggleToOff);
737 			currItem->setItemName( CommonStrings::itemName_RadioButton + QString("%1").arg(m_doc->TotalItems));
738 			break;
739 		case modeInsertPDFTextfield:
740 			currItem->annotation().setType(Annotation::Textfield);
741 			currItem->setItemName( CommonStrings::itemName_TextField + QString("%1").arg(m_doc->TotalItems));
742 			break;
743 		case modeInsertPDFCheckbox:
744 			currItem->annotation().setType(Annotation::Checkbox);
745 			currItem->setItemName( CommonStrings::itemName_CheckBox + QString("%1").arg(m_doc->TotalItems));
746 			break;
747 		case modeInsertPDFCombobox:
748 			currItem->annotation().setType(Annotation::Combobox);
749 			currItem->annotation().setFlag(Annotation::Flag_Combo);
750 			currItem->setItemName( CommonStrings::itemName_ComboBox + QString("%1").arg(m_doc->TotalItems));
751 			break;
752 		case modeInsertPDFListbox:
753 			currItem->annotation().setType(Annotation::Listbox);
754 			currItem->setItemName( CommonStrings::itemName_ListBox + QString("%1").arg(m_doc->TotalItems));
755 			break;
756 		case modeInsertPDFTextAnnotation:
757 			currItem->annotation().setType(Annotation::Text);
758 			currItem->setItemName( CommonStrings::itemName_TextAnnotation + QString("%1").arg(m_doc->TotalItems));
759 			break;
760 		case modeInsertPDFLinkAnnotation:
761 			currItem->annotation().setType(Annotation::Link);
762 			currItem->annotation().setZiel(m_doc->currentPage()->pageNr());
763 			currItem->annotation().setAction("0 0");
764 			currItem->setItemName( CommonStrings::itemName_LinkAnnotation + QString("%1").arg(m_doc->TotalItems));
765 			currItem->setTextFlowMode(PageItem::TextFlowDisabled);
766 			break;
767 		}
768 		break;
769 	case modeDrawTable2:
770 		// TODO: Figure out what these conditions actually do.
771 		if ((m_doc->m_Selection->isEmpty()) && (m_view->HaveSelRect) && (!m_view->MidButt))
772 		{
773 			m_view->HaveSelRect = false;
774 			// Calculate table rectangle.
775 			FRect tableRect = adjustedRect(canvasPressCoord, canvasCurrCoord);
776 			if (tableRect.width() < 6 || tableRect.height() < 6)
777 			{
778 				// Ignore tiny tables.
779 				m_view->requestMode(submodePaintingDone);
780 				break;
781 			}
782 			// Show table insert dialog.
783 		//	qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
784 			InsertTable *dia = new InsertTable(m_view, static_cast<int>(tableRect.height()/6), static_cast<int>(tableRect.width()/6));
785 			if (!dia->exec())
786 			{
787 				m_view->requestMode(submodePaintingDone);
788 				delete dia;
789 				dia = nullptr;
790 				break;
791 			}
792 			int numRows = dia->Rows->value();
793 			int numColumns = dia->Cols->value();
794 			delete dia;
795 			dia = nullptr;
796 			// Add the table item.
797 			// TODO: This should be done in an undo transaction.
798 			m_doc->dontResize = true;
799 			z = m_doc->itemAdd(PageItem::Table, PageItem::Unspecified,
800 						   tableRect.x(),
801 						   tableRect.y(),
802 						   tableRect.width(),
803 						   tableRect.height(),
804 						   0,                    // Unused.
805 						   CommonStrings::None,  // Unused.
806 						   CommonStrings::None); // Unused.
807 			PageItem_Table *table = m_doc->Items->at(z)->asTable();
808 			table->insertRows(0, numRows - 1);
809 			table->insertColumns(0, numColumns - 1);
810 			table->adjustTableToFrame();
811 			table->adjustFrameToTable();
812 			m_doc->dontResize = false;
813 			m_doc->setRedrawBounding(table);
814 		}
815 		break;
816 	case modeInsertPDF3DAnnotation:
817 		if (modifiers == Qt::ShiftModifier)
818 		{
819 			z = m_doc->itemAddArea(PageItem::OSGFrame, PageItem::Unspecified, Rxp, Ryp, 1, m_doc->itemToolPrefs().imageFillColor, m_doc->itemToolPrefs().imageStrokeColor);
820 		}
821 		else
822 		{
823 			z = m_doc->itemAdd(PageItem::OSGFrame, PageItem::Unspecified, Rxp, Ryp, Rxpd, Rypd, m_doc->itemToolPrefs().shapeLineWidth, m_doc->itemToolPrefs().imageFillColor, m_doc->itemToolPrefs().imageStrokeColor);
824 		}
825 		currItem = m_doc->Items->at(z);
826 		currItem->setIsAnnotation(true);
827 		currItem->AutoName = false;
828 		currItem->annotation().setType(Annotation::Annot3D);
829 		currItem->setItemName( tr("3DAnnot") + QString("%1").arg(m_doc->TotalItems));
830 		break;
831 	}
832 	if (z >= 0)
833 	{
834 		SetupDrawNoResize(z);
835 		newObject = m_doc->Items->at(z);
836 		newObject->ContourLine = newObject->PoLine.copy();
837 		m_doc->setRedrawBounding(newObject);
838 	}
839 	return newObject;
840 }
841 
doOneClick(FPoint & startPoint,FPoint & endPoint)842 bool CreateMode::doOneClick(FPoint& startPoint, FPoint& endPoint)
843 {
844 	bool doCreate = false;
845 	double xSize, ySize;
846 	int  originPoint = 0;
847 
848 	if (QApplication::keyboardModifiers() & Qt::ControlModifier)
849 		return true;
850 
851 	PrefsContext* sizes = PrefsManager::instance().prefsFile->getContext("ObjectSize");
852 	bool doRemember     = sizes->getBool("Remember", true);
853 
854 	int lmode = (createObjectMode == modeDrawLine) ? 1 : 0;
855 	if (lmode == 0)
856 	{
857 		xSize = sizes->getDouble("defWidth", 100.0);
858 		ySize = sizes->getDouble("defHeight", 100.0);
859 		originPoint = sizes->getInt("Origin", 0);
860 	}
861 	else
862 	{
863 		xSize = sizes->getDouble("defLength", 100.0);
864 		ySize = sizes->getDouble("defAngle", 0.0);
865 		originPoint = sizes->getInt("OriginL", 0);
866 	}
867 
868 	if (lmode == 0)
869 	{
870 		if (doRemember)
871 		{
872 			sizes->set("defWidth", xSize);
873 			sizes->set("defHeight", ySize);
874 			sizes->set("Origin", originPoint);
875 		}
876 		endPoint.setXY(startPoint.x() + xSize, startPoint.y() + ySize);
877 		switch (originPoint)
878 		{
879 			case 0:
880 				break;
881 			case 1:
882 				startPoint.setX(startPoint.x() - xSize);
883 				endPoint.setX(endPoint.x() - xSize);
884 				break;
885 			case 2:
886 				startPoint.setXY(startPoint.x() - xSize / 2.0, startPoint.y() - ySize / 2.0);
887 				endPoint.setXY(endPoint.x() - xSize / 2.0, endPoint.y() - ySize / 2.0);
888 				break;
889 			case 3:
890 				startPoint.setY(startPoint.y() - ySize);
891 				endPoint.setY(endPoint.y() - ySize);
892 				break;
893 			case 4:
894 				startPoint.setXY(startPoint.x() - xSize, startPoint.y() - ySize);
895 				endPoint.setXY(endPoint.x() - xSize, endPoint.y() - ySize);
896 				break;
897 		}
898 	}
899 	else
900 	{
901 		FPoint oldStart = startPoint;
902 		if (doRemember)
903 		{
904 			sizes->set("defLength", xSize);
905 			sizes->set("defAngle", ySize);
906 			sizes->set("OriginL", originPoint);
907 		}
908 		double angle = -ySize * M_PI / 180.0;
909 		switch (originPoint)
910 		{
911 			case 0:
912 				endPoint = FPoint(startPoint.x() + xSize * cos(angle), startPoint.y() + xSize * sin(angle));
913 				break;
914 			case 1:
915 				startPoint = FPoint(oldStart.x() - xSize * cos(angle), oldStart.y() - xSize * sin(angle));
916 				endPoint   = oldStart;
917 				break;
918 			case 2:
919 				startPoint = FPoint(oldStart.x() - xSize / 2.0 * cos(angle), oldStart.y() - xSize / 2.0 * sin(angle));
920 				endPoint   = FPoint(oldStart.x() + xSize / 2.0 * cos(angle), oldStart.y() + xSize / 2.0 * sin(angle));
921 				break;
922 		}
923 	}
924 	sizes->set("Remember", doRemember);
925 	doCreate = true;
926 
927 	//delete dia;
928 	return doCreate;
929 }
930 
adjustedRect(FPoint & firstPoint,FPoint & secondPoint)931 FRect CreateMode::adjustedRect(FPoint &firstPoint, FPoint &secondPoint)
932 {
933 	// Lock to grid.
934 	FPoint first = m_doc->ApplyGridF(firstPoint);
935 	FPoint second = m_doc->ApplyGridF(secondPoint);
936 
937 	// Lock to guides and items.
938 	double firstX = first.x();
939 	double firstY = first.y();
940 	m_doc->ApplyGuides(&firstX, &firstY);
941 	m_doc->ApplyGuides(&firstX, &firstY,true);
942 
943 	double secondX = second.x();
944 	double secondY = second.y();
945 	m_doc->ApplyGuides(&secondX, &secondY);
946 	m_doc->ApplyGuides(&secondX, &secondY,true);
947 
948 	// Return normalized rectangle.
949 	FRect rect(firstX, firstY, secondX - firstX, secondY - firstY);
950 
951 	return rect.normalize();
952 }
953 
954 // void CreateMode::setResizeCursor(int how)
955 // {
956 // 	switch (how)
957 // 	{
958 // 		case 1:
959 // 		case 2:
960 // 			qApp->changeOverrideCursor(QCursor(Qt::SizeFDiagCursor));
961 // 			break;
962 // 		case 3:
963 // 		case 4:
964 // 			qApp->changeOverrideCursor(QCursor(Qt::SizeBDiagCursor));
965 // 			break;
966 // 		case 5:
967 // 		case 8:
968 // 			qApp->changeOverrideCursor(QCursor(Qt::SizeVerCursor));
969 // 			break;
970 // 		case 6:
971 // 		case 7:
972 // 			qApp->changeOverrideCursor(QCursor(Qt::SizeHorCursor));
973 // 			break;
974 // 		default:
975 // 			qApp->changeOverrideCursor(QCursor(Qt::SizeAllCursor));
976 // 			break;
977 // 	}
978 // }
979 
980