From 0e68943ac3a7938c6b835659f69f8de01be293f9 Mon Sep 17 00:00:00 2001 From: Ian Rees Date: Sun, 29 May 2016 14:40:18 +1200 Subject: [PATCH] Tidy up in MDIViewPage --- src/Mod/TechDraw/Gui/MDIViewPage.cpp | 1209 +++++++++++++------------- src/Mod/TechDraw/Gui/MDIViewPage.h | 30 +- 2 files changed, 626 insertions(+), 613 deletions(-) diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index 199196c4c..233f98d43 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -24,69 +24,56 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include #endif // #ifndef _PreComp_ #include "MDIViewPage.h" -#include -#include -#include -#include +#include "Base/Stream.h" +#include "Base/gzstream.h" +#include "Base/PyObjectBase.h" +#include "Base/Console.h" -#include -#include +#include "App/Document.h" +#include "App/DocumentObject.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Gui/Document.h" +#include "Gui/ViewProvider.h" +#include "Gui/FileDialog.h" +#include "Gui/WaitCursor.h" +#include "Gui/Application.h" +#include "Gui/Command.h" +#include "Gui/Document.h" +#include "Gui/Window.h" +#include "Gui/MainWindow.h" +#include "Gui/Selection.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "../App/DrawHatch.h" +#include "../App/DrawPage.h" +#include "../App/DrawProjGroup.h" +#include "../App/DrawTemplate.h" +#include "../App/DrawView.h" +#include "../App/DrawViewAnnotation.h" +#include "../App/DrawViewClip.h" +#include "../App/DrawViewCollection.h" +#include "../App/DrawViewDimension.h" +#include "../App/DrawViewPart.h" +#include "../App/DrawViewSection.h" #include "../App/DrawViewSpreadsheet.h" +#include "../App/DrawViewSymbol.h" #include "QGIDrawingTemplate.h" #include "QGIView.h" @@ -103,11 +90,10 @@ using namespace TechDrawGui; MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget* parent) : Gui::MDIView(doc, parent), + m_view(new QGVPage(pageVp)), pageGui(pageVp), m_frameState(true) { - m_view = new QGVPage(pageVp); - m_backgroundAction = new QAction(tr("&Background"), this); m_backgroundAction->setEnabled(false); m_backgroundAction->setCheckable(true); @@ -193,6 +179,7 @@ MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget* } + MDIViewPage::~MDIViewPage() { // Safely remove graphicview items that have built up TEMP SOLUTION @@ -204,6 +191,7 @@ MDIViewPage::~MDIViewPage() delete m_view; } + void MDIViewPage::setDimensionGroups(void) { const std::vector &allItems = m_view->getViews(); @@ -220,6 +208,8 @@ void MDIViewPage::setDimensionGroups(void) } } } + + void MDIViewPage::findPrinterSettings(const QString& fileName) { if (fileName.indexOf(QLatin1String("Portrait"), Qt::CaseInsensitive) >= 0) { @@ -260,11 +250,13 @@ void MDIViewPage::findPrinterSettings(const QString& fileName) } } + void MDIViewPage::setDocumentObject(const std::string& name) { m_objectName = name; } + void MDIViewPage::closeEvent(QCloseEvent* ev) { MDIView::closeEvent(ev); @@ -283,6 +275,7 @@ void MDIViewPage::closeEvent(QCloseEvent* ev) } } + void MDIViewPage::contextMenuEvent(QContextMenuEvent *event) { QMenu menu; @@ -298,6 +291,7 @@ void MDIViewPage::contextMenuEvent(QContextMenuEvent *event) menu.exec(event->globalPos()); } + void MDIViewPage::attachTemplate(TechDraw::DrawTemplate *obj) { m_view->setPageTemplate(obj); @@ -306,37 +300,43 @@ void MDIViewPage::attachTemplate(TechDraw::DrawTemplate *obj) m_view->scene()->setSceneRect(QRectF(-1.,-height,width+1.,height)); //the +/- 1 is because of the way the template is define??? } + int MDIViewPage::attachView(App::DocumentObject *obj) { - QGIView *qview = 0; - if(obj->getTypeId().isDerivedFrom(TechDraw::DrawViewSection::getClassTypeId()) ) { - TechDraw::DrawViewSection *viewSect = dynamic_cast(obj); - qview = m_view->addViewSection(viewSect); - } else if (obj->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) ) { - TechDraw::DrawViewPart *viewPart = dynamic_cast(obj); - qview = m_view->addViewPart(viewPart); - } else if (obj->getTypeId().isDerivedFrom(TechDraw::DrawProjGroup::getClassTypeId()) ) { - TechDraw::DrawProjGroup *view = dynamic_cast(obj); - qview = m_view->addProjectionGroup(view); - } else if (obj->getTypeId().isDerivedFrom(TechDraw::DrawViewCollection::getClassTypeId()) ) { - TechDraw::DrawViewCollection *collection = dynamic_cast(obj); - qview = m_view->addDrawView(collection); - } else if(obj->getTypeId().isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId()) ) { - TechDraw::DrawViewDimension *viewDim = dynamic_cast(obj); - qview = m_view->addViewDimension(viewDim); - } else if(obj->getTypeId().isDerivedFrom(TechDraw::DrawViewAnnotation::getClassTypeId()) ) { - TechDraw::DrawViewAnnotation *viewDim = dynamic_cast(obj); - qview = m_view->addDrawViewAnnotation(viewDim); - } else if(obj->getTypeId().isDerivedFrom(TechDraw::DrawViewSymbol::getClassTypeId()) ) { - TechDraw::DrawViewSymbol *viewSym = dynamic_cast(obj); - qview = m_view->addDrawViewSymbol(viewSym); - } else if(obj->getTypeId().isDerivedFrom(TechDraw::DrawViewClip::getClassTypeId()) ) { - TechDraw::DrawViewClip *viewClip = dynamic_cast(obj); - qview = m_view->addDrawViewClip(viewClip); - } else if(obj->getTypeId().isDerivedFrom(TechDraw::DrawViewSpreadsheet::getClassTypeId()) ) { + auto typeId(obj->getTypeId()); + + QGIView *qview(nullptr); + + if (typeId.isDerivedFrom(TechDraw::DrawViewSection::getClassTypeId()) ) { + qview = m_view->addViewSection( dynamic_cast(obj) ); + + } else if (typeId.isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) ) { + qview = m_view->addViewPart( dynamic_cast(obj) ); + + } else if (typeId.isDerivedFrom(TechDraw::DrawProjGroup::getClassTypeId()) ) { + qview = m_view->addProjectionGroup( dynamic_cast(obj) ); + + } else if (typeId.isDerivedFrom(TechDraw::DrawViewCollection::getClassTypeId()) ) { + qview = m_view->addDrawView( dynamic_cast(obj) ); + + } else if (typeId.isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId()) ) { + qview = m_view->addViewDimension( dynamic_cast(obj) ); + + } else if (typeId.isDerivedFrom(TechDraw::DrawViewAnnotation::getClassTypeId()) ) { + qview = m_view->addDrawViewAnnotation( dynamic_cast(obj) ); + + } else if (typeId.isDerivedFrom(TechDraw::DrawViewSymbol::getClassTypeId()) ) { + qview = m_view->addDrawViewSymbol( dynamic_cast(obj) ); + + } else if (typeId.isDerivedFrom(TechDraw::DrawViewClip::getClassTypeId()) ) { + qview = m_view->addDrawViewClip( dynamic_cast(obj) ); + + } else if (typeId.isDerivedFrom(TechDraw::DrawViewSpreadsheet::getClassTypeId()) ) { qview = m_view->addDrawViewSpreadsheet( dynamic_cast(obj) ); - } else if(obj->getTypeId().isDerivedFrom(TechDraw::DrawHatch::getClassTypeId()) ) { + + } else if (typeId.isDerivedFrom(TechDraw::DrawHatch::getClassTypeId()) ) { //Hatch is not attached like other Views (since it isn't really a View) + } else { Base::Console().Log("Logic Error - Unknown view type in MDIViewPage::attachView\n"); } @@ -347,6 +347,7 @@ int MDIViewPage::attachView(App::DocumentObject *obj) return m_view->getViews().size(); } + void MDIViewPage::preSelectionChanged(const QPoint &pos) { QObject *obj = QObject::sender(); @@ -413,11 +414,13 @@ void MDIViewPage::preSelectionChanged(const QPoint &pos) } } + void MDIViewPage::blockSelection(const bool state) { isSlectionBlocked = state; } + void MDIViewPage::clearSelection() { blockSelection(true); @@ -433,6 +436,7 @@ void MDIViewPage::clearSelection() blockSelection(false); } + void MDIViewPage::selectFeature(App::DocumentObject *obj, const bool isSelected) { // Update QGVPage's selection based on Selection made outside Drawing Interace @@ -446,6 +450,533 @@ void MDIViewPage::selectFeature(App::DocumentObject *obj, const bool isSelected) blockSelection(false); } + +void MDIViewPage::updateTemplate(bool forceUpdate) +{ + App::DocumentObject *templObj = pageGui->getPageObject()->Template.getValue(); + // TODO: what if template has been deleted? templObj will be NULL. segfault? + if (!templObj) { + Base::Console().Log("INFO - MDIViewPage::updateTemplate - Page: %s has NO template!!\n",pageGui->getPageObject()->getNameInDocument()); + return; + } + + if(pageGui->getPageObject()->Template.isTouched() || templObj->isTouched()) { + // Template is touched so update + + if(forceUpdate || + (templObj && templObj->isTouched() && templObj->isDerivedFrom(TechDraw::DrawTemplate::getClassTypeId())) ) { + + QGITemplate *qItemTemplate = m_view->getTemplate(); + + if(qItemTemplate) { + TechDraw::DrawTemplate *pageTemplate = dynamic_cast(templObj); + qItemTemplate->setTemplate(pageTemplate); + qItemTemplate->updateView(); + } + } + } + + // m_view->setPageFeature(pageFeature); redundant +} + + +void MDIViewPage::updateDrawing(bool forceUpdate) +{ + // We cannot guarantee if the number of graphical representations (QGIVxxxx) have changed so check the number + // Why? + const std::vector &graphicsList = m_view->getViews(); + const std::vector &pageChildren = pageGui->getPageObject()->Views.getValues(); + + // Count total # DocumentObjects in Page + unsigned int docObjCount = 0; + for(std::vector::const_iterator it = pageChildren.begin(); it != pageChildren.end(); ++it) { + App::DocumentObject *docObj = *it; + if(docObj->getTypeId().isDerivedFrom(TechDraw::DrawViewCollection::getClassTypeId())) { + TechDraw::DrawViewCollection *collection = dynamic_cast(docObj); + docObjCount += collection->countChildren(); // Include self + } + docObjCount += 1; + } + + if(graphicsList.size() < docObjCount) { + // there are more DocumentObjects than graphical representations (QGIVxxxx's) + // Find which DocumentObjects have no graphical representation (QGIVxxxx) + // Iterate over DocumentObjects without graphical representations and create the QGIVxxxx + // TODO think of a better algorithm to deal with any changes to views list + std::vector notFnd; + findMissingViews(pageChildren, notFnd); + for(std::vector::const_iterator it = notFnd.begin(); it != notFnd.end(); ++it) { + attachView(*it); + } + } else if(graphicsList.size() > docObjCount) { + // There are more graphical representations (QGIVxxxx) than DocumentObjects + // Remove the orphans + std::vector::const_iterator itGraphics = graphicsList.begin(); + std::vector newGraphicsList; + bool fnd = false; + while(itGraphics != graphicsList.end()) { + fnd = orphanExists((*itGraphics)->getViewName(), pageChildren); + if(fnd) { + newGraphicsList.push_back(*itGraphics); + } else { + if (m_view->scene() == (*itGraphics)->scene()) { + (*itGraphics)->hide(); + m_view->scene()->removeItem(*itGraphics); + } else { // this "shouldn't" happen, but it does + Base::Console().Log("ERROR - MDIViewPage::updateDrawing - %s already removed from QGraphicsScene\n", + (*itGraphics)->getViewName()); + } + deleteItems.append(*itGraphics); // delete in the destructor when completly safe. TEMP SOLUTION + } + itGraphics++; + } + + // Update the QGVPage (QGraphicsView) list of QGIVxxxx + m_view->setViews(newGraphicsList); + } + + // Update all the QGIVxxxx + const std::vector &upviews = m_view->getViews(); + for(std::vector::const_iterator it = upviews.begin(); it != upviews.end(); ++it) { + if((*it)->getViewObject()->isTouched() || + forceUpdate) { + (*it)->updateView(forceUpdate); + } + } +} + + +void MDIViewPage::findMissingViews(const std::vector &list, std::vector &missing) +{ + for(std::vector::const_iterator it = list.begin(); it != list.end(); ++it) { + + if(!hasQView(*it)) + missing.push_back(*it); + + if((*it)->getTypeId().isDerivedFrom(TechDraw::DrawViewCollection::getClassTypeId())) { + std::vector missingChildViews; + TechDraw::DrawViewCollection *collection = dynamic_cast(*it); + // Find Child Views recursively + findMissingViews(collection->Views.getValues(), missingChildViews); + + // Append the views to current missing list + for(std::vector::const_iterator it = missingChildViews.begin(); it != missingChildViews.end(); ++it) { + missing.push_back(*it); + } + } + } +} + + +/// Helper function +bool MDIViewPage::hasQView(App::DocumentObject *obj) +{ + const std::vector &views = m_view->getViews(); + std::vector::const_iterator qview = views.begin(); + + while(qview != views.end()) { + // Unsure if we can compare pointers so rely on name + if(strcmp((*qview)->getViewObject()->getNameInDocument(), obj->getNameInDocument()) == 0) { + return true; + } + qview++; + } + + return false; +} + + +/// Helper function +bool MDIViewPage::orphanExists(const char *viewName, const std::vector &list) +{ + for(std::vector::const_iterator it = list.begin(); it != list.end(); ++it) { + + //Check child objects too recursively + if((*it)->isDerivedFrom(TechDraw::DrawViewCollection::getClassTypeId())) { + TechDraw::DrawViewCollection *collection = dynamic_cast(*it); + if(orphanExists(viewName, collection->Views.getValues())) + return true; + } + + // Unsure if we can compare pointers so rely on name + if(strcmp(viewName, (*it)->getNameInDocument()) == 0) { + return true; + } + } + return false; +} + + +bool MDIViewPage::onMsg(const char *pMsg, const char **ppReturn) +{ + Gui::Document *doc(getGuiDocument()); + + if (!doc) { + return false; + } else if (strcmp("ViewFit", pMsg) == 0) { + viewAll(); + return true; + } else if (strcmp("Save", pMsg) == 0 ) { + doc->save(); + Gui::Command::updateActive(); + return true; + } else if (strcmp("SaveAs", pMsg) == 0 ) { + doc->saveAs(); + Gui::Command::updateActive(); + return true; + } else if (strcmp("Undo", pMsg) == 0 ) { + doc->undo(1); + Gui::Command::updateActive(); + return true; + } else if (strcmp("Redo", pMsg) == 0 ) { + doc->redo(1); + Gui::Command::updateActive(); + return true; + } + + return false; +} + + +bool MDIViewPage::onHasMsg(const char* pMsg) const +{ + if (strcmp("ViewFit",pMsg) == 0) + return true; + else if(strcmp("Redo", pMsg) == 0 && getAppDocument()->getAvailableRedos() > 0) + return true; + else if(strcmp("Undo", pMsg) == 0 && getAppDocument()->getAvailableUndos() > 0) + return true; + else if (strcmp("Print",pMsg) == 0) + return true; + else if (strcmp("Save",pMsg) == 0) + return true; + else if (strcmp("SaveAs",pMsg) == 0) + return true; + else if (strcmp("PrintPreview",pMsg) == 0) + return true; + else if (strcmp("PrintPdf",pMsg) == 0) + return true; + return false; +} + + +void MDIViewPage::onRelabel(Gui::Document *pDoc) +{ + if (!bIsPassive && pDoc) { + QString cap = QString::fromLatin1("%1 : %2[*]") + .arg(QString::fromUtf8(pDoc->getDocument()->Label.getValue())) + .arg(objectName()); + setWindowTitle(cap); + } +} + + +void MDIViewPage::printPdf() +{ + Gui::FileOptionsDialog dlg(this, 0); + dlg.setFileMode(QFileDialog::AnyFile); + dlg.setAcceptMode(QFileDialog::AcceptSave); + dlg.setWindowTitle(tr("Export PDF")); + dlg.setFilters(QStringList() << QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF file"))); + + QGridLayout *gridLayout; + QGridLayout *formLayout; + QGroupBox *groupBox; + QListWidget *listWidget; + QListWidgetItem* item; + QWidget *form = new QWidget(&dlg); + form->resize(40, 300); + formLayout = new QGridLayout(form); + groupBox = new QGroupBox(form); + gridLayout = new QGridLayout(groupBox); + listWidget = new QListWidget(groupBox); + gridLayout->addWidget(listWidget, 0, 0, 1, 1); + formLayout->addWidget(groupBox, 0, 0, 1, 1); + + groupBox->setTitle(tr("Page sizes")); + item = new QListWidgetItem(tr("A0"), listWidget); + item->setData(Qt::UserRole, QVariant(QPrinter::A0)); + item = new QListWidgetItem(tr("A1"), listWidget); + item->setData(Qt::UserRole, QVariant(QPrinter::A1)); + item = new QListWidgetItem(tr("A2"), listWidget); + item->setData(Qt::UserRole, QVariant(QPrinter::A2)); + item = new QListWidgetItem(tr("A3"), listWidget); + item->setData(Qt::UserRole, QVariant(QPrinter::A3)); + item = new QListWidgetItem(tr("A4"), listWidget); + item->setData(Qt::UserRole, QVariant(QPrinter::A4)); + item = new QListWidgetItem(tr("A5"), listWidget); + item->setData(Qt::UserRole, QVariant(QPrinter::A5)); + item = new QListWidgetItem(tr("Letter"), listWidget); + item->setData(Qt::UserRole, QVariant(QPrinter::Letter)); + item = new QListWidgetItem(tr("Legal"), listWidget); + item->setData(Qt::UserRole, QVariant(QPrinter::Legal)); + //listWidget->item(4)->setSelected(true); // by default A4 + int index = 4; // by default A4 + for (int i=0; icount(); i++) { + if (listWidget->item(i)->data(Qt::UserRole).toInt() == m_pageSize) { + index = i; + break; + } + } + listWidget->item(index)->setSelected(true); + dlg.setOptionsWidget(Gui::FileOptionsDialog::ExtensionRight, form, false); + + if (dlg.exec() == QDialog::Accepted) { + Gui::WaitCursor wc; + QString filename = dlg.selectedFiles().front(); + QPrinter printer(QPrinter::HighResolution); + printer.setFullPage(true); + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setOutputFileName(filename); + printer.setOrientation(m_orientation); + QList items = listWidget->selectedItems(); + if (items.size() == 1) { + int AX = items.front()->data(Qt::UserRole).toInt(); + printer.setPaperSize(QPrinter::PageSize(AX)); + } + + print(&printer); + } +} + + +void MDIViewPage::print() +{ + QPrinter printer(QPrinter::HighResolution); + printer.setFullPage(true); + printer.setPageSize(m_pageSize); + printer.setOrientation(m_orientation); + QPrintDialog dlg(&printer, this); + if (dlg.exec() == QDialog::Accepted) { + print(&printer); + } +} + + +void MDIViewPage::printPreview() +{ + QPrinter printer(QPrinter::HighResolution); + printer.setFullPage(true); + printer.setPageSize(m_pageSize); + printer.setOrientation(m_orientation); + + QPrintPreviewDialog dlg(&printer, this); + connect(&dlg, SIGNAL(paintRequested (QPrinter *)), + this, SLOT(print(QPrinter *))); + dlg.exec(); +} + + +void MDIViewPage::print(QPrinter* printer) +{ + // As size of the render area paperRect() should be used. When performing a real + // print pageRect() may also work but the output is cropped at the bottom part. + // So, independent whether pageRect() or paperRect() is used there is no scaling effect. + // However, when using a different paper size as set in the drawing template (e.g. + // DIN A5 instead of DIN A4) then the output is scaled. + // + // When creating a PDF file there seems to be no difference between pageRect() and + // paperRect(). + // + // When showing the preview of a print paperRect() must be used because with pageRect() + // a certain scaling effect can be observed and the content becomes smaller. + QPaintEngine::Type paintType = printer->paintEngine()->type(); + if (printer->outputFormat() == QPrinter::NativeFormat) { + int w = printer->widthMM(); + int h = printer->heightMM(); + QPrinter::PaperSize realPaperSize = getPageSize(w, h); + QPrinter::PaperSize curPaperSize = printer->paperSize(); + + // for the preview a 'Picture' paint engine is used which we don't + // care if it uses wrong printer settings + bool doPrint = paintType != QPaintEngine::Picture; + + if (doPrint && printer->orientation() != m_orientation) { + int ret = QMessageBox::warning(this, tr("Different orientation"), + tr("The printer uses a different orientation than the drawing.\n" + "Do you want to continue?"), + QMessageBox::Yes | QMessageBox::No); + if (ret != QMessageBox::Yes) + return; + } + else if (doPrint && realPaperSize != m_pageSize) { + int ret = QMessageBox::warning(this, tr("Different paper size"), + tr("The printer uses a different paper size than the drawing.\n" + "Do you want to continue?"), + QMessageBox::Yes | QMessageBox::No); + if (ret != QMessageBox::Yes) + return; + } + else if (doPrint && curPaperSize != m_pageSize) { + int ret = QMessageBox::warning(this, tr("Different paper size"), + tr("The printer uses a different paper size than the drawing.\n" + "Do you want to continue?"), + QMessageBox::Yes | QMessageBox::No); + if (ret != QMessageBox::Yes) + return; + } + } + + QPainter p(printer); + if (!p.isActive() && !printer->outputFileName().isEmpty()) { + qApp->setOverrideCursor(Qt::ArrowCursor); + QMessageBox::critical(this, tr("Opening file failed"), + tr("Can't open file '%1' for writing.").arg(printer->outputFileName())); + qApp->restoreOverrideCursor(); + return; + } + + QRect rect = printer->paperRect(); +#ifdef Q_OS_WIN32 + // On Windows the preview looks broken when using paperRect as render area. + // Although the picture is scaled when using pageRect, it looks just fine. + if (paintType == QPaintEngine::Picture) + rect = printer->pageRect(); +#endif + + //bool block = + static_cast (blockConnection(true)); // avoid to be notified by itself + Gui::Selection().clearSelection(); + + m_view->toggleEdit(false); + m_view->scene()->update(); + + Gui::Selection().clearSelection(); + + m_view->scene()->render(&p, rect); + + // Reset + m_view->toggleEdit(true); +} + + +//QPrinter::PageSize is obsolete. Use QPrinter::PaperSize instead. +QPrinter::PageSize MDIViewPage::getPageSize(int w, int h) const +{ + static const float paperSizes[][2] = { + {210, 297}, // A4 + {176, 250}, // B5 + {215.9f, 279.4f}, // Letter + {215.9f, 355.6f}, // Legal + {190.5f, 254}, // Executive + {841, 1189}, // A0 + {594, 841}, // A1 + {420, 594}, // A2 + {297, 420}, // A3 + {148, 210}, // A5 + {105, 148}, // A6 + {74, 105}, // A7 + {52, 74}, // A8 + {37, 52}, // A8 + {1000, 1414}, // B0 + {707, 1000}, // B1 + {31, 44}, // B10 + {500, 707}, // B2 + {353, 500}, // B3 + {250, 353}, // B4 + {125, 176}, // B6 + {88, 125}, // B7 + {62, 88}, // B8 + {33, 62}, // B9 + {163, 229}, // C5E + {105, 241}, // US Common + {110, 220}, // DLE + {210, 330}, // Folio + {431.8f, 279.4f}, // Ledger + {279.4f, 431.8f} // Tabloid + }; + + QPrinter::PageSize ps = QPrinter::Custom; + for (int i=0; i<30; i++) { + if (std::abs(paperSizes[i][0]-w) <= 1 && + std::abs(paperSizes[i][1]-h) <= 1) { + ps = static_cast(i); + break; + } + else + if (std::abs(paperSizes[i][0]-h) <= 1 && + std::abs(paperSizes[i][1]-w) <= 1) { + ps = static_cast(i); + break; + } + } + + return ps; +} + + +void MDIViewPage::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + if (msg.Type == Gui::SelectionChanges::ClrSelection) { + + } + else if (msg.Type == Gui::SelectionChanges::AddSelection || + msg.Type == Gui::SelectionChanges::RmvSelection) { + //bool select = (msg.Type == Gui::SelectionChanges::AddSelection); + // Check if it is a view object + } + else if (msg.Type == Gui::SelectionChanges::SetSelection) { + // do nothing here + } +} + + +void MDIViewPage::setFrameState(bool state) +{ + m_frameState = state; + m_view->toggleEdit(state); + m_view->scene()->update(); +} + + +PyObject* MDIViewPage::getPyObject() +{ + Py_Return; +} + + +void MDIViewPage::setRenderer(QAction *action) +{ +#ifndef QT_NO_OPENGL + m_highQualityAntialiasingAction->setEnabled(false); +#endif + + if (action == m_nativeAction) + m_view->setRenderer(QGVPage::Native); +#ifndef QT_NO_OPENGL + else if (action == m_glAction) { + m_highQualityAntialiasingAction->setEnabled(true); + m_view->setRenderer(QGVPage::OpenGL); + } +#endif + else if (action == m_imageAction) { + m_view->setRenderer(QGVPage::Image); + } +} + + +void MDIViewPage::viewAll() +{ + m_view->fitInView(m_view->scene()->sceneRect(), Qt::KeepAspectRatio); +} + + +void MDIViewPage::saveSVG() +{ + QStringList filter; + filter << QObject::tr("SVG (*.svg)"); + filter << QObject::tr("All Files (*.*)"); + QString fn = Gui::FileDialog::getSaveFileName(Gui::getMainWindow(), QObject::tr("Export page as SVG"), + QString(), filter.join(QLatin1String(";;"))); + if (fn.isEmpty()) { + return; + } + static_cast (blockConnection(true)); // avoid to be notified by itself + + m_view->saveSvg(fn); +} + + void MDIViewPage::selectionChanged() { if(isSlectionBlocked) @@ -543,514 +1074,6 @@ void MDIViewPage::selectionChanged() } blockConnection(block); -} - -void MDIViewPage::updateTemplate(bool forceUpdate) -{ - App::DocumentObject *templObj = pageGui->getPageObject()->Template.getValue(); - // TODO: what if template has been deleted? templObj will be NULL. segfault? - if (!templObj) { - Base::Console().Log("INFO - MDIViewPage::updateTemplate - Page: %s has NO template!!\n",pageGui->getPageObject()->getNameInDocument()); - return; - } - - if(pageGui->getPageObject()->Template.isTouched() || templObj->isTouched()) { - // Template is touched so update - - if(forceUpdate || - (templObj && templObj->isTouched() && templObj->isDerivedFrom(TechDraw::DrawTemplate::getClassTypeId())) ) { - - QGITemplate *qItemTemplate = m_view->getTemplate(); - - if(qItemTemplate) { - TechDraw::DrawTemplate *pageTemplate = dynamic_cast(templObj); - qItemTemplate->setTemplate(pageTemplate); - qItemTemplate->updateView(); - } - } - } - - // m_view->setPageFeature(pageFeature); redundant -} - -void MDIViewPage::updateDrawing(bool forceUpdate) -{ - // We cannot guarantee if the number of graphical representations (QGIVxxxx) have changed so check the number - // Why? - const std::vector &graphicsList = m_view->getViews(); - const std::vector &pageChildren = pageGui->getPageObject()->Views.getValues(); - - // Count total # DocumentObjects in Page - unsigned int docObjCount = 0; - for(std::vector::const_iterator it = pageChildren.begin(); it != pageChildren.end(); ++it) { - App::DocumentObject *docObj = *it; - if(docObj->getTypeId().isDerivedFrom(TechDraw::DrawViewCollection::getClassTypeId())) { - TechDraw::DrawViewCollection *collection = dynamic_cast(docObj); - docObjCount += collection->countChildren(); // Include self - } - docObjCount += 1; - } - - if(graphicsList.size() < docObjCount) { - // there are more DocumentObjects than graphical representations (QGIVxxxx's) - // Find which DocumentObjects have no graphical representation (QGIVxxxx) - // Iterate over DocumentObjects without graphical representations and create the QGIVxxxx - // TODO think of a better algorithm to deal with any changes to views list - std::vector notFnd; - findMissingViews(pageChildren, notFnd); - for(std::vector::const_iterator it = notFnd.begin(); it != notFnd.end(); ++it) { - attachView(*it); - } - } else if(graphicsList.size() > docObjCount) { - // There are more graphical representations (QGIVxxxx) than DocumentObjects - // Remove the orphans - std::vector::const_iterator itGraphics = graphicsList.begin(); - std::vector newGraphicsList; - bool fnd = false; - while(itGraphics != graphicsList.end()) { - fnd = orphanExists((*itGraphics)->getViewName(), pageChildren); - if(fnd) { - newGraphicsList.push_back(*itGraphics); - } else { - if (m_view->scene() == (*itGraphics)->scene()) { - (*itGraphics)->hide(); - m_view->scene()->removeItem(*itGraphics); - } else { // this "shouldn't" happen, but it does - Base::Console().Log("ERROR - MDIViewPage::updateDrawing - %s already removed from QGraphicsScene\n", - (*itGraphics)->getViewName()); - } - deleteItems.append(*itGraphics); // delete in the destructor when completly safe. TEMP SOLUTION - } - itGraphics++; - } - - // Update the QGVPage (QGraphicsView) list of QGIVxxxx - m_view->setViews(newGraphicsList); - } - - // Update all the QGIVxxxx - const std::vector &upviews = m_view->getViews(); - for(std::vector::const_iterator it = upviews.begin(); it != upviews.end(); ++it) { - if((*it)->getViewObject()->isTouched() || - forceUpdate) { - (*it)->updateView(forceUpdate); - } - } -} - -void MDIViewPage::findMissingViews(const std::vector &list, std::vector &missing) -{ - for(std::vector::const_iterator it = list.begin(); it != list.end(); ++it) { - - if(!hasQView(*it)) - missing.push_back(*it); - - if((*it)->getTypeId().isDerivedFrom(TechDraw::DrawViewCollection::getClassTypeId())) { - std::vector missingChildViews; - TechDraw::DrawViewCollection *collection = dynamic_cast(*it); - // Find Child Views recursively - findMissingViews(collection->Views.getValues(), missingChildViews); - - // Append the views to current missing list - for(std::vector::const_iterator it = missingChildViews.begin(); it != missingChildViews.end(); ++it) { - missing.push_back(*it); - } - } - } -} - -/// Helper function -bool MDIViewPage::hasQView(App::DocumentObject *obj) -{ - const std::vector &views = m_view->getViews(); - std::vector::const_iterator qview = views.begin(); - - while(qview != views.end()) { - // Unsure if we can compare pointers so rely on name - if(strcmp((*qview)->getViewObject()->getNameInDocument(), obj->getNameInDocument()) == 0) { - return true; - } - qview++; - } - - return false; -} - -/// Helper function -bool MDIViewPage::orphanExists(const char *viewName, const std::vector &list) -{ - for(std::vector::const_iterator it = list.begin(); it != list.end(); ++it) { - - //Check child objects too recursively - if((*it)->isDerivedFrom(TechDraw::DrawViewCollection::getClassTypeId())) { - TechDraw::DrawViewCollection *collection = dynamic_cast(*it); - if(orphanExists(viewName, collection->Views.getValues())) - return true; - } - - // Unsure if we can compare pointers so rely on name - if(strcmp(viewName, (*it)->getNameInDocument()) == 0) { - return true; - } - } - return false; -} - - -void MDIViewPage::setRenderer(QAction *action) -{ -#ifndef QT_NO_OPENGL - m_highQualityAntialiasingAction->setEnabled(false); -#endif - - if (action == m_nativeAction) - m_view->setRenderer(QGVPage::Native); -#ifndef QT_NO_OPENGL - else if (action == m_glAction) { - m_highQualityAntialiasingAction->setEnabled(true); - m_view->setRenderer(QGVPage::OpenGL); - } -#endif - else if (action == m_imageAction) { - m_view->setRenderer(QGVPage::Image); - } -} -bool MDIViewPage::onMsg(const char *pMsg, const char **ppReturn) -{ - Gui::Document *doc(getGuiDocument()); - - if (!doc) { - return false; - } else if (strcmp("ViewFit", pMsg) == 0) { - viewAll(); - return true; - } else if (strcmp("Save", pMsg) == 0 ) { - doc->save(); - Gui::Command::updateActive(); - return true; - } else if (strcmp("SaveAs", pMsg) == 0 ) { - doc->saveAs(); - Gui::Command::updateActive(); - return true; - } else if (strcmp("Undo", pMsg) == 0 ) { - doc->undo(1); - Gui::Command::updateActive(); - return true; - } else if (strcmp("Redo", pMsg) == 0 ) { - doc->redo(1); - Gui::Command::updateActive(); - return true; - } - - return false; -} - -bool MDIViewPage::onHasMsg(const char* pMsg) const -{ - if (strcmp("ViewFit",pMsg) == 0) - return true; - else if(strcmp("Redo", pMsg) == 0 && getAppDocument()->getAvailableRedos() > 0) - return true; - else if(strcmp("Undo", pMsg) == 0 && getAppDocument()->getAvailableUndos() > 0) - return true; - else if (strcmp("Print",pMsg) == 0) - return true; - else if (strcmp("Save",pMsg) == 0) - return true; - else if (strcmp("SaveAs",pMsg) == 0) - return true; - else if (strcmp("PrintPreview",pMsg) == 0) - return true; - else if (strcmp("PrintPdf",pMsg) == 0) - return true; - return false; -} - -void MDIViewPage::onRelabel(Gui::Document *pDoc) -{ - if (!bIsPassive && pDoc) { - QString cap = QString::fromLatin1("%1 : %2[*]") - .arg(QString::fromUtf8(pDoc->getDocument()->Label.getValue())) - .arg(objectName()); - setWindowTitle(cap); - } -} - -void MDIViewPage::printPdf() -{ - Gui::FileOptionsDialog dlg(this, 0); - dlg.setFileMode(QFileDialog::AnyFile); - dlg.setAcceptMode(QFileDialog::AcceptSave); - dlg.setWindowTitle(tr("Export PDF")); - dlg.setFilters(QStringList() << QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF file"))); - - QGridLayout *gridLayout; - QGridLayout *formLayout; - QGroupBox *groupBox; - QListWidget *listWidget; - QListWidgetItem* item; - QWidget *form = new QWidget(&dlg); - form->resize(40, 300); - formLayout = new QGridLayout(form); - groupBox = new QGroupBox(form); - gridLayout = new QGridLayout(groupBox); - listWidget = new QListWidget(groupBox); - gridLayout->addWidget(listWidget, 0, 0, 1, 1); - formLayout->addWidget(groupBox, 0, 0, 1, 1); - - groupBox->setTitle(tr("Page sizes")); - item = new QListWidgetItem(tr("A0"), listWidget); - item->setData(Qt::UserRole, QVariant(QPrinter::A0)); - item = new QListWidgetItem(tr("A1"), listWidget); - item->setData(Qt::UserRole, QVariant(QPrinter::A1)); - item = new QListWidgetItem(tr("A2"), listWidget); - item->setData(Qt::UserRole, QVariant(QPrinter::A2)); - item = new QListWidgetItem(tr("A3"), listWidget); - item->setData(Qt::UserRole, QVariant(QPrinter::A3)); - item = new QListWidgetItem(tr("A4"), listWidget); - item->setData(Qt::UserRole, QVariant(QPrinter::A4)); - item = new QListWidgetItem(tr("A5"), listWidget); - item->setData(Qt::UserRole, QVariant(QPrinter::A5)); - item = new QListWidgetItem(tr("Letter"), listWidget); - item->setData(Qt::UserRole, QVariant(QPrinter::Letter)); - item = new QListWidgetItem(tr("Legal"), listWidget); - item->setData(Qt::UserRole, QVariant(QPrinter::Legal)); - //listWidget->item(4)->setSelected(true); // by default A4 - int index = 4; // by default A4 - for (int i=0; icount(); i++) { - if (listWidget->item(i)->data(Qt::UserRole).toInt() == m_pageSize) { - index = i; - break; - } - } - listWidget->item(index)->setSelected(true); - dlg.setOptionsWidget(Gui::FileOptionsDialog::ExtensionRight, form, false); - - if (dlg.exec() == QDialog::Accepted) { - Gui::WaitCursor wc; - QString filename = dlg.selectedFiles().front(); - QPrinter printer(QPrinter::HighResolution); - printer.setFullPage(true); - printer.setOutputFormat(QPrinter::PdfFormat); - printer.setOutputFileName(filename); - printer.setOrientation(m_orientation); - QList items = listWidget->selectedItems(); - if (items.size() == 1) { - int AX = items.front()->data(Qt::UserRole).toInt(); - printer.setPaperSize(QPrinter::PageSize(AX)); - } - - print(&printer); - } -} - -void MDIViewPage::print() -{ - QPrinter printer(QPrinter::HighResolution); - printer.setFullPage(true); - printer.setPageSize(m_pageSize); - printer.setOrientation(m_orientation); - QPrintDialog dlg(&printer, this); - if (dlg.exec() == QDialog::Accepted) { - print(&printer); - } -} - -void MDIViewPage::printPreview() -{ - QPrinter printer(QPrinter::HighResolution); - printer.setFullPage(true); - printer.setPageSize(m_pageSize); - printer.setOrientation(m_orientation); - - QPrintPreviewDialog dlg(&printer, this); - connect(&dlg, SIGNAL(paintRequested (QPrinter *)), - this, SLOT(print(QPrinter *))); - dlg.exec(); -} - - -void MDIViewPage::print(QPrinter* printer) -{ - // As size of the render area paperRect() should be used. When performing a real - // print pageRect() may also work but the output is cropped at the bottom part. - // So, independent whether pageRect() or paperRect() is used there is no scaling effect. - // However, when using a different paper size as set in the drawing template (e.g. - // DIN A5 instead of DIN A4) then the output is scaled. - // - // When creating a PDF file there seems to be no difference between pageRect() and - // paperRect(). - // - // When showing the preview of a print paperRect() must be used because with pageRect() - // a certain scaling effect can be observed and the content becomes smaller. - QPaintEngine::Type paintType = printer->paintEngine()->type(); - if (printer->outputFormat() == QPrinter::NativeFormat) { - int w = printer->widthMM(); - int h = printer->heightMM(); - QPrinter::PaperSize realPaperSize = getPageSize(w, h); - QPrinter::PaperSize curPaperSize = printer->paperSize(); - - // for the preview a 'Picture' paint engine is used which we don't - // care if it uses wrong printer settings - bool doPrint = paintType != QPaintEngine::Picture; - - if (doPrint && printer->orientation() != m_orientation) { - int ret = QMessageBox::warning(this, tr("Different orientation"), - tr("The printer uses a different orientation than the drawing.\n" - "Do you want to continue?"), - QMessageBox::Yes | QMessageBox::No); - if (ret != QMessageBox::Yes) - return; - } - else if (doPrint && realPaperSize != m_pageSize) { - int ret = QMessageBox::warning(this, tr("Different paper size"), - tr("The printer uses a different paper size than the drawing.\n" - "Do you want to continue?"), - QMessageBox::Yes | QMessageBox::No); - if (ret != QMessageBox::Yes) - return; - } - else if (doPrint && curPaperSize != m_pageSize) { - int ret = QMessageBox::warning(this, tr("Different paper size"), - tr("The printer uses a different paper size than the drawing.\n" - "Do you want to continue?"), - QMessageBox::Yes | QMessageBox::No); - if (ret != QMessageBox::Yes) - return; - } - } - - QPainter p(printer); - if (!p.isActive() && !printer->outputFileName().isEmpty()) { - qApp->setOverrideCursor(Qt::ArrowCursor); - QMessageBox::critical(this, tr("Opening file failed"), - tr("Can't open file '%1' for writing.").arg(printer->outputFileName())); - qApp->restoreOverrideCursor(); - return; - } - - QRect rect = printer->paperRect(); -#ifdef Q_OS_WIN32 - // On Windows the preview looks broken when using paperRect as render area. - // Although the picture is scaled when using pageRect, it looks just fine. - if (paintType == QPaintEngine::Picture) - rect = printer->pageRect(); -#endif - - //bool block = - static_cast (blockConnection(true)); // avoid to be notified by itself - Gui::Selection().clearSelection(); - - m_view->toggleEdit(false); - m_view->scene()->update(); - - Gui::Selection().clearSelection(); - - m_view->scene()->render(&p, rect); - - // Reset - m_view->toggleEdit(true); -} - -//QPrinter::PageSize is obsolete. Use QPrinter::PaperSize instead. -QPrinter::PageSize MDIViewPage::getPageSize(int w, int h) const -{ - static const float paperSizes[][2] = { - {210, 297}, // A4 - {176, 250}, // B5 - {215.9f, 279.4f}, // Letter - {215.9f, 355.6f}, // Legal - {190.5f, 254}, // Executive - {841, 1189}, // A0 - {594, 841}, // A1 - {420, 594}, // A2 - {297, 420}, // A3 - {148, 210}, // A5 - {105, 148}, // A6 - {74, 105}, // A7 - {52, 74}, // A8 - {37, 52}, // A8 - {1000, 1414}, // B0 - {707, 1000}, // B1 - {31, 44}, // B10 - {500, 707}, // B2 - {353, 500}, // B3 - {250, 353}, // B4 - {125, 176}, // B6 - {88, 125}, // B7 - {62, 88}, // B8 - {33, 62}, // B9 - {163, 229}, // C5E - {105, 241}, // US Common - {110, 220}, // DLE - {210, 330}, // Folio - {431.8f, 279.4f}, // Ledger - {279.4f, 431.8f} // Tabloid - }; - - QPrinter::PageSize ps = QPrinter::Custom; - for (int i=0; i<30; i++) { - if (std::abs(paperSizes[i][0]-w) <= 1 && - std::abs(paperSizes[i][1]-h) <= 1) { - ps = static_cast(i); - break; - } - else - if (std::abs(paperSizes[i][0]-h) <= 1 && - std::abs(paperSizes[i][1]-w) <= 1) { - ps = static_cast(i); - break; - } - } - - return ps; -} - -void MDIViewPage::viewAll() -{ - m_view->fitInView(m_view->scene()->sceneRect(), Qt::KeepAspectRatio); -} - -void MDIViewPage::onSelectionChanged(const Gui::SelectionChanges& msg) -{ - if (msg.Type == Gui::SelectionChanges::ClrSelection) { - - } - else if (msg.Type == Gui::SelectionChanges::AddSelection || - msg.Type == Gui::SelectionChanges::RmvSelection) { - //bool select = (msg.Type == Gui::SelectionChanges::AddSelection); - // Check if it is a view object - } - else if (msg.Type == Gui::SelectionChanges::SetSelection) { - // do nothing here - } -} - -void MDIViewPage::saveSVG() -{ - QStringList filter; - filter << QObject::tr("SVG (*.svg)"); - filter << QObject::tr("All Files (*.*)"); - QString fn = Gui::FileDialog::getSaveFileName(Gui::getMainWindow(), QObject::tr("Export page as SVG"), - QString(), filter.join(QLatin1String(";;"))); - if (fn.isEmpty()) { - return; - } - static_cast (blockConnection(true)); // avoid to be notified by itself - - m_view->saveSvg(fn); -} - -void MDIViewPage::setFrameState(bool state) -{ - m_frameState = state; - m_view->toggleEdit(state); - m_view->scene()->update(); -} - -PyObject* MDIViewPage::getPyObject() -{ - Py_Return; -} +} // end MDIViewPage::selectionChanged() #include "moc_MDIViewPage.cpp" diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.h b/src/Mod/TechDraw/Gui/MDIViewPage.h index d737e99ba..bbf4d7aae 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.h +++ b/src/Mod/TechDraw/Gui/MDIViewPage.h @@ -24,25 +24,16 @@ #ifndef DRAWINGGUI_DRAWINGVIEW_H #define DRAWINGGUI_DRAWINGVIEW_H -#include -#include +#include "Gui/MDIView.h" +#include "Gui/Selection.h" -#include #include QT_BEGIN_NAMESPACE -class QSlider; class QAction; -class QActionGroup; -class QFile; -class QPopupMenu; -class QToolBar; -class QSvgWidget; -class QScrollArea; -class QPrinter; QT_END_NAMESPACE + namespace TechDraw { -class DrawPage; class DrawTemplate; } @@ -61,14 +52,7 @@ public: MDIViewPage(ViewProviderPage *page, Gui::Document* doc, QWidget* parent = 0); virtual ~MDIViewPage(); -public Q_SLOTS: - void setRenderer(QAction *action); - void viewAll(); - void saveSVG(void); - void selectionChanged(); - -public: - /// Observer message from the Selection + /// Observer message from the Selection void onSelectionChanged(const Gui::SelectionChanges& msg); void preSelectionChanged(const QPoint &pos); void selectFeature(App::DocumentObject *obj, bool state); @@ -95,6 +79,12 @@ public: QGVPage* getQGVPage(void) {return m_view;}; +public Q_SLOTS: + void setRenderer(QAction *action); + void viewAll(); + void saveSVG(void); + void selectionChanged(); + protected: void findMissingViews( const std::vector &list, std::vector &missing); bool hasQView(App::DocumentObject *obj);