1
/***************************************************************************
2
* Copyright (c) 2007 Jürgen Riegel <juergen.riegel@web.de> *
3
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
5
* This file is part of the FreeCAD CAx development system. *
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. *
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. *
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 *
22
***************************************************************************/
24
#include "PreCompiled.h"
28
#include <QApplication>
29
#include <QContextMenuEvent>
34
#include <QPaintEngine>
37
#include <QPrintDialog>
38
#include <QPrintPreviewDialog>
40
#include <boost_signals2.hpp>
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>
65
#include "DrawGuiUtil.h"
66
#include "MDIViewPage.h"
69
#include "QGITemplate.h"
72
#include "QGIViewBalloon.h"
73
#include "QGIViewDimension.h"
78
#include "ViewProviderPage.h"
79
#include "PagePrinter.h"
81
using namespace TechDrawGui;
82
using namespace TechDraw;
83
namespace sp = std::placeholders;
85
/* TRANSLATOR TechDrawGui::MDIViewPage */
87
TYPESYSTEM_SOURCE_ABSTRACT(TechDrawGui::MDIViewPage, Gui::MDIView)
89
MDIViewPage::MDIViewPage(ViewProviderPage* pageVp, Gui::Document* doc, QWidget* parent)
90
: Gui::MDIView(doc, parent), m_vpPage(pageVp)
92
setMouseTracking(true);
94
m_toggleKeepUpdatedAction = new QAction(tr("Toggle &Keep Updated"), this);
95
connect(m_toggleKeepUpdatedAction, &QAction::triggered, this, &MDIViewPage::toggleKeepUpdated);
97
m_toggleFrameAction = new QAction(tr("Toggle &Frames"), this);
98
connect(m_toggleFrameAction, &QAction::triggered, this, &MDIViewPage::toggleFrame);
100
m_exportSVGAction = new QAction(tr("&Export SVG"), this);
101
connect(m_exportSVGAction, &QAction::triggered, this, qOverload<>(&MDIViewPage::saveSVG));
103
m_exportDXFAction = new QAction(tr("Export DXF"), this);
104
connect(m_exportDXFAction, &QAction::triggered, this, qOverload<>(&MDIViewPage::saveDXF));
106
m_exportPDFAction = new QAction(tr("Export PDF"), this);
107
connect(m_exportPDFAction, &QAction::triggered, this, qOverload<>(&MDIViewPage::savePDF));
109
m_printAllAction = new QAction(tr("Print All Pages"), this);
110
connect(m_printAllAction, &QAction::triggered, this, qOverload<>(&MDIViewPage::printAllPages));
112
isSelectionBlocked = false;
114
QString tabText = QString::fromUtf8(pageVp->getDrawPage()->getNameInDocument());
115
tabText += QString::fromUtf8("[*]");
116
setWindowTitle(tabText);
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);
125
m_pagePrinter = new PagePrinter(m_vpPage);
126
m_pagePrinter->setOwner(this);
129
MDIViewPage::~MDIViewPage()
131
connectDeletedObject.disconnect();
132
delete m_pagePrinter;
135
void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget)
138
setCentralWidget(viewWidget);//this makes viewWidget a Qt child of MDIViewPage
139
QObject::connect(scene, &QGSPage::selectionChanged, this, &MDIViewPage::sceneSelectionChanged);
141
m_pagePrinter->setScene(m_scene);
145
void MDIViewPage::setDocumentObject(const std::string& name)
148
setObjectName(Base::Tools::fromStdString(name));
151
void MDIViewPage::setDocumentName(const std::string& name) { m_documentName = name; }
153
void MDIViewPage::closeEvent(QCloseEvent* event)
155
// Base::Console().Message("MDIVP::closeEvent()\n");
156
MDIView::closeEvent(event);
157
if (!event->isAccepted()) {
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();
167
App::DocumentObject* obj = doc->getObject(m_objectName.c_str());
168
Gui::ViewProvider* vp = _pcDocument->getViewProvider(obj);
174
blockSceneSelection(false);
177
void MDIViewPage::onDeleteObject(const App::DocumentObject& obj)
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());
184
blockSceneSelection(false);
187
bool MDIViewPage::onMsg(const char* pMsg, const char**)
189
Gui::Document* doc(getGuiDocument());
194
else if (strcmp("ViewFit", pMsg) == 0) {
198
else if (strcmp("Save", pMsg) == 0) {
202
else if (strcmp("SaveAs", pMsg) == 0) {
206
else if (strcmp("Undo", pMsg) == 0) {
208
Gui::Command::updateActive();
209
fixSceneDependencies(); // check QGraphicsScene item parenting
212
else if (strcmp("Redo", pMsg) == 0) {
214
Gui::Command::updateActive();
217
else if (strcmp("ZoomIn", pMsg) == 0) {
221
else if (strcmp("ZoomOut", pMsg) == 0) {
229
bool MDIViewPage::onHasMsg(const char* pMsg) const
231
if (strcmp("ViewFit", pMsg) == 0) {
234
else if (strcmp("CanPan",pMsg) == 0) {
237
else if (strcmp("Redo", pMsg) == 0 && getAppDocument()->getAvailableRedos() > 0) {
240
else if (strcmp("Undo", pMsg) == 0 && getAppDocument()->getAvailableUndos() > 0) {
243
else if (strcmp("Print", pMsg) == 0) {
246
else if (strcmp("Save", pMsg) == 0) {
249
else if (strcmp("SaveAs", pMsg) == 0) {
252
else if (strcmp("PrintPreview", pMsg) == 0) {
255
else if (strcmp("PrintPdf", pMsg) == 0) {
258
else if (strcmp("PrintAll", pMsg) == 0) {
261
else if (strcmp("ZoomIn", pMsg) == 0) {
264
else if (strcmp("ZoomOut", pMsg) == 0) {
270
// handle a zoomIn message from the menu
271
void MDIViewPage::zoomIn()
273
m_vpPage->getQGVPage()->zoomIn();
276
// handle a zoomOut message from the menu
277
void MDIViewPage::zoomOut()
279
m_vpPage->getQGVPage()->zoomOut();
282
// called by ViewProvider when Page feature Label changes
283
void MDIViewPage::setTabText(std::string tabText)
285
if (!isPassive() && !tabText.empty()) {
286
QString cap = QString::fromLatin1("%1 [*]").arg(QString::fromUtf8(tabText.c_str()));
291
// advise the page to check QGraphicsScene parent/child relationships after undo
292
void MDIViewPage::fixSceneDependencies()
294
if (getViewProviderPage()) {
295
getViewProviderPage()->fixSceneDependencies();
299
//**** printing routines
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.
305
/// overrides of MDIView print methods so that they print the QGraphicsScene instead
306
/// of the COIN3d scenegraph.
307
void MDIViewPage::printPdf()
309
// Base::Console().Message("MDIVP::printPdf()\n");
311
filter << QObject::tr("PDF (*.pdf)");
312
filter << QObject::tr("All Files (*.*)");
314
Gui::FileDialog::getSaveFileName(Gui::getMainWindow(), QObject::tr("Export Page As PDF"),
315
QString(), filter.join(QLatin1String(";;")));
321
std::string utf8Content = fn.toUtf8().constData();
323
m_pagePrinter->printPdf(utf8Content);
327
void MDIViewPage::print()
329
// Base::Console().Message("MDIVP::print()\n");
331
if (!m_pagePrinter) {
334
m_pagePrinter->getPaperAttributes();
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));
342
printer.setPageSize(QPageSize(m_pagePrinter->getPaperSize()));
344
printer.setPageOrientation(m_pagePrinter->getOrientation());
346
QPrintDialog dlg(&printer, this);
347
if (dlg.exec() == QDialog::Accepted) {
352
void MDIViewPage::printPreview()
354
// Base::Console().Message("MDIVP::printPreview()\n");
356
if (!m_pagePrinter) {
359
m_pagePrinter->getPaperAttributes();
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));
367
printer.setPageSize(QPageSize(m_pagePrinter->getPaperSize()));
369
printer.setPageOrientation(m_pagePrinter->getOrientation());
371
QPrintPreviewDialog dlg(&printer, this);
372
connect(&dlg, &QPrintPreviewDialog::paintRequested, this, qOverload<QPrinter*>(&MDIViewPage::print));
377
void MDIViewPage::print(QPrinter* printer)
379
// Base::Console().Message("MDIVP::print(printer)\n");
380
if (!m_pagePrinter) {
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.
390
// When creating a PDF file there seems to be no difference between pageRect() and
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();
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;
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) {
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) {
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();
435
// free the printer from the painter
439
m_pagePrinter->print(printer);
444
//static routine to print all pages in a document
445
void MDIViewPage::printAll(QPrinter* printer, App::Document* doc)
447
// Base::Console().Message("MDIVP::printAll()\n");
448
PagePrinter::printAll(printer, doc);
451
PyObject* MDIViewPage::getPyObject()
454
pythonObject = new MDIViewPagePy(this);
457
Py_INCREF(pythonObject);
461
void MDIViewPage::contextMenuEvent(QContextMenuEvent* event)
463
// Base::Console().Message("MDIVP::contextMenuEvent() - reason: %d\n", event->reason());
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());
474
void MDIViewPage::toggleFrame() { m_vpPage->toggleFrameState(); }
476
void MDIViewPage::toggleKeepUpdated()
478
bool state = m_vpPage->getDrawPage()->KeepUpdated.getValue();
479
m_vpPage->getDrawPage()->KeepUpdated.setValue(!state);
482
void MDIViewPage::viewAll()
484
m_vpPage->getQGVPage()->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
487
void MDIViewPage::saveSVG(std::string filename)
490
m_pagePrinter->saveSVG(filename);
493
void MDIViewPage::saveSVG()
496
filter << QObject::tr("SVG (*.svg)");
497
filter << QObject::tr("All Files (*.*)");
499
Gui::FileDialog::getSaveFileName(Gui::getMainWindow(), QObject::tr("Export page as SVG"),
500
QString(), filter.join(QLatin1String(";;")));
504
static_cast<void>(blockSelection(true));// avoid to be notified by itself
505
saveSVG(Base::Tools::toStdString(fn));
506
static_cast<void>(blockSelection(false));
509
void MDIViewPage::saveDXF(std::string filename)
512
m_pagePrinter->saveDXF(filename);
516
void MDIViewPage::saveDXF()
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()) {
526
std::string sFileName = fileName.toUtf8().constData();
530
void MDIViewPage::savePDF(std::string filename)
533
m_pagePrinter->savePDF(filename);
537
void MDIViewPage::savePDF()
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()) {
547
std::string sFileName = fileName.toUtf8().constData();
551
/// a slot for printing all the pages
552
void MDIViewPage::printAll()
554
MDIViewPage::printAllPages();
557
//static routine for PrintAll command
558
/// prints all the pages in the active document
559
void MDIViewPage::printAllPages()
561
QPrinter printer(QPrinter::HighResolution);
562
printer.setFullPage(true);
564
QPrintDialog dlg(&printer, Gui::getMainWindow());
565
if (dlg.exec() == QDialog::Accepted) {
566
App::Document* doc = App::GetApplication().getActiveDocument();
570
if (printer.outputFileName().isEmpty()) {
571
PagePrinter::printAll(&printer, doc);
574
PagePrinter::printAllPdf(&printer, doc);
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)
585
QObject* obj = QObject::sender();
591
auto view(dynamic_cast<QGIView*>(obj));
596
QGraphicsItem* parent = view->parentItem();
601
TechDraw::DrawView* viewObj = view->getViewObject();
602
std::stringstream ss;
604
QGIFace* face = dynamic_cast<QGIFace*>(obj);
605
QGIEdge* edge = dynamic_cast<QGIEdge*>(obj);
606
QGIVertex* vert = dynamic_cast<QGIVertex*>(obj);
608
ss << "Edge" << edge->getProjIndex();
610
static_cast<void>(Gui::Selection().setPreselect(viewObj->getDocument()->getName(),
611
viewObj->getNameInDocument(),
612
ss.str().c_str(), pos.x(), pos.y(), 0));
615
ss << "Vertex" << vert->getProjIndex();
617
static_cast<void>(Gui::Selection().setPreselect(viewObj->getDocument()->getName(),
618
viewObj->getNameInDocument(),
619
ss.str().c_str(), pos.x(), pos.y(), 0));
623
<< face->getProjIndex();//TODO: SectionFaces have ProjIndex = -1. (but aren't selectable?) Problem?
625
static_cast<void>(Gui::Selection().setPreselect(viewObj->getDocument()->getName(),
626
viewObj->getNameInDocument(),
627
ss.str().c_str(), pos.x(), pos.y(), 0));
631
Gui::Selection().setPreselect(viewObj->getDocument()->getName(),
632
viewObj->getNameInDocument(), ss.str().c_str(), pos.x(),
637
//flag to prevent selection activity within mdivp
638
void MDIViewPage::blockSceneSelection(const bool isBlocked) { isSelectionBlocked = isBlocked; }
641
//Set all QGIViews to unselected state
642
void MDIViewPage::clearSceneSelection()
644
// Base::Console().Message("MDIVP::clearSceneSelection()\n");
645
m_qgSceneSelected.clear();
647
std::vector<QGIView*> views = m_scene->getViews();
649
// Iterate through all views and unselect all
650
for (std::vector<QGIView*>::iterator it = views.begin(); it != views.end(); ++it) {
652
if (item->getGroupSelection()) {
653
item->setGroupSelection(false);
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)
663
QGIView* view = m_scene->findQViewForDocObj(obj);
665
view->setGroupSelection(isSelected, subNames);
670
//! invoked by selection change made in Tree via father MDIView
671
//really "onTreeSelectionChanged"
672
void MDIViewPage::onSelectionChanged(const Gui::SelectionChanges& msg)
674
blockSceneSelection(true);
676
if (msg.Type == Gui::SelectionChanges::ClrSelection || msg.Type == Gui::SelectionChanges::SetSelection) {
677
clearSceneSelection();
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());
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 : "")));
697
blockSceneSelection(false);
700
//! maintain QGScene selected items in selection order
701
void MDIViewPage::sceneSelectionManager()
703
// Base::Console().Message("MDIVP::sceneSelectionManager()\n");
704
QList<QGraphicsItem*> sceneSel = m_scene->selectedItems();
706
if (sceneSel.isEmpty()) {
707
m_qgSceneSelected.clear();//TODO: need to signal somebody? Tree? handled elsewhere
712
if (m_qgSceneSelected.isEmpty() && !sceneSel.isEmpty()) {
713
m_qgSceneSelected.push_back(sceneSel.front());
717
//add to m_qgSceneSelected anything that is in q_sceneSel
718
for (auto qts : sceneSel) {
720
for (auto ms : qAsConst(m_qgSceneSelected)) {
727
m_qgSceneSelected.push_back(qts);
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) {
742
m_qgSceneSelected = m_new;
745
//! update Tree Selection from QGraphicsScene selection
746
//triggered by m_scene signal
747
void MDIViewPage::sceneSelectionChanged()
749
sceneSelectionManager();
751
if (isSelectionBlocked) {
755
std::vector<Gui::SelectionObject> treeSel = Gui::Selection().getSelectionEx();
756
QList<QGraphicsItem*> sceneSel = m_qgSceneSelected;
758
//check if really need to change selection
759
bool sameSel = compareSelections(treeSel, sceneSel);
764
setTreeToSceneSelect();
767
//Note: Qt says: "no guarantee of selection order"!!!
768
void MDIViewPage::setTreeToSceneSelect()
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);
778
QGIEdge* edge = dynamic_cast<QGIEdge*>(*it);
780
QGraphicsItem* parent = edge->parentItem();
785
QGIView* viewItem = dynamic_cast<QGIView*>(parent);
790
TechDraw::DrawView* viewObj = viewItem->getViewObject();
792
std::stringstream ss;
793
ss << "Edge" << edge->getProjIndex();
795
static_cast<void>(Gui::Selection().addSelection(viewObj->getDocument()->getName(),
796
viewObj->getNameInDocument(),
798
showStatusMsg(viewObj->getDocument()->getName(), viewObj->getNameInDocument(),
803
QGIVertex* vert = dynamic_cast<QGIVertex*>(*it);
805
QGraphicsItem* parent = vert->parentItem();
810
QGIView* viewItem = dynamic_cast<QGIView*>(parent);
815
TechDraw::DrawView* viewObj = viewItem->getViewObject();
817
std::stringstream ss;
818
ss << "Vertex" << vert->getProjIndex();
820
static_cast<void>(Gui::Selection().addSelection(viewObj->getDocument()->getName(),
821
viewObj->getNameInDocument(),
823
showStatusMsg(viewObj->getDocument()->getName(), viewObj->getNameInDocument(),
828
QGIFace* face = dynamic_cast<QGIFace*>(*it);
830
QGraphicsItem* parent = face->parentItem();
835
QGIView* viewItem = dynamic_cast<QGIView*>(parent);
840
TechDraw::DrawView* viewObj = viewItem->getViewObject();
842
std::stringstream ss;
843
ss << "Face" << face->getProjIndex();
845
static_cast<void>(Gui::Selection().addSelection(viewObj->getDocument()->getName(),
846
viewObj->getNameInDocument(),
848
showStatusMsg(viewObj->getDocument()->getName(), viewObj->getNameInDocument(),
853
QGIDatumLabel* dimLabel = dynamic_cast<QGIDatumLabel*>(*it);
855
QGraphicsItem* dimParent = dimLabel->QGraphicsItem::parentItem();
860
QGIView* dimItem = dynamic_cast<QGIView*>(dimParent);
866
TechDraw::DrawView* dimObj = dimItem->getViewObject();
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");
877
static_cast<void>(Gui::Selection().addSelection(dimObj->getDocument()->getName(),
878
dimObj->getNameInDocument()));
881
QGMText* mText = dynamic_cast<QGMText*>(*it);
883
QGraphicsItem* textParent = mText->QGraphicsItem::parentItem();
888
QGIView* parent = dynamic_cast<QGIView*>(textParent);
894
TechDraw::DrawView* parentFeat = parent->getViewObject();
898
const char* name = parentFeat->getNameInDocument();
899
if (!name) {//can happen during undo/redo if Dim is selected???
904
static_cast<void>(Gui::Selection().addSelection(
905
parentFeat->getDocument()->getName(), parentFeat->getNameInDocument()));
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();
915
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str());
916
showStatusMsg(doc_name.c_str(), obj_name.c_str(), "");
921
blockSceneSelection(false);
922
blockSelection(saveBlock);
925
bool MDIViewPage::compareSelections(std::vector<Gui::SelectionObject> treeSel,
926
QList<QGraphicsItem*> sceneSel)
930
if (treeSel.empty() && sceneSel.empty()) {
933
else if (treeSel.empty() && !sceneSel.empty()) {
936
else if (!treeSel.empty() && sceneSel.empty()) {
945
std::vector<std::string> treeNames;
946
std::vector<std::string> sceneNames;
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();
955
std::sort(treeNames.begin(), treeNames.end());
956
treeCount = treeNames.size();
958
for (auto sn : sceneSel) {
959
QGIView* itemView = dynamic_cast<QGIView*>(sn);
961
QGIDatumLabel* dl = dynamic_cast<QGIDatumLabel*>(sn);
962
QGIPrimPath* pp = dynamic_cast<QGIPrimPath*>(sn);//count Vertex/Edge/Face
967
//get dim associated with this label
968
QGraphicsItem* qgi = dl->parentItem();
970
QGIViewDimension* vd = dynamic_cast<QGIViewDimension*>(qgi);
972
std::string s = vd->getViewNameAsString();
973
sceneNames.push_back(s);
979
std::string s = itemView->getViewNameAsString();
980
sceneNames.push_back(s);
983
std::sort(sceneNames.begin(), sceneNames.end());
984
sceneCount = sceneNames.size();
986
//different # of DrawView* vs QGIV*
987
if (sceneCount != treeCount) {
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)) {
1003
//Objects all match, check subs
1004
if (subCount != ppCount) {
1011
///////////////////end Selection Routines //////////////////////
1013
void MDIViewPage::showStatusMsg(const char* string1, const char* string2, const char* string3) const
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);
1023
// ----------------------------------------------------------------------------
1025
void MDIViewPagePy::init_type()
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();
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();
1041
MDIViewPagePy::MDIViewPagePy(MDIViewPage* mdi) : base(mdi) {}
1043
MDIViewPagePy::~MDIViewPagePy() {}
1045
Py::Object MDIViewPagePy::repr()
1047
std::ostringstream s_out;
1048
if (!getMDIViewPagePtr()) {
1049
throw Py::RuntimeError("Cannot print representation of deleted object");
1051
s_out << "MDI view page";
1052
return Py::String(s_out.str());
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)
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());
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);
1077
return BaseType::getattr(attrName);
1079
catch (Py::AttributeError& e) {
1081
return base.getattr(attrName);
1085
MDIViewPage* MDIViewPagePy::getMDIViewPagePtr()
1087
return qobject_cast<MDIViewPage*>(base.getMDIViewPtr());
1090
Py::Object MDIViewPagePy::getPage(const Py::Tuple& args)
1092
if (!PyArg_ParseTuple(args.ptr(), "")) {
1093
throw Py::Exception();
1095
return Py::asObject(new TechDraw::DrawPagePy(getMDIViewPagePtr()->getPage()));
1098
Py::Object MDIViewPagePy::cast_to_base(const Py::Tuple&)
1100
return Gui::MDIViewPy::create(base.getMDIViewPtr());
1103
#include <Mod/TechDraw/Gui/moc_MDIViewPage.cpp>