FreeCAD

Форк
0
/
QGILeaderLine.cpp 
588 строк · 17.8 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2019 WandererFan <wandererfan@gmail.com>                *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
# include <cmath>
26

27
# include <QGraphicsScene>
28
# include <QGraphicsSceneMouseEvent>
29
# include <QPainter>
30
# include <QPainterPath>
31
# include <QVector2D>
32
#endif
33

34
#include <Base/Console.h>
35
#include <Mod/TechDraw/App/ArrowPropEnum.h>
36
#include <Mod/TechDraw/App/DrawLeaderLine.h>
37
#include <Mod/TechDraw/App/DrawUtil.h>
38
#include <Mod/TechDraw/App/LineGroup.h>
39

40
#include "QGILeaderLine.h"
41
#include "PreferencesGui.h"
42
#include "QGEPath.h"
43
#include "QGIArrow.h"
44
#include "QGIPrimPath.h"
45
#include "Rez.h"
46
#include "ViewProviderLeader.h"
47
#include "ZVALUE.h"
48

49

50
using namespace TechDrawGui;
51
using namespace TechDraw;
52

53
//**************************************************************
54
QGILeaderLine::QGILeaderLine()
55
    : m_lineColor(Qt::black),
56
      m_lineStyle(Qt::SolidLine),
57
      m_hasHover(false),
58
      m_saveX(0.0),
59
      m_saveY(0.0),
60
      m_blockDraw(false)
61

62
{
63
    setHandlesChildEvents(false);
64
    setAcceptHoverEvents(true);
65
    setFlag(QGraphicsItem::ItemIsSelectable, true);
66
    setFlag(QGraphicsItem::ItemIsMovable, false);
67
    setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
68
    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
69

70
    setCacheMode(QGraphicsItem::NoCache);
71

72
    m_line = new QGIPrimPath();
73
    addToGroup(m_line);
74
    m_line->setFlag(QGraphicsItem::ItemIsSelectable, false);
75
    m_line->setAcceptHoverEvents(false);
76
    m_line->setPos(0.0, 0.0);
77

78
    m_editPath = new QGEPath(this);
79
    addToGroup(m_editPath);
80
    m_editPath->setPos(0.0, 0.0);
81
    m_editPath->setFlag(QGraphicsItem::ItemIsSelectable, false);
82
    m_editPath->setFlag(QGraphicsItem::ItemIsMovable, false);
83
    setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
84
    m_editPath->setZValue(ZVALUE::DIMENSION);
85
    m_editPath->hide();
86

87
    m_arrow1 = new QGIArrow();
88
    addToGroup(m_arrow1);
89
    m_arrow1->setPos(0.0, 0.0);
90
    m_arrow1->hide();
91
    m_arrow2 = new QGIArrow();
92
    addToGroup(m_arrow2);
93
    m_arrow2->setPos(0.0, 0.0);
94
    m_arrow2->hide();
95

96
    setZValue(ZVALUE::DIMENSION);
97

98
    QObject::connect(m_editPath,
99
                     &QGEPath::pointsUpdated,
100
                     this,
101
                     &QGILeaderLine::onLineEditFinished);
102
}
103

104
void QGILeaderLine::setLeaderFeature(TechDraw::DrawLeaderLine* feat)
105
{
106
    //    Base::Console().Message("QGILL::setLeaderFeature()\n");
107
    setViewFeature(static_cast<TechDraw::DrawView*>(feat));
108

109
    float x = Rez::guiX(feat->X.getValue());
110
    float y = Rez::guiX(-feat->Y.getValue());
111
    setPos(x, y);
112

113
    setNormalColorAll();
114
    setPrettyNormal();
115

116
    updateView();
117
}
118

119
QVariant QGILeaderLine::itemChange(GraphicsItemChange change, const QVariant& value)
120
{
121
    //    Base::Console().Message("QGILL::itemChange(%d)\n", change);
122
    if (change == ItemSelectedHasChanged && scene()) {
123
        if (isSelected()) {
124
            setPrettySel();
125
        }
126
        else {
127
            setPrettyNormal();
128
        }
129
        draw();
130
    }
131
    else if (change == ItemSceneChange && scene()) {
132
        // nothing special!
133
    }
134
    return QGIView::itemChange(change, value);
135
}
136

137
//QGILL isn't draggable so skip QGIV::mousePress have event
138
void QGILeaderLine::mousePressEvent(QGraphicsSceneMouseEvent* event)
139
{
140
    //    Base::Console().Message("QGILL::mousePressEvent() - %s\n", getViewName());
141
    QGraphicsItem::mousePressEvent(event);
142
}
143

144
//QGILL isn't draggable so skip QGIV::mouseRelease
145
void QGILeaderLine::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
146
{
147
    //    Base::Console().Message("QGILL::mouseReleaseEvent() - %s\n", getViewName());
148
    QGraphicsItem::mouseReleaseEvent(event);
149
}
150

151
void QGILeaderLine::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
152
{
153
    //    Base::Console().Message("QGILL::hoverEnter() - selected; %d\n", isSelected());
154
    m_hasHover = true;
155
    if (!isSelected()) {
156
        setPrettyPre();
157
    }
158
    QGIView::hoverEnterEvent(event);
159
}
160

161
void QGILeaderLine::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
162
{
163
    //    Base::Console().Message("QGILL::hoverLeave() - selected; %d\n", isSelected());
164
    m_hasHover = false;
165
    if (!isSelected()) {
166
        setPrettyNormal();
167
    }
168
    QGIView::hoverLeaveEvent(event);
169
}
170

171
void QGILeaderLine::setNormalColorAll()
172
{
173
    //    Base::Console().Message("QGILL::setNormalColorAll - normal color: %s\n", qPrintable(getNormalColor().name()));
174
    QColor qc = prefNormalColor();
175
    m_line->setNormalColor(qc);
176
    m_editPath->setNormalColor(qc);
177
    m_arrow1->setNormalColor(qc);
178
    m_arrow1->setFillColor(qc);
179
    m_arrow2->setNormalColor(qc);
180
    m_arrow2->setFillColor(qc);
181
}
182

183
void QGILeaderLine::setPrettyNormal()
184
{
185
    //    Base::Console().Message("QGILL::setPrettyNormal()\n");
186
    m_line->setPrettyNormal();
187
    m_arrow1->setPrettyNormal();
188
    m_arrow2->setPrettyNormal();
189
}
190

191
void QGILeaderLine::setPrettyPre()
192
{
193
    //    Base::Console().Message("QGILL::setPrettyPre()\n");
194
    m_line->setPrettyPre();
195
    m_arrow1->setPrettyPre();
196
    m_arrow2->setPrettyPre();
197
}
198

199
void QGILeaderLine::setPrettySel()
200
{
201
    //    Base::Console().Message("QGILL::setPrettySel()\n");
202
    m_line->setPrettySel();
203
    m_arrow1->setPrettySel();
204
    m_arrow2->setPrettySel();
205
}
206

207

208
void QGILeaderLine::closeEdit()
209
{
210
    //    Base::Console().Message("QGIL::closeEdit()\n");
211
    if (m_editPath) {
212
        m_editPath->onEndEdit();//tell QEPath that edit session ended
213
    }
214
}
215

216
//signaled from QEPath
217
void QGILeaderLine::onLineEditFinished(QPointF tipDisplace, std::vector<QPointF> points)
218
{
219
    //    Base::Console().Message("QGILL::onLineEditFinished(%s, %d)\n",
220
    //                            TechDraw::DrawUtil::formatVector(tipDisplace).c_str(),
221
    //                            points.size());
222
    m_blockDraw = true;
223
    auto featLeader = getFeature();
224
    if (!featLeader) {
225
        return;
226
    }
227
    double baseScale = featLeader->getBaseScale();
228

229
    if (!(TechDraw::DrawUtil::fpCompare(tipDisplace.x(), 0.0)
230
          && TechDraw::DrawUtil::fpCompare(tipDisplace.y(), 0.0))) {
231
        //tip was moved. need to change AttachPoint
232
        QPointF oldAttach = getAttachFromFeature();
233
        QPointF newAttach = oldAttach + (tipDisplace / baseScale);
234
        featLeader->setPosition(Rez::appX(newAttach.x()), Rez::appX(-newAttach.y()), true);
235
    }
236

237
    std::vector<Base::Vector3d> waypoints;
238
    for (auto& p : points) {
239
        QPointF moved = p - tipDisplace;
240
        Base::Vector3d v(moved.x(), moved.y(), 0.0);
241
        waypoints.push_back(v);
242
    }
243
    waypoints.at(0) = Base::Vector3d(0.0, 0.0, 0.0);
244

245
    featLeader->WayPoints.setValues(waypoints);
246
    if (featLeader->AutoHorizontal.getValue()) {
247
        featLeader->adjustLastSegment();
248
    }
249

250
    Q_EMIT editComplete();//tell task editing is complete
251

252
    m_blockDraw = false;
253
    m_editPath->hide();
254
    draw();
255
}
256

257
void QGILeaderLine::startPathEdit()
258
{
259
    saveState();
260
    auto featLeader(dynamic_cast<TechDraw::DrawLeaderLine*>(getViewObject()));
261
    if (!featLeader) {
262
        return;
263
    }
264

265
    double scale = featLeader->getScale();
266
    m_editPath->setScale(scale);
267
    m_editPath->inEdit(true);
268
    m_editPath->show();
269
    m_editPath->startPathEdit(getWayPointsFromFeature());
270
}
271

272
void QGILeaderLine::saveState()
273
{
274
    //    Base::Console().Message("QGILL::saveState()\n");
275
    auto featLeader = getFeature();
276
    if (featLeader) {
277
        m_savePoints = featLeader->WayPoints.getValues();
278
        m_saveX = featLeader->X.getValue();
279
        m_saveY = featLeader->Y.getValue();
280
    }
281
}
282

283
void QGILeaderLine::restoreState()
284
{
285
    //    Base::Console().Message("QGILL::restoreState()\n");
286
    auto featLeader = getFeature();
287
    if (featLeader) {
288
        featLeader->WayPoints.setValues(m_savePoints);
289
        featLeader->X.setValue(m_saveX);
290
        featLeader->Y.setValue(m_saveY);
291
        featLeader->recomputeFeature();
292
    }
293
}
294

295
//******************************************************************************
296

297
void QGILeaderLine::updateView(bool update)
298
{
299
    //    Base::Console().Message("QGIL::updateView() %s\n", getViewObject()->getNameInDocument());
300
    Q_UNUSED(update);
301
    auto featLeader(dynamic_cast<TechDraw::DrawLeaderLine*>(getViewObject()));
302
    if (!featLeader) {
303
        Base::Console().Warning("QGILL::updateView - no feature!\n");
304
        return;
305
    }
306

307
    auto vp = static_cast<ViewProviderLeader*>(getViewProvider(getViewObject()));
308
    if (!vp) {
309
        return;
310
    }
311
    draw();
312
}
313

314
void QGILeaderLine::draw()
315
{
316
    //    Base::Console().Message("QGILL::draw()- %s\n", getViewObject()->getNameInDocument());
317
    if (m_blockDraw) {
318
        return;
319
    }
320
    if (!isVisible()) {
321
        return;
322
    }
323
    TechDraw::DrawLeaderLine* featLeader = getFeature();
324
    if (!featLeader) {
325
        return;
326
    }
327
    auto vp = static_cast<ViewProviderLeader*>(getViewProvider(getViewObject()));
328
    if (!vp) {
329
        return;
330
    }
331

332
    double scale = 1.0;
333
    TechDraw::DrawView* parent = featLeader->getBaseView();
334
    if (parent) {
335
        scale = parent->getScale();
336
    }
337

338
    if (m_editPath->inEdit()) {
339
        return;
340
    }
341

342
    //********
343
    if (featLeader->isLocked()) {
344
        setFlag(QGraphicsItem::ItemIsMovable, false);
345
    }
346
    else {
347
        setFlag(QGraphicsItem::ItemIsMovable, true);
348
    }
349

350
    m_lineStyle = static_cast<Qt::PenStyle>(vp->LineStyle.getValue());
351
    double baseScale = featLeader->getBaseScale();
352
    double x = Rez::guiX(featLeader->X.getValue());
353
    double y = -Rez::guiX(featLeader->Y.getValue());
354
    QPointF aPoint(x, y);
355
    aPoint *= baseScale;
356
    setPos(aPoint);
357

358
    m_line->setFillStyle(Qt::NoBrush);
359
    m_line->setStyle(m_lineStyle);
360
    m_line->setWidth(getLineWidth());
361

362
    m_line->setPos(0, 0);//make m_line coords == leader coords
363

364
    std::vector<QPointF> qPoints = getWayPointsFromFeature();
365
    if (featLeader->Scalable.getValue()) {
366
        for (auto& p : qPoints) {
367
            p = p * scale;
368
        }
369
    }
370

371
    setNormalColorAll();
372
    m_line->setPath(makeLeaderPath(qPoints));
373
    setArrows(qPoints);
374

375
    if (isSelected()) {
376
        setPrettySel();
377
    }
378
    else if (m_hasHover) {
379
        setPrettyPre();
380
    }
381
    else {
382
        setPrettyNormal();
383
    }
384
    update(boundingRect());
385
}
386

387
QPainterPath QGILeaderLine::makeLeaderPath(std::vector<QPointF> qPoints)
388
{
389
    //    Base::Console().Message("QGILeaderLine::makeLeaderPath()\n");
390
    QPainterPath result;
391
    DrawLeaderLine* featLeader = getFeature();
392
    if (!featLeader) {
393
        Base::Console().Message("QGILL::makeLeaderPath - featLeader is nullptr\n");
394
        return result;
395
    }
396

397
    QPointF startAdjVec(0.0, 0.0);
398
    double startAdjLength(0.0);
399
    QPointF endAdjVec(0.0, 0.0);
400
    double endAdjLength(0.0);
401
    if (qPoints.size() > 1) {
402
        //make path adjustment to hide leaderline ends behind arrowheads
403
        if (featLeader->StartSymbol.getValue() != ArrowType::NONE) {
404
            startAdjLength = QGIArrow::getOverlapAdjust(featLeader->StartSymbol.getValue(),
405
                                                        QGIArrow::getPrefArrowSize());
406
        }
407
        if (featLeader->EndSymbol.getValue() != ArrowType::NONE) {
408
            endAdjLength = QGIArrow::getOverlapAdjust(featLeader->EndSymbol.getValue(),
409
                                                      QGIArrow::getPrefArrowSize());
410
        }
411

412
        //get adjustment directions
413
        startAdjVec = qPoints.at(1) - qPoints.front();
414
        endAdjVec = (*(qPoints.end() - 2)) - qPoints.back();
415

416
        //get adjustment vectors
417
        QVector2D startTemp(startAdjVec);
418
        QVector2D endTemp(endAdjVec);
419
        startTemp.normalize();
420
        endTemp.normalize();
421
        startAdjVec = startTemp.toPointF() * startAdjLength;
422
        endAdjVec = endTemp.toPointF() * endAdjLength;
423

424
        qPoints.front() += startAdjVec;
425
        qPoints.back() += endAdjVec;
426
        result.moveTo(qPoints.front());
427
        for (int i = 1; i < (int)qPoints.size(); i++) {
428
            result.lineTo(qPoints.at(i));
429
        }
430
    }
431
    return result;
432
}
433

434
QPointF QGILeaderLine::getAttachFromFeature()
435
{
436
    //    Base::Console().Message("QGILL::getAttachFromFeature()\n");
437
    TechDraw::DrawLeaderLine* featLeader = getFeature();
438
    if (!featLeader) {
439
        Base::Console().Message("QGIL::getAttachFromLeader - no feature\n");
440
        return QPointF();
441
    }
442
    double x = Rez::guiX(featLeader->X.getValue());
443
    double y = -Rez::guiX(featLeader->Y.getValue());
444
    return QPointF(x, y);
445
}
446

447
std::vector<QPointF> QGILeaderLine::getWayPointsFromFeature()
448
{
449
    std::vector<QPointF> qPoints;
450

451
    DrawLeaderLine* featLeader = getFeature();
452
    if (!featLeader) {
453
        Base::Console().Message("QGILL::getWayPointsFromFeature - featLeader is nullptr\n");
454
        return qPoints;
455
    }
456

457
    std::vector<Base::Vector3d> vPoints = featLeader->WayPoints.getValues();
458
    for (auto& d : vPoints) {
459
        QPointF temp(d.x, d.y);
460
        qPoints.push_back(temp);
461
    }
462
    if (qPoints.empty()) {
463
        Base::Console().Warning("QGILeaderLine::getWayPointsFromFeature - no points\n");
464
    }
465
    return qPoints;
466
}
467

468
void QGILeaderLine::setArrows(std::vector<QPointF> pathPoints)
469
{
470
    //    Base::Console().Message("QGILL::setArrows()\n");
471
    Base::Vector3d stdX(1.0, 0.0, 0.0);
472
    TechDraw::DrawLeaderLine* featLeader = getFeature();
473

474
    QPointF lastOffset = (pathPoints.back() - pathPoints.front());
475

476
    if (featLeader->StartSymbol.getValue() != ArrowType::NONE) {
477
        m_arrow1->setStyle(featLeader->StartSymbol.getValue());
478
        m_arrow1->setWidth(getLineWidth());
479
        m_arrow1->setSize(QGIArrow::getPrefArrowSize());
480
        m_arrow1->setDirMode(true);
481
        m_arrow1->setDirection(stdX);
482
        if (pathPoints.size() > 1) {
483
            auto it = pathPoints.begin();
484
            QPointF s = (*it);
485
            QPointF e = (*(it + 1));
486
            QPointF qsVec = s - e;
487
            Base::Vector3d sVec(qsVec.x(), qsVec.y(), 0.0);
488
            m_arrow1->setDirection(sVec);
489
            m_arrow1->setPos(0.0, 0.0);
490
        }
491
        m_arrow1->draw();
492
        m_arrow1->show();
493
    }
494
    else {
495
        m_arrow1->hide();
496
    }
497

498
    if (featLeader->EndSymbol.getValue() != ArrowType::NONE) {
499
        m_arrow2->setStyle(featLeader->EndSymbol.getValue());
500
        m_arrow2->setWidth(getLineWidth());
501
        m_arrow2->setSize(QGIArrow::getPrefArrowSize());
502
        m_arrow2->setDirMode(true);
503
        m_arrow2->setDirection(-stdX);
504
        if (pathPoints.size() > 1) {
505
            auto itr = pathPoints.rbegin();
506
            QPointF s = (*itr);
507
            QPointF e = (*(itr + 1));
508
            QPointF qeVec = s - e;
509
            Base::Vector3d eVec(qeVec.x(), qeVec.y(), 0.0);
510
            m_arrow2->setDirection(eVec);
511
            m_arrow2->setPos(lastOffset);
512
        }
513
        m_arrow2->draw();
514
        m_arrow2->show();
515
    }
516
    else {
517
        m_arrow2->hide();
518
    }
519
}
520

521
void QGILeaderLine::drawBorder()
522
{
523
    ////Leaders have no border!
524
    //    QGIView::drawBorder();   //good for debugging
525
}
526

527
//******************************************************************************
528

529

530
void QGILeaderLine::abandonEdit()
531
{
532
    //    Base::Console().Message("QGIL::abandonEdit()\n");
533
    m_editPath->clearMarkers();
534
    m_editPath->hide();
535
    restoreState();
536
}
537

538
double QGILeaderLine::getLineWidth()
539
{
540
    auto vp = static_cast<ViewProviderLeader*>(getViewProvider(getViewObject()));
541
    if (!vp) {
542
        return Rez::guiX(LineGroup::getDefaultWidth("Graphic"));
543
    }
544
    return Rez::guiX(vp->LineWidth.getValue());
545
}
546

547
TechDraw::DrawLeaderLine* QGILeaderLine::getFeature()
548
{
549
    TechDraw::DrawLeaderLine* result = static_cast<TechDraw::DrawLeaderLine*>(getViewObject());
550
    return result;
551
}
552

553
double QGILeaderLine::getEdgeFuzz() const
554
{
555
    return PreferencesGui::edgeFuzz();
556
}
557

558
QColor QGILeaderLine::prefNormalColor()
559
{
560
    //    Base::Console().Message("QGILL::getNormalColor()\n");
561
    setNormalColor(PreferencesGui::leaderQColor());
562

563
    auto vp = dynamic_cast<ViewProviderLeader*>(getViewProvider(getViewObject()));
564
    if (vp) {
565
        QColor normal = vp->Color.getValue().asValue<QColor>();
566
        setNormalColor(PreferencesGui::getAccessibleQColor(normal));
567
    }
568
    return getNormalColor();
569
}
570

571
QRectF QGILeaderLine::boundingRect() const
572
{
573
    return childrenBoundingRect();
574
}
575

576
void QGILeaderLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
577
                          QWidget* widget)
578
{
579
    QStyleOptionGraphicsItem myOption(*option);
580
    myOption.state &= ~QStyle::State_Selected;
581

582
    //    painter->setPen(Qt::blue);
583
    //    painter->drawRect(boundingRect());          //good for debugging
584

585
    QGIView::paint(painter, &myOption, widget);
586
}
587

588
#include <Mod/TechDraw/Gui/moc_QGILeaderLine.cpp>
589

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.