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_copyproperties.h"
18 
19 #include <QApplication>
20 #include <QCursor>
21 #include <QEvent>
22 #include <QMouseEvent>
23 #include <QPoint>
24 #include <QRect>
25 #include <QDebug>
26 
27 #include "appmodes.h"
28 #include "canvas.h"
29 #include "fpoint.h"
30 #include "scribus.h"
31 #include "scribusdoc.h"
32 #include "scribusview.h"
33 #include "selection.h"
34 #include "selectionrubberband.h"
35 #include "ui/contextmenu.h"
36 #include "util.h"
37 #include "util_math.h"
38 
39 
CanvasMode_CopyProperties(ScribusView * view)40 CanvasMode_CopyProperties::CanvasMode_CopyProperties(ScribusView* view) : CanvasMode(view), m_ScMW(view->m_ScMW)
41 {
42 }
43 
GetItem(PageItem ** pi)44 inline bool CanvasMode_CopyProperties::GetItem(PageItem** pi)
45 {
46 	*pi = m_doc->m_Selection->itemAt(0);
47 	return (*pi) != nullptr;
48 }
49 
drawControls(QPainter * p)50 void CanvasMode_CopyProperties::drawControls(QPainter* p)
51 {
52 	commonDrawControls(p, false);
53 }
54 
enterEvent(QEvent *)55 void CanvasMode_CopyProperties::enterEvent(QEvent *)
56 {
57 	if (!m_canvas->m_viewMode.m_MouseButtonPressed)
58 	{
59 		setModeCursor();
60 	}
61 }
62 
leaveEvent(QEvent * e)63 void CanvasMode_CopyProperties::leaveEvent(QEvent *e)
64 {
65 }
66 
67 
activate(bool fromGesture)68 void CanvasMode_CopyProperties::activate(bool fromGesture)
69 {
70 //	qDebug() << "CanvasMode_CopyProperties::activate" << fromGesture;
71 	CanvasMode::activate(fromGesture);
72 
73 	m_canvas->m_viewMode.m_MouseButtonPressed = false;
74 	m_canvas->resetRenderMode();
75 	m_doc->DragP = false;
76 	m_doc->leaveDrag = false;
77 	m_canvas->m_viewMode.operItemMoving = false;
78 	m_canvas->m_viewMode.operItemResizing = false;
79 	m_view->MidButt = false;
80 	Mxp = Myp = -1;
81 	Dxp = Dyp = -1;
82 	frameResizeHandle = -1;
83 	setModeCursor();
84 	if (fromGesture)
85 	{
86 		m_view->update();
87 	}
88 }
89 
deactivate(bool forGesture)90 void CanvasMode_CopyProperties::deactivate(bool forGesture)
91 {
92 //	qDebug() << "CanvasMode_CopyProperties::deactivate" << forGesture;
93 	m_view->setRedrawMarkerShown(false);
94 	CanvasMode::deactivate(forGesture);
95 }
96 
keyPressEvent(QKeyEvent * e)97 void CanvasMode_CopyProperties::keyPressEvent(QKeyEvent *e)
98 {
99 	commonkeyPressEvent_Default(e);
100 }
101 
keyReleaseEvent(QKeyEvent * e)102 void CanvasMode_CopyProperties::keyReleaseEvent(QKeyEvent *e)
103 {
104 	commonkeyReleaseEvent(e);
105 }
106 
mouseDoubleClickEvent(QMouseEvent * m)107 void CanvasMode_CopyProperties::mouseDoubleClickEvent(QMouseEvent *m)
108 {
109 	m->accept();
110 	m_canvas->m_viewMode.m_MouseButtonPressed = false;
111 	m_canvas->resetRenderMode();
112 //	m_view->stopDragTimer();
113 }
114 
mouseMoveEvent(QMouseEvent * m)115 void CanvasMode_CopyProperties::mouseMoveEvent(QMouseEvent *m)
116 {
117 	m->accept();
118 	if (commonMouseMove(m))
119 		return;
120 	if ((m_canvas->m_viewMode.m_MouseButtonPressed) && (m->buttons() & Qt::LeftButton))
121 	{
122 		QPoint startP = m_canvas->canvasToGlobal(QPointF(Mxp, Myp));
123 		m_view->redrawMarker->setGeometry(QRect(startP, m->globalPos()).normalized());
124 		m_view->setRedrawMarkerShown(true);
125 		m_view->HaveSelRect = true;
126 		return;
127 	}
128 }
129 
mousePressEvent(QMouseEvent * m)130 void CanvasMode_CopyProperties::mousePressEvent(QMouseEvent *m)
131 {
132 // 	const double mouseX = m->globalX();
133 // 	const double mouseY = m->globalY();
134 	const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
135 
136 	m_canvas->PaintSizeRect(QRect());
137 	m_canvas->m_viewMode.m_MouseButtonPressed = true;
138 	m_canvas->m_viewMode.operItemMoving = false;
139 	m_view->HaveSelRect = false;
140 	m_doc->DragP = false;
141 	m_doc->leaveDrag = false;
142 	m->accept();
143 	m_view->registerMousePress(m->globalPos());
144 	Mxp = mousePointDoc.x(); //qRound(m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
145 	Myp = mousePointDoc.y(); //qRound(m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
146 	double Rxp = m_doc->ApplyGridF(FPoint(Mxp, Myp)).x();
147 	Mxp = qRound(Rxp);
148 	double Ryp = m_doc->ApplyGridF(FPoint(Mxp, Myp)).y();
149 	Myp = qRound(Ryp);
150 	if (m->button() == Qt::MidButton)
151 	{
152 		m_view->MidButt = true;
153 		if (m->modifiers() & Qt::ControlModifier)
154 			m_view->DrawNew();
155 		return;
156 	}
157 	if (m->button() != Qt::LeftButton)
158 		return;
159 	SeleItem(m);
160 	PageItem *currItem;
161 	if (GetItem(&currItem))
162 	{
163 		double sx, sy, ex, ey, r, skx, sky, fx, fy, ss, sk, sp;
164 		currItem->m_columnGap = m_doc->ElemToLink->m_columnGap;
165 		currItem->m_columns = m_doc->ElemToLink->m_columns;
166 		currItem->setTextToFrameDist(m_doc->ElemToLink->textToFrameDistLeft(), m_doc->ElemToLink->textToFrameDistRight(), m_doc->ElemToLink->textToFrameDistTop(), m_doc->ElemToLink->textToFrameDistBottom());
167 		// Stroke Properties
168 		currItem->setLineStyle(m_doc->ElemToLink->lineStyle());
169 		currItem->setLineWidth(m_doc->ElemToLink->lineWidth());
170 		currItem->setLineTransparency(m_doc->ElemToLink->lineTransparency());
171 		currItem->setLineShade(m_doc->ElemToLink->lineShade());
172 		currItem->setLineColor(m_doc->ElemToLink->lineColor());
173 		currItem->setLineEnd(m_doc->ElemToLink->lineEnd());
174 		currItem->setLineJoin(m_doc->ElemToLink->lineJoin());
175 		currItem->setCustomLineStyle(m_doc->ElemToLink->customLineStyle());
176 		currItem->setEndArrowIndex(m_doc->ElemToLink->endArrowIndex());
177 		currItem->setStartArrowIndex(m_doc->ElemToLink->startArrowIndex());
178 		currItem->setEndArrowScale(m_doc->ElemToLink->endArrowScale());
179 		currItem->setStartArrowScale(m_doc->ElemToLink->startArrowScale());
180 		// Fill Properties
181 		currItem->setFillColor(m_doc->ElemToLink->fillColor());
182 		currItem->setFillShade(m_doc->ElemToLink->fillShade());
183 		currItem->setFillTransparency(m_doc->ElemToLink->fillTransparency());
184 		// Gradient Properties
185 		currItem->fill_gradient = m_doc->ElemToLink->fill_gradient;
186 		currItem->setGradient(m_doc->ElemToLink->gradient());
187 		m_doc->ElemToLink->gradientVector(sx, sy, ex, ey, fx, fy, ss, sk);
188 		currItem->setGradientVector(sx, sy, ex, ey, fx, fy, ss, sk);
189 		// Pattern Properties
190 		currItem->setPattern(m_doc->ElemToLink->pattern());
191 		m_doc->ElemToLink->patternTransform(sx, sy, ex, ey, r, skx, sky);
192 		currItem->setPatternTransform(sx, sy, ex, ey, r, skx, sky);
193 		currItem->setStrokePattern(m_doc->ElemToLink->strokePattern());
194 		m_doc->ElemToLink->strokePatternTransform(sx, sy, ex, ey, r, skx, sky, sp);
195 		currItem->setStrokePatternTransform(sx, sy, ex, ey, r, skx, sky, sp);
196 		currItem->setStrokePatternToPath(m_doc->ElemToLink->isStrokePatternToPath());
197 		// Set Gradient type after all properties
198 		currItem->setGradientType(m_doc->ElemToLink->gradientType());
199 
200 		currItem->stroke_gradient = m_doc->ElemToLink->stroke_gradient;
201 		currItem->setStrokeGradient(m_doc->ElemToLink->strokeGradient());
202 		m_doc->ElemToLink->strokeGradientVector(sx, sy, ex, ey, fx, fy, ss, sk);
203 		currItem->setStrokeGradientVector(sx, sy, ex, ey, fx, fy, ss, sk);
204 		currItem->setStrokeGradientType(m_doc->ElemToLink->strokeGradientType());
205 		// Update Item
206 		m_doc->ElemToLink = currItem;
207 		currItem->update();
208 //		emit DocChanged();
209 //		m_view->updateContents();
210 	}
211 	else
212 	{
213 		m_doc->ElemToLink = nullptr;
214 		m_view->requestMode(submodePaintingDone);
215 		m_view->canvasMode()->mousePressEvent(m);
216 	}
217 }
218 
mouseReleaseEvent(QMouseEvent * m)219 void CanvasMode_CopyProperties::mouseReleaseEvent(QMouseEvent *m)
220 {
221 #ifdef GESTURE_FRAME_PREVIEW
222 	clearPixmapCache();
223 #endif // GESTURE_FRAME_PREVIEW
224 	const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
225 	PageItem *currItem;
226 	m_canvas->m_viewMode.m_MouseButtonPressed = false;
227 	m_canvas->resetRenderMode();
228 	m->accept();
229 //	m_view->stopDragTimer();
230 	if ((GetItem(&currItem)) && (m->button() == Qt::RightButton) && (!m_doc->DragP))
231 	{
232 		createContextMenu(currItem, mousePointDoc.x(), mousePointDoc.y());
233 		return;
234 	}
235 }
236 
237 //CB-->Doc/Fix
SeleItem(QMouseEvent * m)238 bool CanvasMode_CopyProperties::SeleItem(QMouseEvent *m)
239 {
240 	const unsigned SELECT_IN_GROUP = Qt::AltModifier;
241 	const unsigned SELECT_MULTIPLE = Qt::ShiftModifier;
242 	const unsigned SELECT_BENEATH = Qt::ControlModifier;
243 	PageItem *currItem;
244 	m_canvas->m_viewMode.m_MouseButtonPressed = true;
245 	FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
246 	Mxp = mousePointDoc.x(); //m->x()/m_canvas->scale());
247 	Myp = mousePointDoc.y(); //m->y()/m_canvas->scale());
248 	int MxpS = static_cast<int>(mousePointDoc.x()); //m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
249 	int MypS = static_cast<int>(mousePointDoc.y()); //m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
250 	m_doc->nodeEdit.deselect();
251 	if (!m_doc->masterPageMode())
252 	{
253 		int pgNum = -1;
254 		int docPageCount = static_cast<int>(m_doc->Pages->count() - 1);
255 		MarginStruct pageBleeds;
256 		bool drawBleed = false;
257 		if (!m_doc->bleeds()->isNull() && m_doc->guidesPrefs().showBleed)
258 			drawBleed = true;
259 		for (int a = docPageCount; a > -1; a--)
260 		{
261 			if (drawBleed)
262 				m_doc->getBleeds(a, pageBleeds);
263 			int x = static_cast<int>(m_doc->Pages->at(a)->xOffset() - pageBleeds.left());
264 			int y = static_cast<int>(m_doc->Pages->at(a)->yOffset() - pageBleeds.top());
265 			int w = static_cast<int>(m_doc->Pages->at(a)->width() + pageBleeds.left() + pageBleeds.right());
266 			int h = static_cast<int>(m_doc->Pages->at(a)->height() + pageBleeds.bottom() + pageBleeds.top());
267 			if (QRect(x, y, w, h).contains(MxpS, MypS))
268 			{
269 				pgNum = static_cast<int>(a);
270 				if (drawBleed)  // check again if its really on the correct page
271 				{
272 					for (int a2 = docPageCount; a2 > -1; a2--)
273 					{
274 						int xn = static_cast<int>(m_doc->Pages->at(a2)->xOffset());
275 						int yn = static_cast<int>(m_doc->Pages->at(a2)->yOffset());
276 						int wn = static_cast<int>(m_doc->Pages->at(a2)->width());
277 						int hn = static_cast<int>(m_doc->Pages->at(a2)->height());
278 						if (QRect(xn, yn, wn, hn).contains(MxpS, MypS))
279 						{
280 							pgNum = static_cast<int>(a2);
281 							break;
282 						}
283 					}
284 				}
285 				break;
286 			}
287 		}
288 		if (pgNum >= 0)
289 		{
290 			if (m_doc->currentPageNumber() != pgNum)
291 			{
292 				m_doc->setCurrentPage(m_doc->Pages->at(pgNum));
293 				m_view->m_ScMW->slotSetCurrentPage(pgNum);
294 				m_view->DrawNew();
295 			}
296 		}
297 		m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
298 	}
299 	currItem = nullptr;
300 	if ((m->modifiers() & SELECT_BENEATH) != 0)
301 	{
302 		for (int i=0; i < m_doc->m_Selection->count(); ++i)
303 		{
304 			if (m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), m_doc->m_Selection->itemAt(i)) >= 0)
305 			{
306 				currItem = m_doc->m_Selection->itemAt(i);
307 				m_doc->m_Selection->removeItem(currItem);
308 				break;
309 			}
310 		}
311 	}
312 	else if ( (m->modifiers() & SELECT_MULTIPLE) == Qt::NoModifier || (m_doc->appMode == modeLinkFrames) || (m_doc->appMode == modeUnlinkFrames) )
313 	{
314 		m_view->deselectItems(false);
315 	}
316 	currItem = m_canvas->itemUnderCursor(m->globalPos(), currItem, (m->modifiers() & SELECT_IN_GROUP));
317 	if (currItem)
318 	{
319 		m_doc->m_Selection->delaySignalsOn();
320 		if (m_doc->m_Selection->containsItem(currItem))
321 		{
322 			m_doc->m_Selection->removeItem(currItem);
323 		}
324 		else
325 		{
326 			//CB: If we have a selection but the user clicks with control on another item that is not below the current
327 			//then clear and select the new item
328 			if ((m->modifiers() == SELECT_BENEATH) && m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem) >= 0)
329 				m_doc->m_Selection->clear();
330 			m_doc->m_Selection->addItem(currItem);
331 			if ( (m->modifiers() & SELECT_IN_GROUP) && (!currItem->isGroup()))
332 			{
333 				currItem->isSingleSel = true;
334 			}
335 		}
336 
337 		currItem->update();
338 		m_doc->m_Selection->delaySignalsOff();
339 		if (m_doc->m_Selection->count() > 1)
340 		{
341 			for (int aa = 0; aa < m_doc->m_Selection->count(); ++aa)
342 			{
343 				PageItem *bb = m_doc->m_Selection->itemAt(aa);
344 				bb->update();
345 			}
346 			double x, y, w, h;
347 			m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
348 			m_view->getGroupRectScreen(&x, &y, &w, &h);
349 		}
350 		if (m_doc->m_Selection->count() == 1)
351 		{
352 			frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
353 			if ((frameResizeHandle == Canvas::INSIDE) && (!currItem->locked()))
354 				m_view->setCursor(QCursor(Qt::SizeAllCursor));
355 		}
356 		else
357 		{
358 			m_view->setCursor(QCursor(Qt::SizeAllCursor));
359 			m_canvas->m_viewMode.operItemResizing = false;
360 		}
361 		return true;
362 	}
363 	m_doc->m_Selection->connectItemToGUI();
364 	if ( !(m->modifiers() & SELECT_MULTIPLE) || (m_doc->appMode == modeLinkFrames) || (m_doc->appMode == modeUnlinkFrames))
365 		m_view->deselectItems(true);
366 	return false;
367 }
368 
createContextMenu(PageItem *,double mx,double my)369 void CanvasMode_CopyProperties::createContextMenu(PageItem* /*currItem*/, double mx, double my)
370 {
371 	ContextMenu* cmen=nullptr;
372 	m_view->setCursor(QCursor(Qt::ArrowCursor));
373 	m_view->setObjectUndoMode();
374 	Mxp = mx;
375 	Myp = my;
376 	cmen = new ContextMenu(*(m_doc->m_Selection), m_ScMW, m_doc);
377 	if (cmen)
378 		cmen->exec(QCursor::pos());
379 	m_view->setGlobalUndoMode();
380 	delete cmen;
381 }
382