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 canvasmode_editweldpoint.cpp - description
17 -------------------
18 begin : Sun Oct 23 2011
19 copyright : (C) 2011 by Franz Schmid
20 email : Franz.Schmid@altmuehlnet.de
21 ***************************************************************************/
22
23
24 #include "canvasmode_editweldpoint.h"
25
26 #include <QApplication>
27 #include <QButtonGroup>
28 #include <QCheckBox>
29 #include <QCursor>
30 #include <QEvent>
31 #include <QMessageBox>
32 #include <QMouseEvent>
33 #include <QPainterPath>
34 #include <QPoint>
35 #include <QRect>
36 #include <QTimer>
37 #include <QWidgetAction>
38 #include <QDebug>
39
40 #include "appmodes.h"
41 #include "canvas.h"
42 #include "fpoint.h"
43 #include "fpointarray.h"
44 #include "hyphenator.h"
45 #include "pageitem_textframe.h"
46 #include "prefscontext.h"
47 #include "prefsfile.h"
48 #include "prefsmanager.h"
49 #include "sccolorengine.h"
50 #include "sclimits.h"
51 #include "scribus.h"
52 #include "scribusXml.h"
53 #include "scribusdoc.h"
54 #include "scribusview.h"
55 #include "selection.h"
56 #include "ui/aligndistribute.h"
57 #include "ui/contextmenu.h"
58 #include "ui/pageselector.h"
59 #include "ui/propertiespalette.h"
60 #include "undomanager.h"
61 #include "units.h"
62 #include "util.h"
63 #include "util_math.h"
64
65
CanvasMode_EditWeldPoint(ScribusView * view)66 CanvasMode_EditWeldPoint::CanvasMode_EditWeldPoint(ScribusView* view) : CanvasMode(view),
67 m_ScMW(view->m_ScMW)
68 {
69 }
70
GetItem(PageItem ** pi)71 inline bool CanvasMode_EditWeldPoint::GetItem(PageItem** pi)
72 {
73 *pi = m_doc->m_Selection->itemAt(0);
74 return (*pi) != nullptr;
75 }
76
drawControls(QPainter * p)77 void CanvasMode_EditWeldPoint::drawControls(QPainter* p)
78 {
79 p->save();
80 if (m_canvas->m_viewMode.operItemMoving)
81 {
82 drawOutline(p);
83 }
84 else
85 {
86 drawSelection(p, false);
87 }
88 if (m_doc->appMode == modeEditWeldPoint)
89 {
90 drawControlsWeldPoint(p, m_doc->m_Selection->itemAt(0));
91 }
92 p->restore();
93 }
94
drawControlsWeldPoint(QPainter * psx,PageItem * currItem)95 void CanvasMode_EditWeldPoint::drawControlsWeldPoint(QPainter* psx, PageItem* currItem)
96 {
97 psx->translate(static_cast<int>(currItem->xPos()), static_cast<int>(currItem->yPos()));
98 psx->rotate(currItem->rotation());
99 psx->setBrush(Qt::NoBrush);
100 for (int i = 0 ; i < currItem->weldList.count(); i++)
101 {
102 PageItem::WeldingInfo wInf = currItem->weldList.at(i);
103 if (i == m_selectedPoint)
104 psx->setPen(QPen(Qt::red, 8.0 / m_canvas->scale(), Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
105 else
106 psx->setPen(QPen(Qt::yellow, 8.0 / m_canvas->scale(), Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
107 psx->drawPoint(QPointF(wInf.weldPoint.x(), wInf.weldPoint.y()));
108 }
109 }
110
enterEvent(QEvent * e)111 void CanvasMode_EditWeldPoint::enterEvent(QEvent *e)
112 {
113 if (!m_canvas->m_viewMode.m_MouseButtonPressed)
114 {
115 setModeCursor();
116 }
117 }
118
leaveEvent(QEvent * e)119 void CanvasMode_EditWeldPoint::leaveEvent(QEvent *e)
120 {
121 }
122
123
activate(bool fromGesture)124 void CanvasMode_EditWeldPoint::activate(bool fromGesture)
125 {
126 CanvasMode::activate(fromGesture);
127
128 m_canvas->m_viewMode.m_MouseButtonPressed = false;
129 m_canvas->resetRenderMode();
130 m_doc->DragP = false;
131 m_doc->leaveDrag = false;
132 m_canvas->m_viewMode.operItemMoving = false;
133 m_canvas->m_viewMode.operItemResizing = false;
134 m_view->MidButt = false;
135 m_keyRepeat = false;
136 m_currItem = m_doc->m_Selection->itemAt(0);
137 m_weldToList = m_currItem->itemsWeldedTo();
138 m_weldToList.append(m_currItem);
139 m_Mxp = m_Myp = -1;
140 m_selectedPoint = -1;
141 setModeCursor();
142 if (fromGesture)
143 {
144 m_view->update();
145 }
146 m_ModeDialog = new WeldEditDialog(m_ScMW);
147 m_ModeDialog->show();
148 connect(m_ModeDialog, SIGNAL(endEdit()), this, SLOT(endEditing()));
149 connect(m_ModeDialog, SIGNAL(paletteShown(bool)), this, SLOT(endEditing(bool)));
150 connect(m_ModeDialog, SIGNAL(modeMoveWeld()), this, SLOT(setWeldMode()));
151 connect(m_ModeDialog, SIGNAL(modeMoveObject()), this, SLOT(setObjectMode()));
152 }
153
deactivate(bool forGesture)154 void CanvasMode_EditWeldPoint::deactivate(bool forGesture)
155 {
156 m_view->setRedrawMarkerShown(false);
157 m_selectedPoint = -1;
158 m_weldToList.clear();
159 disconnect(m_ModeDialog, SIGNAL(paletteShown(bool)), this, SLOT(endEditing(bool)));
160 m_ModeDialog->close();
161 delete m_ModeDialog;
162
163 CanvasMode::deactivate(forGesture);
164 }
165
endEditing(bool active)166 void CanvasMode_EditWeldPoint::endEditing(bool active)
167 {
168 if (!active)
169 endEditing();
170 }
171
endEditing()172 void CanvasMode_EditWeldPoint::endEditing()
173 {
174 m_view->requestMode(modeNormal);
175 }
176
setWeldMode()177 void CanvasMode_EditWeldPoint::setWeldMode()
178 {
179 m_editWeldMode = true;
180 }
181
setObjectMode()182 void CanvasMode_EditWeldPoint::setObjectMode()
183 {
184 m_editWeldMode = false;
185 }
186
keyPressEvent(QKeyEvent * e)187 void CanvasMode_EditWeldPoint::keyPressEvent(QKeyEvent *e)
188 {
189 if (m_selectedPoint < 0)
190 return;
191 int kk = e->key();
192 if (m_keyRepeat)
193 return;
194 m_keyRepeat = true;
195 e->accept();
196
197 if (e->key() == Qt::Key_Escape)
198 {
199 // Go back to normal mode.
200 m_view->requestMode(modeNormal);
201 return;
202 }
203
204 Qt::KeyboardModifiers buttonModifiers = e->modifiers();
205 if ((!m_view->m_ScMW->zoomSpinBox->hasFocus()) && (!m_view->m_ScMW->pageSelector->hasFocus()))
206 {
207 if (m_doc->m_Selection->count() != 0)
208 {
209 double moveBy = 1.0;
210 double moveX = 0.0;
211 double moveY = 0.0;
212 bool isMoving = false;
213 bool doUpdate = false;
214 if (m_doc->unitIndex()!=SC_INCHES)
215 {
216 if ((buttonModifiers & Qt::ShiftModifier) && !(buttonModifiers & Qt::ControlModifier) && !(buttonModifiers & Qt::AltModifier))
217 moveBy = 0.1;
218 else if (!(buttonModifiers & Qt::ShiftModifier) && (buttonModifiers & Qt::ControlModifier) && !(buttonModifiers & Qt::AltModifier))
219 moveBy = 10.0;
220 else if ((buttonModifiers & Qt::ShiftModifier) && (buttonModifiers & Qt::ControlModifier) && !(buttonModifiers & Qt::AltModifier))
221 moveBy = 0.01;
222 moveBy /= m_doc->unitRatio();//Lets allow movement by the current doc ratio, not only points
223 }
224 else
225 {
226 if ((buttonModifiers & Qt::ShiftModifier) && !(buttonModifiers & Qt::ControlModifier) && !(buttonModifiers & Qt::AltModifier))
227 moveBy = 0.1 / m_doc->unitRatio();
228 else if (!(buttonModifiers & Qt::ShiftModifier) && (buttonModifiers & Qt::ControlModifier) && !(buttonModifiers & Qt::AltModifier))
229 moveBy = 1.0 / m_doc->unitRatio();
230 else if ((buttonModifiers & Qt::ShiftModifier) && (buttonModifiers & Qt::ControlModifier) && !(buttonModifiers & Qt::AltModifier))
231 moveBy = 0.01 /m_doc->unitRatio();
232 }
233 moveBy /= m_canvas->m_viewMode.scale;
234 PageItem *currItem = m_doc->m_Selection->itemAt(0);
235 switch (kk)
236 {
237 case Qt::Key_7:
238 moveX = -moveBy;
239 moveY = -moveBy;
240 isMoving = true;
241 doUpdate = true;
242 break;
243 case Qt::Key_9:
244 moveX = moveBy;
245 moveY = -moveBy;
246 isMoving = true;
247 doUpdate = true;
248 break;
249 case Qt::Key_3:
250 moveX = moveBy;
251 moveY = moveBy;
252 isMoving = true;
253 doUpdate = true;
254 break;
255 case Qt::Key_1:
256 moveX = -moveBy;
257 moveY = moveBy;
258 isMoving = true;
259 doUpdate = true;
260 break;
261 case Qt::Key_Left:
262 case Qt::Key_4:
263 moveX = -moveBy;
264 isMoving = true;
265 doUpdate = true;
266 break;
267 case Qt::Key_Right:
268 case Qt::Key_6:
269 moveX = moveBy;
270 isMoving = true;
271 doUpdate = true;
272 break;
273 case Qt::Key_Up:
274 case Qt::Key_8:
275 moveY = -moveBy;
276 isMoving = true;
277 doUpdate = true;
278 break;
279 case Qt::Key_Down:
280 case Qt::Key_2:
281 moveY = moveBy;
282 isMoving = true;
283 doUpdate = true;
284 break;
285 }
286 if (isMoving)
287 {
288 if (m_editWeldMode)
289 {
290 currItem->weldList[m_selectedPoint].weldPoint += FPoint(moveX, moveY);
291 }
292 else
293 {
294 currItem->setXYPos(currItem->xPos() + moveX, currItem->yPos() + moveY, true);
295 currItem->setRedrawBounding();
296 currItem->OwnPage = m_doc->OnPage(currItem);
297 }
298 }
299 if (doUpdate)
300 {
301 currItem->update();
302 m_doc->regionsChanged()->update(getUpdateRect());
303 }
304 }
305 }
306 m_keyRepeat = false;
307 }
308
mouseDoubleClickEvent(QMouseEvent * m)309 void CanvasMode_EditWeldPoint::mouseDoubleClickEvent(QMouseEvent *m)
310 {
311 m->accept();
312 m_canvas->m_viewMode.m_MouseButtonPressed = false;
313 m_canvas->resetRenderMode();
314 if ((m_doc->m_Selection->isMultipleSelection()) || (m_doc->appMode != modeNormal))
315 {
316 if ((m_doc->m_Selection->isMultipleSelection()) && (m_doc->appMode == modeNormal))
317 {
318 if (GetItem(&m_currItem))
319 {
320 /* CB: old code, removing this as shift-alt select on an unselected table selects a cell now.
321 //#6789 is closed by sorting this.
322 if (currItem->isTableItem)
323 {
324 m_view->Deselect(false);
325 m_doc->m_Selection->addItem(currItem);
326 currItem->isSingleSel = true;
327 //CB FIXME don't call this if the added item is item 0
328 if (!m_doc->m_Selection->primarySelectionIs(currItem))
329 currItem->emitAllToGUI();
330 m_view->updateContents(currItem->getRedrawBounding(m_canvas->scale()));
331 }*/
332 }
333 return;
334 }
335 if (!(GetItem(&m_currItem) && (m_doc->appMode == modeEdit) && m_currItem->isTextFrame()))
336 {
337 mousePressEvent(m);
338 return;
339 }
340 }
341 }
342
mouseMoveEvent(QMouseEvent * m)343 void CanvasMode_EditWeldPoint::mouseMoveEvent(QMouseEvent *m)
344 {
345 const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
346 m->accept();
347 FPoint npfN;
348 double nx = mousePointDoc.x();
349 double ny = mousePointDoc.y();
350 if (!m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
351 npfN = m_doc->ApplyGridF(FPoint(nx, ny));
352 else
353 npfN = FPoint(nx, ny);
354 m_currItem = m_doc->m_Selection->itemAt(0);
355 FPoint npf = FPoint(npfN.x(), npfN.y(), m_currItem->xPos(), m_currItem->yPos(), m_currItem->rotation(), 1, 1, true);
356 FPoint npx(m_Mxp - npfN.x(), m_Myp - npfN.y(), 0, 0, m_currItem->rotation(), 1, 1, true);
357 m_canvas->displayXYHUD(m->globalPos(), npf.x(), npf.y());
358 if (m_canvas->m_viewMode.m_MouseButtonPressed && m_view->moveTimerElapsed())
359 {
360 if (m_editWeldMode)
361 {
362 if (m_selectedPoint != -1)
363 {
364 m_canvas->displayXYHUD(m->globalPos(), npf.x(), npf.y());
365 FPoint mp_orig = m_currItem->weldList[m_selectedPoint].weldPoint;
366 FPoint mp = mp_orig - npx;
367 double xx = mp.x();
368 double yy = mp.y();
369 snapToEdgePoints(xx, yy);
370 m_currItem->weldList[m_selectedPoint].weldPoint = FPoint(xx, yy);
371 }
372 }
373 else
374 {
375 m_currItem->setXYPos(m_currItem->xPos() - npx.x(), m_currItem->yPos() - npx.y(), true);
376 m_currItem->setRedrawBounding();
377 m_currItem->OwnPage = m_doc->OnPage(m_currItem);
378 }
379 m_doc->regionsChanged()->update(getUpdateRect());
380 }
381 m_Mxp = npfN.x();
382 m_Myp = npfN.y();
383 }
384
mousePressEvent(QMouseEvent * m)385 void CanvasMode_EditWeldPoint::mousePressEvent(QMouseEvent *m)
386 {
387 const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
388
389 m_canvas->PaintSizeRect(QRect());
390 m_canvas->m_viewMode.m_MouseButtonPressed = true;
391 m_canvas->m_viewMode.operItemMoving = false;
392 m_view->HaveSelRect = false;
393 m_doc->DragP = false;
394 m_doc->leaveDrag = false;
395 m->accept();
396 m_view->registerMousePress(m->globalPos());
397 m_Mxp = mousePointDoc.x(); //m->x();
398 m_Myp = mousePointDoc.y(); //m->y();
399 if (m->button() == Qt::MidButton)
400 {
401 m_view->MidButt = true;
402 if (m->modifiers() & Qt::ControlModifier)
403 m_view->DrawNew();
404 return;
405 }
406 QTransform itemMatrix;
407 m_currItem = m_doc->m_Selection->itemAt(0);
408 itemMatrix.translate(m_currItem->xPos(), m_currItem->yPos());
409 itemMatrix.rotate(m_currItem->rotation());
410 m_selectedPoint = -1;
411 for (int i = 0 ; i < m_currItem->weldList.count(); i++)
412 {
413 PageItem::WeldingInfo wInf = m_currItem->weldList.at(i);
414 if (m_canvas->hitsCanvasPoint(mousePointDoc, itemMatrix.map(QPointF(wInf.weldPoint.x(), wInf.weldPoint.y()))))
415 {
416 m_selectedPoint = i;
417 break;
418 }
419 }
420 m_canvas->m_viewMode.m_MouseButtonPressed = true;
421 m_view->setCursor(QCursor(Qt::CrossCursor));
422 m_doc->regionsChanged()->update(getUpdateRect());
423 }
424
mouseReleaseEvent(QMouseEvent * m)425 void CanvasMode_EditWeldPoint::mouseReleaseEvent(QMouseEvent *m)
426 {
427 m_canvas->m_viewMode.m_MouseButtonPressed = false;
428 m_canvas->resetRenderMode();
429 m->accept();
430 m_currItem = m_doc->m_Selection->itemAt(0);
431 m_currItem->update();
432 m_doc->regionsChanged()->update(getUpdateRect());
433 }
434
snapToEdgePoints(double & x,double & y)435 void CanvasMode_EditWeldPoint::snapToEdgePoints(double &x, double &y)
436 {
437 int radius = m_doc->guidesPrefs().grabRadius;
438 if (qAbs(0.0 - x) < radius && qAbs(0.0 - y) < radius)
439 {
440 x = 0.0;
441 y = 0.0;
442 return;
443 }
444 if ((qAbs((m_currItem->width() / 2.0) - x) < radius) && (qAbs(0.0 - y) < radius))
445 {
446 x = m_currItem->width() / 2.0;
447 y = 0.0;
448 return;
449 }
450 if ((qAbs(m_currItem->width() - x) < radius) && (qAbs(0.0 - y) < radius))
451 {
452 x = m_currItem->width();
453 y = 0.0;
454 return;
455 }
456 if ((qAbs(0.0 - x) < radius) && (qAbs((m_currItem->height() / 2.0) - y) < radius))
457 {
458 x = 0.0;
459 y = m_currItem->height() / 2.0;
460 return;
461 }
462 if ((qAbs((m_currItem->width() / 2.0) - x) < radius) && (qAbs((m_currItem->height() / 2.0) - y) < radius))
463 {
464 x = m_currItem->width() / 2.0;
465 y = m_currItem->height() / 2.0;
466 return;
467 }
468 if ((qAbs(m_currItem->width() - x) < radius) && (qAbs((m_currItem->height() / 2.0) - y) < radius))
469 {
470 x = m_currItem->width();
471 y = m_currItem->height() / 2.0;
472 return;
473 }
474 if ((qAbs(0.0 - x) < radius) && (qAbs(m_currItem->height() - y) < radius))
475 {
476 x = 0.0;
477 y = m_currItem->height();
478 return;
479 }
480 if ((qAbs((m_currItem->width() / 2.0) - x) < radius) && (qAbs(m_currItem->height() - y) < radius))
481 {
482 x = m_currItem->width() / 2.0;
483 y = m_currItem->height();
484 return;
485 }
486 if ((qAbs(m_currItem->width() - x) < radius) && (qAbs(m_currItem->height() - y) < radius))
487 {
488 x = m_currItem->width();
489 y = m_currItem->height();
490 return;
491 }
492 }
493
getUpdateRect()494 QRectF CanvasMode_EditWeldPoint::getUpdateRect()
495 {
496 PageItem *item;
497 uint selectedItemCount = m_weldToList.count();
498 if (selectedItemCount == 0)
499 return QRectF();
500 double vminx = std::numeric_limits<double>::max();
501 double vminy = std::numeric_limits<double>::max();
502 double vmaxx = -std::numeric_limits<double>::max();
503 double vmaxy = -std::numeric_limits<double>::max();
504
505 for (uint gc = 0; gc < selectedItemCount; ++gc)
506 {
507 item = m_weldToList.at(gc);
508 if (item->rotation() != 0)
509 {
510 QRectF itRect(item->getVisualBoundingRect());
511 vminx = qMin(vminx, itRect.x());
512 vminy = qMin(vminy, itRect.y());
513 vmaxx = qMax(vmaxx, itRect.right());
514 vmaxy = qMax(vmaxy, itRect.bottom());
515 }
516 else
517 {
518 vminx = qMin(vminx, item->visualXPos());
519 vminy = qMin(vminy, item->visualYPos());
520 vmaxx = qMax(vmaxx, item->visualXPos() + item->visualWidth());
521 vmaxy = qMax(vmaxy, item->visualYPos() + item->visualHeight());
522 }
523 }
524 return QRectF(vminx, vminy, vmaxx - vminx, vmaxy - vminy).adjusted(-20, -20, 40, 40);
525 }
526