FreeCAD

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

24
#include "PreCompiled.h"
25

26
#ifndef _PreComp_
27
#include <QAction>
28
#include <QApplication>
29
#include <QContextMenuEvent>
30
#include <QMenu>
31
#include <QMessageBox>
32
#include <QPageLayout>
33
#include <QPageSize>
34
#include <QPaintEngine>
35
#include <QPainter>
36
#include <QPdfWriter>
37
#include <QPrintDialog>
38
#include <QPrintPreviewDialog>
39
#include <QPrinter>
40
#include <boost_signals2.hpp>
41
#include <cmath>
42
#endif
43

44
#include <App/Application.h>
45
#include <App/Document.h>
46
#include <App/DocumentObject.h>
47
#include <Base/Console.h>
48
#include <Base/Stream.h>
49
#include <Base/Tools.h>
50
#include <Gui/Application.h>
51
#include <Gui/Command.h>
52
#include <Gui/Document.h>
53
#include <Gui/FileDialog.h>
54
#include <Gui/MainWindow.h>
55
#include <Gui/Selection.h>
56
#include <Gui/SelectionObject.h>
57
#include <Gui/ViewProvider.h>
58
#include <Gui/WaitCursor.h>
59
#include <Gui/Window.h>
60
#include <Mod/TechDraw/App/DrawPage.h>
61
#include <Mod/TechDraw/App/DrawPagePy.h>
62
#include <Mod/TechDraw/App/DrawTemplate.h>
63
#include <Mod/TechDraw/App/Preferences.h>
64

65
#include "DrawGuiUtil.h"
66
#include "MDIViewPage.h"
67
#include "QGIEdge.h"
68
#include "QGIFace.h"
69
#include "QGITemplate.h"
70
#include "QGIVertex.h"
71
#include "QGIView.h"
72
#include "QGIViewBalloon.h"
73
#include "QGIViewDimension.h"
74
#include "QGMText.h"
75
#include "QGSPage.h"
76
#include "QGVPage.h"
77
#include "Rez.h"
78
#include "ViewProviderPage.h"
79
#include "PagePrinter.h"
80

81
using namespace TechDrawGui;
82
using namespace TechDraw;
83
namespace sp = std::placeholders;
84

85
/* TRANSLATOR TechDrawGui::MDIViewPage */
86

87
TYPESYSTEM_SOURCE_ABSTRACT(TechDrawGui::MDIViewPage, Gui::MDIView)
88

89
MDIViewPage::MDIViewPage(ViewProviderPage* pageVp, Gui::Document* doc, QWidget* parent)
90
    : Gui::MDIView(doc, parent), m_vpPage(pageVp)
91
{
92
    setMouseTracking(true);
93

94
    m_toggleKeepUpdatedAction = new QAction(tr("Toggle &Keep Updated"), this);
95
    connect(m_toggleKeepUpdatedAction, &QAction::triggered, this, &MDIViewPage::toggleKeepUpdated);
96

97
    m_toggleFrameAction = new QAction(tr("Toggle &Frames"), this);
98
    connect(m_toggleFrameAction, &QAction::triggered, this, &MDIViewPage::toggleFrame);
99

100
    m_exportSVGAction = new QAction(tr("&Export SVG"), this);
101
    connect(m_exportSVGAction, &QAction::triggered, this, qOverload<>(&MDIViewPage::saveSVG));
102

103
    m_exportDXFAction = new QAction(tr("Export DXF"), this);
104
    connect(m_exportDXFAction, &QAction::triggered, this, qOverload<>(&MDIViewPage::saveDXF));
105

106
    m_exportPDFAction = new QAction(tr("Export PDF"), this);
107
    connect(m_exportPDFAction, &QAction::triggered, this, qOverload<>(&MDIViewPage::savePDF));
108

109
    m_printAllAction = new QAction(tr("Print All Pages"), this);
110
    connect(m_printAllAction, &QAction::triggered, this, qOverload<>(&MDIViewPage::printAllPages));
111

112
    isSelectionBlocked = false;
113

114
    QString tabText = QString::fromUtf8(pageVp->getDrawPage()->getNameInDocument());
115
    tabText += QString::fromUtf8("[*]");
116
    setWindowTitle(tabText);
117

118
    //NOLINTBEGIN
119
    //get informed by App side about deleted DocumentObjects
120
    App::Document* appDoc = m_vpPage->getDocument()->getDocument();
121
    auto bnd = std::bind(&MDIViewPage::onDeleteObject, this, sp::_1);
122
    connectDeletedObject = appDoc->signalDeletedObject.connect(bnd);
123
    //NOLINTEND
124

125
    m_pagePrinter = new PagePrinter(m_vpPage);
126
    m_pagePrinter->setOwner(this);
127
}
128

129
MDIViewPage::~MDIViewPage()
130
{
131
    connectDeletedObject.disconnect();
132
    delete m_pagePrinter;
133
}
134

135
void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget)
136
{
137
    m_scene = scene;
138
    setCentralWidget(viewWidget);//this makes viewWidget a Qt child of MDIViewPage
139
    QObject::connect(scene, &QGSPage::selectionChanged, this, &MDIViewPage::sceneSelectionChanged);
140
    if (m_pagePrinter) {
141
        m_pagePrinter->setScene(m_scene);
142
    }
143
}
144

145
void MDIViewPage::setDocumentObject(const std::string& name)
146
{
147
    m_objectName = name;
148
    setObjectName(Base::Tools::fromStdString(name));
149
}
150

151
void MDIViewPage::setDocumentName(const std::string& name) { m_documentName = name; }
152

153
void MDIViewPage::closeEvent(QCloseEvent* event)
154
{
155
    //    Base::Console().Message("MDIVP::closeEvent()\n");
156
    MDIView::closeEvent(event);
157
    if (!event->isAccepted()) {
158
        return;
159
    }
160
    detachSelection();
161

162
    blockSceneSelection(true);
163
    // when closing the view from GUI notify the view provider to mark it invisible
164
    if (_pcDocument && !m_objectName.empty()) {
165
        App::Document* doc = _pcDocument->getDocument();
166
        if (doc) {
167
            App::DocumentObject* obj = doc->getObject(m_objectName.c_str());
168
            Gui::ViewProvider* vp = _pcDocument->getViewProvider(obj);
169
            if (vp) {
170
                vp->hide();
171
            }
172
        }
173
    }
174
    blockSceneSelection(false);
175
}
176

177
void MDIViewPage::onDeleteObject(const App::DocumentObject& obj)
178
{
179
    //if this page has a QView for this obj, delete it.
180
    blockSceneSelection(true);
181
    if (obj.isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
182
        (void)m_scene->removeQViewByName(obj.getNameInDocument());
183
    }
184
    blockSceneSelection(false);
185
}
186

187
bool MDIViewPage::onMsg(const char* pMsg, const char**)
188
{
189
    Gui::Document* doc(getGuiDocument());
190

191
    if (!doc) {
192
        return false;
193
    }
194
    else if (strcmp("ViewFit", pMsg) == 0) {
195
        viewAll();
196
        return true;
197
    }
198
    else if (strcmp("Save", pMsg) == 0) {
199
        doc->save();
200
        return true;
201
    }
202
    else if (strcmp("SaveAs", pMsg) == 0) {
203
        doc->saveAs();
204
        return true;
205
    }
206
    else if (strcmp("Undo", pMsg) == 0) {
207
        doc->undo(1);
208
        Gui::Command::updateActive();
209
        fixSceneDependencies();    // check QGraphicsScene item parenting
210
        return true;
211
    }
212
    else if (strcmp("Redo", pMsg) == 0) {
213
        doc->redo(1);
214
        Gui::Command::updateActive();
215
        return true;
216
    }
217
    else if (strcmp("ZoomIn", pMsg) == 0) {
218
        zoomIn();
219
        return true;
220
    }
221
    else if (strcmp("ZoomOut", pMsg) == 0) {
222
        zoomOut();
223
        return true;
224
    }
225

226
    return false;
227
}
228

229
bool MDIViewPage::onHasMsg(const char* pMsg) const
230
{
231
    if (strcmp("ViewFit", pMsg) == 0) {
232
        return true;
233
    }
234
    else if (strcmp("CanPan",pMsg) == 0) {
235
        return true;
236
    }
237
    else if (strcmp("Redo", pMsg) == 0 && getAppDocument()->getAvailableRedos() > 0) {
238
        return true;
239
    }
240
    else if (strcmp("Undo", pMsg) == 0 && getAppDocument()->getAvailableUndos() > 0) {
241
        return true;
242
    }
243
    else if (strcmp("Print", pMsg) == 0) {
244
        return true;
245
    }
246
    else if (strcmp("Save", pMsg) == 0) {
247
        return true;
248
    }
249
    else if (strcmp("SaveAs", pMsg) == 0) {
250
        return true;
251
    }
252
    else if (strcmp("PrintPreview", pMsg) == 0) {
253
        return true;
254
    }
255
    else if (strcmp("PrintPdf", pMsg) == 0) {
256
        return true;
257
    }
258
    else if (strcmp("PrintAll", pMsg) == 0) {
259
        return true;
260
    }
261
    else if (strcmp("ZoomIn", pMsg) == 0) {
262
        return true;
263
    }
264
    else if (strcmp("ZoomOut", pMsg) == 0) {
265
        return true;
266
    }
267
    return false;
268
}
269

270
// handle a zoomIn message from the menu
271
void MDIViewPage::zoomIn()
272
{
273
    m_vpPage->getQGVPage()->zoomIn();
274
}
275

276
// handle a zoomOut message from the menu
277
void MDIViewPage::zoomOut()
278
{
279
    m_vpPage->getQGVPage()->zoomOut();
280
}
281

282
// called by ViewProvider when Page feature Label changes
283
void MDIViewPage::setTabText(std::string tabText)
284
{
285
    if (!isPassive() && !tabText.empty()) {
286
        QString cap = QString::fromLatin1("%1 [*]").arg(QString::fromUtf8(tabText.c_str()));
287
        setWindowTitle(cap);
288
    }
289
}
290

291
// advise the page to check QGraphicsScene parent/child relationships after undo
292
void MDIViewPage::fixSceneDependencies()
293
{
294
    if (getViewProviderPage()) {
295
        getViewProviderPage()->fixSceneDependencies();
296
    }
297
}
298

299
//**** printing routines
300

301
/// MDIViewPage handles those aspects of printing that require user interaction, such
302
/// as file name selection and error messages
303
/// PagePrinter handles the actual printing mechanics.
304

305
/// overrides of MDIView print methods so that they print the QGraphicsScene instead
306
/// of the COIN3d scenegraph.
307
void MDIViewPage::printPdf()
308
{
309
//    Base::Console().Message("MDIVP::printPdf()\n");
310
    QStringList filter;
311
    filter << QObject::tr("PDF (*.pdf)");
312
    filter << QObject::tr("All Files (*.*)");
313
    QString fn =
314
        Gui::FileDialog::getSaveFileName(Gui::getMainWindow(), QObject::tr("Export Page As PDF"),
315
                                         QString(), filter.join(QLatin1String(";;")));
316
    if (fn.isEmpty()) {
317
        return;
318
    }
319

320
    Gui::WaitCursor wc;
321
    std::string utf8Content = fn.toUtf8().constData();
322
    if (m_pagePrinter) {
323
        m_pagePrinter->printPdf(utf8Content);
324
    }
325
}
326

327
void MDIViewPage::print()
328
{
329
//    Base::Console().Message("MDIVP::print()\n");
330

331
    if (!m_pagePrinter) {
332
        return;
333
    }
334
    m_pagePrinter->getPaperAttributes();
335

336
    QPrinter printer(QPrinter::HighResolution);
337
    printer.setFullPage(true);
338
    if (m_pagePrinter->getPaperSize() == QPageSize::Custom) {
339
        printer.setPageSize(QPageSize(QSizeF(m_pagePrinter->getPageWidth(), m_pagePrinter->getPageHeight()), QPageSize::Millimeter));
340
    }
341
    else {
342
        printer.setPageSize(QPageSize(m_pagePrinter->getPaperSize()));
343
    }
344
    printer.setPageOrientation(m_pagePrinter->getOrientation());
345

346
    QPrintDialog dlg(&printer, this);
347
    if (dlg.exec() == QDialog::Accepted) {
348
        print(&printer);
349
    }
350
}
351

352
void MDIViewPage::printPreview()
353
{
354
//    Base::Console().Message("MDIVP::printPreview()\n");
355

356
    if (!m_pagePrinter) {
357
        return;
358
    }
359
    m_pagePrinter->getPaperAttributes();
360

361
    QPrinter printer(QPrinter::HighResolution);
362
    printer.setFullPage(true);
363
    if (m_pagePrinter->getPaperSize() == QPageSize::Custom) {
364
        printer.setPageSize(QPageSize(QSizeF(m_pagePrinter->getPageWidth(), m_pagePrinter->getPageHeight()), QPageSize::Millimeter));
365
    }
366
    else {
367
        printer.setPageSize(QPageSize(m_pagePrinter->getPaperSize()));
368
    }
369
    printer.setPageOrientation(m_pagePrinter->getOrientation());
370

371
    QPrintPreviewDialog dlg(&printer, this);
372
    connect(&dlg, &QPrintPreviewDialog::paintRequested, this, qOverload<QPrinter*>(&MDIViewPage::print));
373
    dlg.exec();
374
}
375

376

377
void MDIViewPage::print(QPrinter* printer)
378
{
379
//    Base::Console().Message("MDIVP::print(printer)\n");
380
    if (!m_pagePrinter) {
381
        return;
382
    }
383
    m_pagePrinter->getPaperAttributes();
384
    // As size of the render area paperRect() should be used. When performing a real
385
    // print pageRect() may also work but the output is cropped at the bottom part.
386
    // So, independent whether pageRect() or paperRect() is used there is no scaling effect.
387
    // However, when using a different paper size as set in the drawing template (e.g.
388
    // DIN A5 instead of DIN A4) then the output is scaled.
389
    //
390
    // When creating a PDF file there seems to be no difference between pageRect() and
391
    // paperRect().
392
    //
393
    // When showing the preview of a print paperRect() must be used because with pageRect()
394
    // a certain scaling effect can be observed and the content becomes smaller.
395
    QPaintEngine::Type paintType = printer->paintEngine()->type();
396
    if (printer->outputFormat() == QPrinter::NativeFormat) {
397
        QPageSize::PageSizeId psPrtSetting = printer->pageLayout().pageSize().id();
398

399
        // for the preview a 'Picture' paint engine is used which we don't
400
        // care if it uses wrong printer settings
401
        bool doPrint = paintType != QPaintEngine::Picture;
402

403
        if (doPrint && printer->pageLayout().orientation() != m_pagePrinter->getOrientation()) {
404
            int ret = QMessageBox::warning(
405
                this, tr("Different orientation"),
406
                tr("The printer uses a different orientation  than the drawing.\n"
407
                   "Do you want to continue?"),
408
                QMessageBox::Yes | QMessageBox::No);
409
            if (ret != QMessageBox::Yes) {
410
                return;
411
            }
412
        }
413
        if (doPrint && psPrtSetting != m_pagePrinter->getPaperSize()) {
414
            int ret = QMessageBox::warning(
415
                this, tr("Different paper size"),
416
                tr("The printer uses a different paper size than the drawing.\n"
417
                   "Do you want to continue?"),
418
                QMessageBox::Yes | QMessageBox::No);
419
            if (ret != QMessageBox::Yes) {
420
                return;
421
            }
422
        }
423
    }
424

425
    QPainter p(printer);
426
    // why use a QPainter to determine if we can write to a file?
427
    if (!p.isActive() && !printer->outputFileName().isEmpty()) {
428
        qApp->setOverrideCursor(Qt::ArrowCursor);
429
        QMessageBox::critical(
430
            this, tr("Opening file failed"),
431
            tr("Can not open file %1 for writing.").arg(printer->outputFileName()));
432
        qApp->restoreOverrideCursor();
433
        return;
434
    }
435
    // free the printer from the painter
436
    p.end();
437

438
    if (m_pagePrinter) {
439
        m_pagePrinter->print(printer);
440
    }
441

442
}
443

444
//static routine to print all pages in a document
445
void MDIViewPage::printAll(QPrinter* printer, App::Document* doc)
446
{
447
//    Base::Console().Message("MDIVP::printAll()\n");
448
    PagePrinter::printAll(printer, doc);
449
}
450

451
PyObject* MDIViewPage::getPyObject()
452
{
453
    if (!pythonObject) {
454
        pythonObject = new MDIViewPagePy(this);
455
    }
456

457
    Py_INCREF(pythonObject);
458
    return pythonObject;
459
}
460

461
void MDIViewPage::contextMenuEvent(QContextMenuEvent* event)
462
{
463
    //    Base::Console().Message("MDIVP::contextMenuEvent() - reason: %d\n", event->reason());
464
    QMenu menu;
465
    menu.addAction(m_toggleFrameAction);
466
    menu.addAction(m_toggleKeepUpdatedAction);
467
    menu.addAction(m_exportSVGAction);
468
    menu.addAction(m_exportDXFAction);
469
    menu.addAction(m_exportPDFAction);
470
    menu.addAction(m_printAllAction);
471
    menu.exec(event->globalPos());
472
}
473

474
void MDIViewPage::toggleFrame() { m_vpPage->toggleFrameState(); }
475

476
void MDIViewPage::toggleKeepUpdated()
477
{
478
    bool state = m_vpPage->getDrawPage()->KeepUpdated.getValue();
479
    m_vpPage->getDrawPage()->KeepUpdated.setValue(!state);
480
}
481

482
void MDIViewPage::viewAll()
483
{
484
    m_vpPage->getQGVPage()->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
485
}
486

487
void MDIViewPage::saveSVG(std::string filename)
488
{
489
    if (m_pagePrinter) {
490
        m_pagePrinter->saveSVG(filename);
491
    }
492
}
493
void MDIViewPage::saveSVG()
494
{
495
    QStringList filter;
496
    filter << QObject::tr("SVG (*.svg)");
497
    filter << QObject::tr("All Files (*.*)");
498
    QString fn =
499
        Gui::FileDialog::getSaveFileName(Gui::getMainWindow(), QObject::tr("Export page as SVG"),
500
                                         QString(), filter.join(QLatin1String(";;")));
501
    if (fn.isEmpty()) {
502
        return;
503
    }
504
    static_cast<void>(blockSelection(true));// avoid to be notified by itself
505
    saveSVG(Base::Tools::toStdString(fn));
506
    static_cast<void>(blockSelection(false));
507
}
508

509
void MDIViewPage::saveDXF(std::string filename)
510
{
511
    if (m_pagePrinter) {
512
        m_pagePrinter->saveDXF(filename);
513
    }
514
}
515

516
void MDIViewPage::saveDXF()
517
{
518
    QString defaultDir;
519
    QString fileName = Gui::FileDialog::getSaveFileName(
520
        Gui::getMainWindow(), QString::fromUtf8(QT_TR_NOOP("Save DXF file")), defaultDir,
521
        QString::fromUtf8(QT_TR_NOOP("DXF (*.dxf)")));
522
    if (fileName.isEmpty()) {
523
        return;
524
    }
525

526
    std::string sFileName = fileName.toUtf8().constData();
527
    saveDXF(sFileName);
528
}
529

530
void MDIViewPage::savePDF(std::string filename)
531
{
532
    if (m_pagePrinter) {
533
        m_pagePrinter->savePDF(filename);
534
    }
535
}
536

537
void MDIViewPage::savePDF()
538
{
539
    QString defaultDir;
540
    QString fileName = Gui::FileDialog::getSaveFileName(
541
        Gui::getMainWindow(), QString::fromUtf8(QT_TR_NOOP("Save PDF file")), defaultDir,
542
        QString::fromUtf8(QT_TR_NOOP("PDF (*.pdf)")));
543
    if (fileName.isEmpty()) {
544
        return;
545
    }
546

547
    std::string sFileName = fileName.toUtf8().constData();
548
    savePDF(sFileName);
549
}
550

551
/// a slot for printing all the pages
552
void MDIViewPage::printAll()
553
{
554
    MDIViewPage::printAllPages();
555
}
556

557
//static routine for PrintAll command
558
/// prints all the pages in the active document
559
void MDIViewPage::printAllPages()
560
{
561
    QPrinter printer(QPrinter::HighResolution);
562
    printer.setFullPage(true);
563

564
    QPrintDialog dlg(&printer, Gui::getMainWindow());
565
    if (dlg.exec() == QDialog::Accepted) {
566
        App::Document* doc = App::GetApplication().getActiveDocument();
567
        if (!doc) {
568
            return;
569
        }
570
        if (printer.outputFileName().isEmpty()) {
571
            PagePrinter::printAll(&printer, doc);
572
        }
573
        else {
574
            PagePrinter::printAllPdf(&printer, doc);
575
        }
576
    }
577
}
578

579
/////////////// Selection Routines ///////////////////
580
// wf: this is never executed???
581
// needs a signal from Scene? hoverEvent?  Scene does not emit signal for "preselect"
582
// there is no "preSelect" signal from Gui either.
583
void MDIViewPage::preSelectionChanged(const QPoint& pos)
584
{
585
    QObject* obj = QObject::sender();
586

587
    if (!obj) {
588
        return;
589
    }
590

591
    auto view(dynamic_cast<QGIView*>(obj));
592
    if (!view) {
593
        return;
594
    }
595

596
    QGraphicsItem* parent = view->parentItem();
597
    if (!parent) {
598
        return;
599
    }
600

601
    TechDraw::DrawView* viewObj = view->getViewObject();
602
    std::stringstream ss;
603

604
    QGIFace* face = dynamic_cast<QGIFace*>(obj);
605
    QGIEdge* edge = dynamic_cast<QGIEdge*>(obj);
606
    QGIVertex* vert = dynamic_cast<QGIVertex*>(obj);
607
    if (edge) {
608
        ss << "Edge" << edge->getProjIndex();
609
        //bool accepted =
610
        static_cast<void>(Gui::Selection().setPreselect(viewObj->getDocument()->getName(),
611
                                                        viewObj->getNameInDocument(),
612
                                                        ss.str().c_str(), pos.x(), pos.y(), 0));
613
    }
614
    else if (vert) {
615
        ss << "Vertex" << vert->getProjIndex();
616
        //bool accepted =
617
        static_cast<void>(Gui::Selection().setPreselect(viewObj->getDocument()->getName(),
618
                                                        viewObj->getNameInDocument(),
619
                                                        ss.str().c_str(), pos.x(), pos.y(), 0));
620
    }
621
    else if (face) {
622
        ss << "Face"
623
           << face->getProjIndex();//TODO: SectionFaces have ProjIndex = -1. (but aren't selectable?) Problem?
624
        //bool accepted =
625
        static_cast<void>(Gui::Selection().setPreselect(viewObj->getDocument()->getName(),
626
                                                        viewObj->getNameInDocument(),
627
                                                        ss.str().c_str(), pos.x(), pos.y(), 0));
628
    }
629
    else {
630
        ss << "";
631
        Gui::Selection().setPreselect(viewObj->getDocument()->getName(),
632
                                      viewObj->getNameInDocument(), ss.str().c_str(), pos.x(),
633
                                      pos.y(), 0);
634
    }
635
}
636

637
//flag to prevent selection activity within mdivp
638
void MDIViewPage::blockSceneSelection(const bool isBlocked) { isSelectionBlocked = isBlocked; }
639

640

641
//Set all QGIViews to unselected state
642
void MDIViewPage::clearSceneSelection()
643
{
644
    //    Base::Console().Message("MDIVP::clearSceneSelection()\n");
645
    m_qgSceneSelected.clear();
646

647
    std::vector<QGIView*> views = m_scene->getViews();
648

649
    // Iterate through all views and unselect all
650
    for (std::vector<QGIView*>::iterator it = views.begin(); it != views.end(); ++it) {
651
        QGIView* item = *it;
652
        if (item->getGroupSelection()) {
653
            item->setGroupSelection(false);
654
            item->updateView();
655
        }
656
    }
657
}
658

659
//!Update QGIView's selection state based on Selection made outside Drawing Interface
660
void MDIViewPage::selectQGIView(App::DocumentObject *obj, bool isSelected,
661
                                const std::vector<std::string> &subNames)
662
{
663
    QGIView* view = m_scene->findQViewForDocObj(obj);
664
    if (view) {
665
        view->setGroupSelection(isSelected, subNames);
666
        view->updateView();
667
    }
668
}
669

670
//! invoked by selection change made in Tree via father MDIView
671
//really "onTreeSelectionChanged"
672
void MDIViewPage::onSelectionChanged(const Gui::SelectionChanges& msg)
673
{
674
    blockSceneSelection(true);
675

676
    if (msg.Type == Gui::SelectionChanges::ClrSelection || msg.Type == Gui::SelectionChanges::SetSelection) {
677
        clearSceneSelection();
678

679
        if (msg.Type == Gui::SelectionChanges::SetSelection) {
680
            std::vector<Gui::SelectionObject> selObjs = Gui::Selection().getSelectionEx(msg.pDocName);
681
            for (auto &so : selObjs) {
682
                App::DocumentObject *docObj = so.getObject();
683
                if (docObj->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
684
                    selectQGIView(docObj, true, so.getSubNames());
685
                }
686
            }
687
        }
688
    }
689
    else if (msg.Type == Gui::SelectionChanges::AddSelection || msg.Type == Gui::SelectionChanges::RmvSelection) {
690
        App::DocumentObject *docObj = msg.Object.getSubObject();
691
        if (docObj->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
692
            bool isSelected = msg.Type != Gui::SelectionChanges::RmvSelection;
693
            selectQGIView(docObj, isSelected, std::vector(1, std::string(msg.pSubName ? msg.pSubName : "")));
694
        }
695
    }
696

697
    blockSceneSelection(false);
698
}
699

700
//! maintain QGScene selected items in selection order
701
void MDIViewPage::sceneSelectionManager()
702
{
703
    //    Base::Console().Message("MDIVP::sceneSelectionManager()\n");
704
    QList<QGraphicsItem*> sceneSel = m_scene->selectedItems();
705

706
    if (sceneSel.isEmpty()) {
707
        m_qgSceneSelected.clear();//TODO: need to signal somebody?  Tree? handled elsewhere
708
        //clearSelection
709
        return;
710
    }
711

712
    if (m_qgSceneSelected.isEmpty() && !sceneSel.isEmpty()) {
713
        m_qgSceneSelected.push_back(sceneSel.front());
714
        return;
715
    }
716

717
    //add to m_qgSceneSelected anything that is in q_sceneSel
718
    for (auto qts : sceneSel) {
719
        bool found = false;
720
        for (auto ms : qAsConst(m_qgSceneSelected)) {
721
            if (qts == ms) {
722
                found = true;
723
                break;
724
            }
725
        }
726
        if (!found) {
727
            m_qgSceneSelected.push_back(qts);
728
            break;
729
        }
730
    }
731

732
    //remove items from m_qgSceneSelected that are not in q_sceneSel
733
    QList<QGraphicsItem*> m_new;
734
    for (auto m : qAsConst(m_qgSceneSelected)) {
735
        for (auto q : sceneSel) {
736
            if (m == q) {
737
                m_new.push_back(m);
738
                break;
739
            }
740
        }
741
    }
742
    m_qgSceneSelected = m_new;
743
}
744

745
//! update Tree Selection from QGraphicsScene selection
746
//triggered by m_scene signal
747
void MDIViewPage::sceneSelectionChanged()
748
{
749
    sceneSelectionManager();
750

751
    if (isSelectionBlocked) {
752
        return;
753
    }
754

755
    std::vector<Gui::SelectionObject> treeSel = Gui::Selection().getSelectionEx();
756
    QList<QGraphicsItem*> sceneSel = m_qgSceneSelected;
757

758
    //check if really need to change selection
759
    bool sameSel = compareSelections(treeSel, sceneSel);
760
    if (sameSel) {
761
        return;
762
    }
763

764
    setTreeToSceneSelect();
765
}
766

767
//Note: Qt says: "no guarantee of selection order"!!!
768
void MDIViewPage::setTreeToSceneSelect()
769
{
770
    //    Base::Console().Message("MDIVP::setTreeToSceneSelect()\n");
771
    bool saveBlock = blockSelection(true);// block selectionChanged signal from Tree/Observer
772
    blockSceneSelection(true);
773
    Gui::Selection().clearSelection();
774
    QList<QGraphicsItem*> sceneSel = m_qgSceneSelected;
775
    for (QList<QGraphicsItem*>::iterator it = sceneSel.begin(); it != sceneSel.end(); ++it) {
776
        QGIView* itemView = dynamic_cast<QGIView*>(*it);
777
        if (!itemView) {
778
            QGIEdge* edge = dynamic_cast<QGIEdge*>(*it);
779
            if (edge) {
780
                QGraphicsItem* parent = edge->parentItem();
781
                if (!parent) {
782
                    continue;
783
                }
784

785
                QGIView* viewItem = dynamic_cast<QGIView*>(parent);
786
                if (!viewItem) {
787
                    continue;
788
                }
789

790
                TechDraw::DrawView* viewObj = viewItem->getViewObject();
791

792
                std::stringstream ss;
793
                ss << "Edge" << edge->getProjIndex();
794
                //bool accepted =
795
                static_cast<void>(Gui::Selection().addSelection(viewObj->getDocument()->getName(),
796
                                                                viewObj->getNameInDocument(),
797
                                                                ss.str().c_str()));
798
                showStatusMsg(viewObj->getDocument()->getName(), viewObj->getNameInDocument(),
799
                              ss.str().c_str());
800
                continue;
801
            }
802

803
            QGIVertex* vert = dynamic_cast<QGIVertex*>(*it);
804
            if (vert) {
805
                QGraphicsItem* parent = vert->parentItem();
806
                if (!parent) {
807
                    continue;
808
                }
809

810
                QGIView* viewItem = dynamic_cast<QGIView*>(parent);
811
                if (!viewItem) {
812
                    continue;
813
                }
814

815
                TechDraw::DrawView* viewObj = viewItem->getViewObject();
816

817
                std::stringstream ss;
818
                ss << "Vertex" << vert->getProjIndex();
819
                //bool accepted =
820
                static_cast<void>(Gui::Selection().addSelection(viewObj->getDocument()->getName(),
821
                                                                viewObj->getNameInDocument(),
822
                                                                ss.str().c_str()));
823
                showStatusMsg(viewObj->getDocument()->getName(), viewObj->getNameInDocument(),
824
                              ss.str().c_str());
825
                continue;
826
            }
827

828
            QGIFace* face = dynamic_cast<QGIFace*>(*it);
829
            if (face) {
830
                QGraphicsItem* parent = face->parentItem();
831
                if (!parent) {
832
                    continue;
833
                }
834

835
                QGIView* viewItem = dynamic_cast<QGIView*>(parent);
836
                if (!viewItem) {
837
                    continue;
838
                }
839

840
                TechDraw::DrawView* viewObj = viewItem->getViewObject();
841

842
                std::stringstream ss;
843
                ss << "Face" << face->getProjIndex();
844
                //bool accepted =
845
                static_cast<void>(Gui::Selection().addSelection(viewObj->getDocument()->getName(),
846
                                                                viewObj->getNameInDocument(),
847
                                                                ss.str().c_str()));
848
                showStatusMsg(viewObj->getDocument()->getName(), viewObj->getNameInDocument(),
849
                              ss.str().c_str());
850
                continue;
851
            }
852

853
            QGIDatumLabel* dimLabel = dynamic_cast<QGIDatumLabel*>(*it);
854
            if (dimLabel) {
855
                QGraphicsItem* dimParent = dimLabel->QGraphicsItem::parentItem();
856
                if (!dimParent) {
857
                    continue;
858
                }
859

860
                QGIView* dimItem = dynamic_cast<QGIView*>(dimParent);
861

862
                if (!dimItem) {
863
                    continue;
864
                }
865

866
                TechDraw::DrawView* dimObj = dimItem->getViewObject();
867
                if (!dimObj) {
868
                    continue;
869
                }
870
                const char* name = dimObj->getNameInDocument();
871
                if (!name) {//can happen during undo/redo if Dim is selected???
872
                    //Base::Console().Log("INFO - MDIVP::sceneSelectionChanged - dimObj name is null!\n");
873
                    continue;
874
                }
875

876
                //bool accepted =
877
                static_cast<void>(Gui::Selection().addSelection(dimObj->getDocument()->getName(),
878
                                                                dimObj->getNameInDocument()));
879
            }
880

881
            QGMText* mText = dynamic_cast<QGMText*>(*it);
882
            if (mText) {
883
                QGraphicsItem* textParent = mText->QGraphicsItem::parentItem();
884
                if (!textParent) {
885
                    continue;
886
                }
887

888
                QGIView* parent = dynamic_cast<QGIView*>(textParent);
889

890
                if (!parent) {
891
                    continue;
892
                }
893

894
                TechDraw::DrawView* parentFeat = parent->getViewObject();
895
                if (!parentFeat) {
896
                    continue;
897
                }
898
                const char* name = parentFeat->getNameInDocument();
899
                if (!name) {//can happen during undo/redo if Dim is selected???
900
                    continue;
901
                }
902

903
                //bool accepted =
904
                static_cast<void>(Gui::Selection().addSelection(
905
                    parentFeat->getDocument()->getName(), parentFeat->getNameInDocument()));
906
            }
907
        }
908
        else {
909

910
            TechDraw::DrawView* viewObj = itemView->getViewObject();
911
            if (viewObj && !viewObj->isRemoving()) {
912
                std::string doc_name = viewObj->getDocument()->getName();
913
                std::string obj_name = viewObj->getNameInDocument();
914

915
                Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str());
916
                showStatusMsg(doc_name.c_str(), obj_name.c_str(), "");
917
            }
918
        }
919
    }
920

921
    blockSceneSelection(false);
922
    blockSelection(saveBlock);
923
}
924

925
bool MDIViewPage::compareSelections(std::vector<Gui::SelectionObject> treeSel,
926
                                    QList<QGraphicsItem*> sceneSel)
927
{
928
    bool result = true;
929

930
    if (treeSel.empty() && sceneSel.empty()) {
931
        return true;
932
    }
933
    else if (treeSel.empty() && !sceneSel.empty()) {
934
        return false;
935
    }
936
    else if (!treeSel.empty() && sceneSel.empty()) {
937
        return false;
938
    }
939

940
    int treeCount = 0;
941
    int subCount = 0;
942
    int sceneCount = 0;
943
    int ppCount = 0;
944

945
    std::vector<std::string> treeNames;
946
    std::vector<std::string> sceneNames;
947

948
    for (auto tn : treeSel) {
949
        if (tn.getObject()->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
950
            std::string s = tn.getObject()->getNameInDocument();
951
            treeNames.push_back(s);
952
            subCount += tn.getSubNames().size();
953
        }
954
    }
955
    std::sort(treeNames.begin(), treeNames.end());
956
    treeCount = treeNames.size();
957

958
    for (auto sn : sceneSel) {
959
        QGIView* itemView = dynamic_cast<QGIView*>(sn);
960
        if (!itemView) {
961
            QGIDatumLabel* dl = dynamic_cast<QGIDatumLabel*>(sn);
962
            QGIPrimPath* pp = dynamic_cast<QGIPrimPath*>(sn);//count Vertex/Edge/Face
963
            if (pp) {
964
                ppCount++;
965
            }
966
            else if (dl) {
967
                //get dim associated with this label
968
                QGraphicsItem* qgi = dl->parentItem();
969
                if (qgi) {
970
                    QGIViewDimension* vd = dynamic_cast<QGIViewDimension*>(qgi);
971
                    if (vd) {
972
                        std::string s = vd->getViewNameAsString();
973
                        sceneNames.push_back(s);
974
                    }
975
                }
976
            }
977
        }
978
        else {
979
            std::string s = itemView->getViewNameAsString();
980
            sceneNames.push_back(s);
981
        }
982
    }
983
    std::sort(sceneNames.begin(), sceneNames.end());
984
    sceneCount = sceneNames.size();
985

986
    //different # of DrawView* vs QGIV*
987
    if (sceneCount != treeCount) {
988
        return false;
989
    }
990

991
    // even of counts match, have to check that names in scene == names in tree
992
    auto treePtr = treeNames.begin();
993
    for (auto& s : sceneNames) {
994
        if (s == (*treePtr)) {
995
            treePtr++;
996
            continue;
997
        }
998
        else {
999
            return false;
1000
        }
1001
    }
1002

1003
    //Objects all match, check subs
1004
    if (subCount != ppCount) {
1005
        return false;
1006
    }
1007

1008
    return result;
1009
}
1010

1011
///////////////////end Selection Routines //////////////////////
1012

1013
void MDIViewPage::showStatusMsg(const char* string1, const char* string2, const char* string3) const
1014
{
1015
    QString msg = QString::fromLatin1("%1 %2.%3.%4 ")
1016
                      .arg(tr("Selected:"), QString::fromUtf8(string1), QString::fromUtf8(string2),
1017
                           QString::fromUtf8(string3));
1018
    if (Gui::getMainWindow()) {
1019
        Gui::getMainWindow()->showMessage(msg, 6000);
1020
    }
1021
}
1022

1023
// ----------------------------------------------------------------------------
1024

1025
void MDIViewPagePy::init_type()
1026
{
1027
    behaviors().name("MDIViewPagePy");
1028
    behaviors().doc("Python binding class for the MDI view page class");
1029
    // you must have overwritten the virtual functions
1030
    behaviors().supportRepr();
1031
    behaviors().supportGetattr();
1032
    behaviors().supportSetattr();
1033

1034
    add_varargs_method("getPage", &MDIViewPagePy::getPage,
1035
                       "getPage() returns the page being displayed");
1036
    add_varargs_method("cast_to_base", &MDIViewPagePy::cast_to_base,
1037
                       "cast_to_base() cast to MDIView class");
1038
    behaviors().readyType();
1039
}
1040

1041
MDIViewPagePy::MDIViewPagePy(MDIViewPage* mdi) : base(mdi) {}
1042

1043
MDIViewPagePy::~MDIViewPagePy() {}
1044

1045
Py::Object MDIViewPagePy::repr()
1046
{
1047
    std::ostringstream s_out;
1048
    if (!getMDIViewPagePtr()) {
1049
        throw Py::RuntimeError("Cannot print representation of deleted object");
1050
    }
1051
    s_out << "MDI view page";
1052
    return Py::String(s_out.str());
1053
}
1054

1055
// Since with PyCXX it is not possible to make a sub-class of MDIViewPy
1056
// a trick is to use MDIViewPy as class member and override getattr() to
1057
// join the attributes of both classes. This way all methods of MDIViewPy
1058
// appear for SheetViewPy, too.
1059
Py::Object MDIViewPagePy::getattr(const char* attrName)
1060
{
1061
    if (!getMDIViewPagePtr()) {
1062
        std::ostringstream s_out;
1063
        s_out << "Cannot access attribute '" << attrName << "' of deleted object";
1064
        throw Py::RuntimeError(s_out.str());
1065
    }
1066
    std::string name(attrName);
1067
    if (name == "__dict__" || name == "__class__") {
1068
        Py::Dict dict_self(BaseType::getattr("__dict__"));
1069
        Py::Dict dict_base(base.getattr("__dict__"));
1070
        for (const auto& it : dict_base) {
1071
            dict_self.setItem(it.first, it.second);
1072
        }
1073
        return dict_self;
1074
    }
1075

1076
    try {
1077
        return BaseType::getattr(attrName);
1078
    }
1079
    catch (Py::AttributeError& e) {
1080
        e.clear();
1081
        return base.getattr(attrName);
1082
    }
1083
}
1084

1085
MDIViewPage* MDIViewPagePy::getMDIViewPagePtr()
1086
{
1087
    return qobject_cast<MDIViewPage*>(base.getMDIViewPtr());
1088
}
1089

1090
Py::Object MDIViewPagePy::getPage(const Py::Tuple& args)
1091
{
1092
    if (!PyArg_ParseTuple(args.ptr(), "")) {
1093
        throw Py::Exception();
1094
    }
1095
    return Py::asObject(new TechDraw::DrawPagePy(getMDIViewPagePtr()->getPage()));
1096
}
1097

1098
Py::Object MDIViewPagePy::cast_to_base(const Py::Tuple&)
1099
{
1100
    return Gui::MDIViewPy::create(base.getMDIViewPtr());
1101
}
1102

1103
#include <Mod/TechDraw/Gui/moc_MDIViewPage.cpp>
1104

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

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

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

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