From 45ef05746e93ffca8bfd76efa85da9c3f92358c4 Mon Sep 17 00:00:00 2001 From: paullee0 Date: Wed, 15 Jan 2020 03:05:18 +0800 Subject: [PATCH 01/11] [ArchWindow] Fix getIcon() problem if base is SketchObjectPython Similar to ArchWall + SketchObjectPython in Disscusion : https://forum.freecadweb.org/viewtopic.php?t=26815 --- src/Mod/Arch/ArchWindow.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 21caabcc9a..d5d7ab17cb 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -1709,11 +1709,11 @@ class _ArchWindowTaskPanel: def getIcon(self,obj): if hasattr(obj.ViewObject,"Proxy"): - return QtGui.QIcon(obj.ViewObject.Proxy.getIcon()) - elif obj.isDerivedFrom("Sketcher::SketchObject"): + if hasattr(obj.ViewObject.Proxy,"getIcon"): + return QtGui.QIcon(obj.ViewObject.Proxy.getIcon()) + if obj.isDerivedFrom("Sketcher::SketchObject"): return QtGui.QIcon(":/icons/Sketcher_Sketch.svg") - else: - return QtGui.QIcon(":/icons/Tree_Part.svg") + return QtGui.QIcon(":/icons/Tree_Part.svg") def update(self): From d195c1a703024033a7d2bdc4bbbcd8f8ab0d35b0 Mon Sep 17 00:00:00 2001 From: Pablo Gil Date: Tue, 14 Jan 2020 08:42:03 +0100 Subject: [PATCH 02/11] [Stylesheets] fix selection background color for Darker theme --- src/Gui/Stylesheets/Darker-blue.qss | 6 +++--- src/Gui/Stylesheets/Darker-green.qss | 6 +++--- src/Gui/Stylesheets/Darker-orange.qss | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Gui/Stylesheets/Darker-blue.qss b/src/Gui/Stylesheets/Darker-blue.qss index c9316fecce..f9ae666417 100644 --- a/src/Gui/Stylesheets/Darker-blue.qss +++ b/src/Gui/Stylesheets/Darker-blue.qss @@ -1,7 +1,7 @@ /* ABOUT ============================================================================================================ -version 2.21 +version 2.22 Qt theme (stylesheet) specially developed for FreeCAD (https://www.freecadweb.org/). It might work with other software that uses Qt styling. @@ -1165,8 +1165,8 @@ QDateEdit, QDateTimeEdit { color: #bebebe; background-color: #2a2a2a; - selection-color: #cbd8e6; - selection-background-color: #2053c0; + selection-color: white; + selection-background-color: #1b3774 ; border: 1px solid #2a2a2a; border-radius: 3px; min-width: 50px; /* it ensures the default value is correctly displayed */ diff --git a/src/Gui/Stylesheets/Darker-green.qss b/src/Gui/Stylesheets/Darker-green.qss index 688a404552..4d67800e87 100644 --- a/src/Gui/Stylesheets/Darker-green.qss +++ b/src/Gui/Stylesheets/Darker-green.qss @@ -1,7 +1,7 @@ /* ABOUT ============================================================================================================ -version 2.21 +version 2.22 Qt theme (stylesheet) specially developed for FreeCAD (https://www.freecadweb.org/). It might work with other software that uses Qt styling. @@ -1165,8 +1165,8 @@ QDateEdit, QDateTimeEdit { color: #bebebe; background-color: #2a2a2a; - selection-color: #dadfc5; - selection-background-color: #74831d; + selection-color: white; + selection-background-color: #566214 ; border: 1px solid #2a2a2a; border-radius: 3px; min-width: 50px; /* it ensures the default value is correctly displayed */ diff --git a/src/Gui/Stylesheets/Darker-orange.qss b/src/Gui/Stylesheets/Darker-orange.qss index e71752ce80..7b6213dc07 100644 --- a/src/Gui/Stylesheets/Darker-orange.qss +++ b/src/Gui/Stylesheets/Darker-orange.qss @@ -1,7 +1,7 @@ /* ABOUT ============================================================================================================ -version 2.21 +version 2.22 Qt theme (stylesheet) specially developed for FreeCAD (https://www.freecadweb.org/). It might work with other software that uses Qt styling. @@ -1165,8 +1165,8 @@ QDateEdit, QDateTimeEdit { color: #bebebe; background-color: #2a2a2a; - selection-color: #e3d8b9; - selection-background-color: #b28416; + selection-color: white; + selection-background-color: #624b14 ; border: 1px solid #2a2a2a; border-radius: 3px; min-width: 50px; /* it ensures the default value is correctly displayed */ From 099cc2c59ed4bec4099d5caa1db58b66bb92cd00 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 15 Jan 2020 12:24:18 +0100 Subject: [PATCH 03/11] Draft: only try to import FreeCADGui, coin and QtGui if FreeCAD.GuiUp is true --- src/Mod/Draft/draftutils/gui_utils.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Mod/Draft/draftutils/gui_utils.py b/src/Mod/Draft/draftutils/gui_utils.py index 6f1cbb7ce2..fb5d1922ee 100644 --- a/src/Mod/Draft/draftutils/gui_utils.py +++ b/src/Mod/Draft/draftutils/gui_utils.py @@ -34,19 +34,21 @@ the graphical user interface (GUI). import FreeCAD -import FreeCADGui from .utils import _msg from .utils import _wrn # from .utils import _log from .utils import _tr from .utils import getParam -from pivy import coin -from PySide import QtGui -# from PySide import QtSvg # for load_texture import os import math import six +if FreeCAD.GuiUp: + import FreeCADGui + from pivy import coin + from PySide import QtGui +# from PySide import QtSvg # for load_texture + def get_3d_view(): """Return the current 3D view. From 1458e49e139d742de69f3abb6dbc2b66edab4edc Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 14 Jan 2020 19:43:21 -0500 Subject: [PATCH 04/11] [TD]Cleanup dead code in TaskRichAnno --- src/Mod/TechDraw/Gui/TaskRichAnno.cpp | 27 ++++++++------------------- src/Mod/TechDraw/Gui/TaskRichAnno.h | 3 --- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/Mod/TechDraw/Gui/TaskRichAnno.cpp b/src/Mod/TechDraw/Gui/TaskRichAnno.cpp index 602abc7515..ce3ab6fb2e 100644 --- a/src/Mod/TechDraw/Gui/TaskRichAnno.cpp +++ b/src/Mod/TechDraw/Gui/TaskRichAnno.cpp @@ -238,7 +238,14 @@ void TaskRichAnno::onEditorClicked(bool b) Q_UNUSED(b); m_textDialog = new QDialog(0); QString leadText = ui->teAnnoText->toHtml(); - m_rte = new MRichTextEdit(m_textDialog, leadText); + QString plainText = ui->teAnnoText->toPlainText(); +// Base::Console().Message("TRA::onEditorClicked - leadText: %s** plainText: %s**\n", +// qPrintable(leadText), qPrintable(plainText)); + if (plainText.isEmpty()) { + m_rte = new MRichTextEdit(m_textDialog); + } else { + m_rte = new MRichTextEdit(m_textDialog, leadText); + } //m_rte->setTextWidth(m_annoVP->MaxWidth); QGridLayout* gl = new QGridLayout(m_textDialog); gl->addWidget(m_rte,0,0,1,1); @@ -424,24 +431,6 @@ void TaskRichAnno::enableTaskButtons(bool b) m_btnCancel->setEnabled(b); } -QString TaskRichAnno::getDefFont(void) -{ - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Labels"); - std::string fontName = hGrp->GetASCII("LabelFont", "osifont"); - QString result = Base::Tools::fromStdString(fontName); - return result; -} - -int TaskRichAnno::getDefFontSize() -{ - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions"); - double fontSize = hGrp->GetFloat("FontSize", 5.0); // this is mm, not pts! - double mmToPts = 2.83; - int ptsSize = round(fontSize * mmToPts); - return ptsSize; -} //****************************************************************************** bool TaskRichAnno::accept() diff --git a/src/Mod/TechDraw/Gui/TaskRichAnno.h b/src/Mod/TechDraw/Gui/TaskRichAnno.h index ffbdd0d4f4..fedb395ee0 100644 --- a/src/Mod/TechDraw/Gui/TaskRichAnno.h +++ b/src/Mod/TechDraw/Gui/TaskRichAnno.h @@ -100,9 +100,6 @@ protected: void enableTextUi(bool b); void enableVPUi(bool b); - int getDefFontSize(void); - QString getDefFont(void); - private: Ui_TaskRichAnno * ui; bool blockUpdate; From ab4368531b781b5e23cc43c22714b37970d878cc Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 14 Jan 2020 19:43:54 -0500 Subject: [PATCH 05/11] [TD]fix RTA text size handling --- src/Mod/TechDraw/Gui/mrichtextedit.cpp | 141 +++++++++++++++++++------ src/Mod/TechDraw/Gui/mrichtextedit.h | 3 +- 2 files changed, 108 insertions(+), 36 deletions(-) diff --git a/src/Mod/TechDraw/Gui/mrichtextedit.cpp b/src/Mod/TechDraw/Gui/mrichtextedit.cpp index 01f97caa12..5dca6ec84a 100644 --- a/src/Mod/TechDraw/Gui/mrichtextedit.cpp +++ b/src/Mod/TechDraw/Gui/mrichtextedit.cpp @@ -25,7 +25,7 @@ * includes changes by wandererfan@gmail.com * for FreeCAD project https://www.freecadweb.org/ ********************************/ - +#include "PreCompiled.h" #include #include @@ -46,6 +46,13 @@ #include #include +#include + +#include +#include +#include + +#include #include "mrichtextedit.h" @@ -53,8 +60,9 @@ MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent) setupUi(this); m_lastBlockList = 0; f_textedit->setTabStopWidth(40); - setDefFontSize(12); - m_defFont = QString::fromUtf8("Sans"); + setDefFontSize(getDefFontSizeNum()); + m_defFont = getDefFont().family(); + f_textedit->setFont(getDefFont()); connect(f_save, SIGNAL(clicked()), this, SLOT(onSave())); @@ -75,12 +83,10 @@ MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent) m_fontsize_h4 = m_defFontSize + 2; //TODO: should check for existing text and set font to match -// fontChanged(f_textedit->font()); fontChanged(getDefFont()); bgColorChanged(f_textedit->textColor()); // paragraph formatting - m_paragraphItems << tr("Standard") << tr("Heading 1") << tr("Heading 2") @@ -125,8 +131,6 @@ MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent) connect(f_textedit, SIGNAL(copyAvailable(bool)), f_cut, SLOT(setEnabled(bool))); connect(f_textedit, SIGNAL(copyAvailable(bool)), f_copy, SLOT(setEnabled(bool))); -// f_textedit->setLineWrapMode(QTextEdit::FixedColumnWidth); -// f_textedit->setLineWrapColumnOrWidth(????)); #ifndef QT_NO_CLIPBOARD connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(slotClipboardDataChanged())); #endif @@ -149,7 +153,7 @@ MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent) connect(f_strikeout, SIGNAL(clicked()), this, SLOT(textStrikeout())); QAction *removeFormat = new QAction(tr("Remove character formatting"), this); - removeFormat->setShortcut(QKeySequence("CTRL+M")); + removeFormat->setShortcut(QKeySequence(QString::fromUtf8("CTRL+M"))); connect(removeFormat, SIGNAL(triggered()), this, SLOT(textRemoveFormat())); f_textedit->addAction(removeFormat); @@ -158,7 +162,7 @@ MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent) f_textedit->addAction(removeAllFormat); QAction *textsource = new QAction(tr("Edit document source"), this); - textsource->setShortcut(QKeySequence("CTRL+O")); + textsource->setShortcut(QKeySequence(QString::fromUtf8("CTRL+O"))); connect(textsource, SIGNAL(triggered()), this, SLOT(textSource())); f_textedit->addAction(textsource); @@ -188,29 +192,19 @@ MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent) // font size QFontDatabase db; - foreach(int size, db.standardSizes()) + for(int size: db.standardSizes()) { f_fontsize->addItem(QString::number(size)); + } //TODO: void QComboBox::setEditText(const QString &text) to " " when multiple select - -// connect(f_fontsize, SIGNAL(activated(QString)), -// this, SLOT(textSize(QString))); connect(f_fontsize, SIGNAL(currentIndexChanged(QString)), this, SLOT(textSize(QString))); -// f_fontsize->setCurrentIndex(f_fontsize->findText(QString::number(QApplication::font() -// .pointSize()))); - // text foreground color -// QPixmap pix(16, 16); -// pix.fill(QApplication::palette().foreground().color()); -// f_fgcolor->setIcon(pix); + // text foreground color connect(f_fgcolor, SIGNAL(clicked()), this, SLOT(textFgColor())); // text background color -// pix.fill(QApplication::palette().background().color()); -// f_bgcolor->setIcon(pix); - connect(f_bgcolor, SIGNAL(clicked()), this, SLOT(textBgColor())); // images @@ -231,6 +225,15 @@ MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent) int fSize = f_fontsize->findText(QString::number(currSize)); f_fontsize ->setCurrentIndex(fSize); } else { + QTextCursor cursor = f_textedit->textCursor(); + cursor.movePosition(QTextCursor::Start); + f_textedit->setTextCursor(cursor); + + QTextCharFormat fmt = cursor.charFormat(); + fmt.setFontPointSize(getDefFontSizeNum()); + + addFontSize(getDefFontSize()); + f_fontsize->setCurrentIndex(f_fontsize->findText(getDefFontSize())); } } @@ -396,7 +399,7 @@ void MRichTextEdit::textStyle(int index) { } if (index == ParagraphMonospace) { fmt = cursor.charFormat(); - fmt.setFontFamily("Monospace"); + fmt.setFontFamily(QString::fromUtf8("Monospace")); fmt.setFontStyleHint(QFont::Monospace); fmt.setFontFixedPitch(true); } @@ -539,7 +542,7 @@ void MRichTextEdit::fontChanged(const QFont &f) { } else if (f.pointSize() == m_fontsize_h4) { f_paragraph->setCurrentIndex(ParagraphHeading4); } else { - if (f.fixedPitch() && f.family() == "Monospace") { + if (f.fixedPitch() && f.family() == QString::fromUtf8("Monospace")) { f_paragraph->setCurrentIndex(ParagraphMonospace); } else { f_paragraph->setCurrentIndex(ParagraphStandard); @@ -608,9 +611,13 @@ void MRichTextEdit::slotClipboardDataChanged() { QString MRichTextEdit::toHtml() const { QString s = f_textedit->toHtml(); // convert emails to links - s = s.replace(QRegExp("(<[^a][^>]+>(?:]+>)?|\\s)([a-zA-Z\\d]+@[a-zA-Z\\d]+\\.[a-zA-Z]+)"), "\\1\\2"); + s = s.replace(QRegExp( + QString::fromUtf8("(<[^a][^>]+>(?:]+>)?|\\s)([a-zA-Z\\d]+@[a-zA-Z\\d]+\\.[a-zA-Z]+)")), + QString::fromUtf8("\\1\\2")); // convert links - s = s.replace(QRegExp("(<[^a][^>]+>(?:]+>)?|\\s)((?:https?|ftp|file)://[^\\s'\"<>]+)"), "\\1\\2"); + s = s.replace(QRegExp( + QString::fromUtf8("(<[^a][^>]+>(?:]+>)?|\\s)((?:https?|ftp|file)://[^\\s'\"<>]+)")), + QString::fromUtf8( "\\1\\2")); // see also: Utils::linkify() return s; } @@ -640,7 +647,7 @@ void MRichTextEdit::setText(const QString& text) { setPlainText(text); return; } - if (text[0] == '<') { + if (text[0] == QChar::fromLatin1('<')) { setHtml(text); } else { setPlainText(text); @@ -649,15 +656,15 @@ void MRichTextEdit::setText(const QString& text) { void MRichTextEdit::insertImage() { QSettings s; - QString attdir = s.value("general/filedialog-path").toString(); + QString attdir = s.value(QString::fromUtf8("general/filedialog-path")).toString(); QString file = QFileDialog::getOpenFileName(this, tr("Select an image"), attdir, tr("JPEG (*.jpg);; GIF (*.gif);; PNG (*.png);; BMP (*.bmp);; All (*)")); QImage image = QImageReader(file).read(); - f_textedit->dropImage(image, QFileInfo(file).suffix().toUpper().toLocal8Bit().data() ); - + f_textedit->dropImage(image, + QFileInfo(file).suffix().toUpper()); } void MRichTextEdit::onSave(void) @@ -716,26 +723,49 @@ bool MRichTextEdit::hasMultipleSizes(void) return result; } - void MRichTextEdit::setDefFontSize(int fs) { +// Base::Console().Message("MRTE::setDefFontSize(%d)\n", fs); m_defFontSize = fs; - f_fontsize->findText(getDefFontSize()); m_fontsize_h1 = fs + 8; m_fontsize_h2 = fs + 6; m_fontsize_h3 = fs + 4; m_fontsize_h4 = fs + 2; + QString newSize = QString::number(fs); - f_fontsize->setCurrentIndex(f_fontsize->findText(newSize)); + f_fontsize->findText(newSize); + int idx = f_fontsize->findText(newSize); + if (idx > -1) { + f_fontsize->setCurrentIndex(idx); + } else { + f_fontsize->setCurrentIndex(0); + } textSize(newSize); } +int MRichTextEdit::getDefFontSizeNum(void) +{ +// Base::Console().Message("MRTE::getDefFontSizeNum()\n"); + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions"); + double fontSize = hGrp->GetFloat("FontSize", 5.0); // this is mm, not pts! + + //this conversion is only approximate. the factor changes for different fonts. +// double mmToPts = 2.83; //theoretical value + double mmToPts = 2.00; //practical value. seems to be reasonable for common fonts. + + int ptsSize = round(fontSize * mmToPts); + return ptsSize; +} + QString MRichTextEdit::getDefFontSize(void) { - QString result = QString::number(m_defFontSize); +// Base::Console().Message("MRTE::getDefFontSize()\n"); + QString result = QString::number(getDefFontSizeNum()); return result; } +//not used. void MRichTextEdit::setDefFont(QString f) { m_defFont = f; @@ -743,10 +773,51 @@ void MRichTextEdit::setDefFont(QString f) QFont MRichTextEdit::getDefFont(void) { + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Labels"); + std::string fontName = hGrp->GetASCII("LabelFont", "osifont"); + QString family = Base::Tools::fromStdString(fontName); + m_defFont = family; QFont result; - result.setFamily(m_defFont); + result.setFamily(family); return result; } +// add a new fontSize to the list +// this seems like massive overkill for integer point<->mm conversion factor +// if the conversion factor is float, will generate non-standard sizes +void MRichTextEdit::addFontSize(QString fs) +{ +// Base::Console().Message("MRTE::addFontSize(%s)\n", qPrintable(fs)); + QStringList newList; + int fsVal = fs.toInt(); + int size = f_fontsize->count(); + bool added = false; + for (int i = 0; i < size; i++) { + QString item = f_fontsize->itemText(i); + int itemVal = item.toInt(); + if (added) { + newList << item; + continue; + } + if (itemVal < fsVal) { + newList << item; + } else if (itemVal == fsVal) { // already in list + newList << item; + added = true; + } else { //item > fs, add both + newList << fs; + newList << item; + added = true; + } + } + if (!added) { //bigger than all choices, add to end of list + newList << fs; + } + f_fontsize->clear(); + f_fontsize->addItems(newList); + size = newList.size(); +} + #include diff --git a/src/Mod/TechDraw/Gui/mrichtextedit.h b/src/Mod/TechDraw/Gui/mrichtextedit.h index 0bec5bb3f5..4e5a31cc13 100644 --- a/src/Mod/TechDraw/Gui/mrichtextedit.h +++ b/src/Mod/TechDraw/Gui/mrichtextedit.h @@ -46,10 +46,10 @@ class MRichTextEdit : public QWidget, protected Ui::MRichTextEdit { QTextCursor textCursor() const { return f_textedit->textCursor(); } void setTextCursor(const QTextCursor& cursor) { f_textedit->setTextCursor(cursor); } void setMaxWidth(double w); -/* void setFontSize(double fs);*/ void setDefFontSize(int fs); void setDefFont(QString f); QString getDefFontSize(void); + int getDefFontSizeNum(void); QFont getDefFont(void); public slots: @@ -96,6 +96,7 @@ Q_SIGNALS: void focusInEvent(QFocusEvent *event); bool hasMultipleSizes(void); + void addFontSize(QString fs); QStringList m_paragraphItems; int m_fontsize_h1; From 0b4f82f280f6a1c0f866183c356cd66ba8d97a9b Mon Sep 17 00:00:00 2001 From: wandererfan Date: Wed, 15 Jan 2020 09:05:58 -0500 Subject: [PATCH 06/11] [TD]fix parenting in Tree --- src/Mod/TechDraw/Gui/TaskLeaderLine.cpp | 8 ++++++++ src/Mod/TechDraw/Gui/TaskRichAnno.cpp | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/Mod/TechDraw/Gui/TaskLeaderLine.cpp b/src/Mod/TechDraw/Gui/TaskLeaderLine.cpp index 5c03405863..ddfb437cfa 100644 --- a/src/Mod/TechDraw/Gui/TaskLeaderLine.cpp +++ b/src/Mod/TechDraw/Gui/TaskLeaderLine.cpp @@ -304,6 +304,14 @@ void TaskLeaderLine::createLeaderFeature(std::vector converted) Gui::Command::updateActive(); Gui::Command::commitCommand(); + + //trigger claimChildren in tree + if (m_baseFeat != nullptr) { + m_baseFeat->touch(); + } + if (m_basePage != nullptr) { + m_basePage->touch(); + } m_lineFeat->requestPaint(); } diff --git a/src/Mod/TechDraw/Gui/TaskRichAnno.cpp b/src/Mod/TechDraw/Gui/TaskRichAnno.cpp index ce3ab6fb2e..fec698e24f 100644 --- a/src/Mod/TechDraw/Gui/TaskRichAnno.cpp +++ b/src/Mod/TechDraw/Gui/TaskRichAnno.cpp @@ -311,6 +311,14 @@ void TaskRichAnno::createAnnoFeature() Gui::Command::updateActive(); Gui::Command::commitCommand(); + + //trigger collectChildren in tree + if (m_baseFeat != nullptr) { + m_baseFeat->touch(); + } + if (m_basePage != nullptr) { + m_basePage->touch(); + } m_annoFeat->requestPaint(); } From efa4cb66a272efae79c5bb2a31a9906dcfa4f125 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 16 Jan 2020 13:28:01 +0100 Subject: [PATCH 07/11] Gui: allow to dump only the visible part of the scene graph Gui.ActiveDocument.ActiveView.dump("scene.iv", True) The second parameter is optional and by default False --- src/Gui/View3DInventor.cpp | 19 ++++++++++++++++--- src/Gui/View3DInventor.h | 2 +- src/Gui/View3DPy.cpp | 7 ++++--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index fc6bc76288..b0228fe3c1 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -823,16 +823,29 @@ void View3DInventor::restoreOverrideCursor() _viewer->getWidget()->setCursor(QCursor(Qt::ArrowCursor)); } -void View3DInventor::dump(const char* filename) +// defined in SoFCDB.cpp +extern SoNode* replaceSwitchesInSceneGraph(SoNode*); + +void View3DInventor::dump(const char* filename, bool onlyVisible) { SoGetPrimitiveCountAction action; action.setCanApproximate(true); action.apply(_viewer->getSceneGraph()); + SoNode* node = _viewer->getSceneGraph(); + if (onlyVisible) { + node = replaceSwitchesInSceneGraph(node); + node->ref(); + } + if ( action.getTriangleCount() > 100000 || action.getPointCount() > 30000 || action.getLineCount() > 10000 ) - _viewer->dumpToFile(_viewer->getSceneGraph(), filename, true); + _viewer->dumpToFile(node, filename, true); else - _viewer->dumpToFile(_viewer->getSceneGraph(), filename, false); + _viewer->dumpToFile(node, filename, false); + + if (onlyVisible) { + node->unref(); + } } void View3DInventor::windowStateChanged(MDIView* view) diff --git a/src/Gui/View3DInventor.h b/src/Gui/View3DInventor.h index 5e22c96192..76534a2851 100644 --- a/src/Gui/View3DInventor.h +++ b/src/Gui/View3DInventor.h @@ -113,7 +113,7 @@ public Q_SLOTS: void setOverrideCursor(const QCursor&); void restoreOverrideCursor(); - void dump(const char* filename); + void dump(const char* filename, bool onlyVisible=false); protected Q_SLOTS: void stopAnimating(); diff --git a/src/Gui/View3DPy.cpp b/src/Gui/View3DPy.cpp index fe967a4d54..bc73deca01 100644 --- a/src/Gui/View3DPy.cpp +++ b/src/Gui/View3DPy.cpp @@ -113,7 +113,7 @@ void View3DInventorPy::init_type() add_varargs_method("stopAnimating",&View3DInventorPy::stopAnimating,"stopAnimating()"); add_varargs_method("setAnimationEnabled",&View3DInventorPy::setAnimationEnabled,"setAnimationEnabled()"); add_varargs_method("isAnimationEnabled",&View3DInventorPy::isAnimationEnabled,"isAnimationEnabled()"); - add_varargs_method("dump",&View3DInventorPy::dump,"dump()"); + add_varargs_method("dump",&View3DInventorPy::dump,"dump(filename, [onlyVisible=False])"); add_varargs_method("dumpNode",&View3DInventorPy::dumpNode,"dumpNode(node)"); add_varargs_method("setStereoType",&View3DInventorPy::setStereoType,"setStereoType()"); add_varargs_method("getStereoType",&View3DInventorPy::getStereoType,"getStereoType()"); @@ -1233,11 +1233,12 @@ Py::Object View3DInventorPy::listCameraTypes(const Py::Tuple& args) Py::Object View3DInventorPy::dump(const Py::Tuple& args) { char* filename; - if (!PyArg_ParseTuple(args.ptr(), "s", &filename)) + PyObject *onlyVisible = Py_False; + if (!PyArg_ParseTuple(args.ptr(), "s|O", &filename, &onlyVisible)) throw Py::Exception(); try { - _view->dump(filename); + _view->dump(filename, PyObject_IsTrue(onlyVisible)); return Py::None(); } catch (const Base::Exception& e) { From 96ad0d9f37fa51693a79f3160373533d8c936b96 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Sun, 12 Jan 2020 18:33:59 -0500 Subject: [PATCH 08/11] [TD]Balloon ends and kink --- src/Mod/TechDraw/App/DrawViewBalloon.cpp | 29 +++-- src/Mod/TechDraw/App/DrawViewBalloon.h | 16 ++- src/Mod/TechDraw/Gui/QGIArrow.cpp | 94 ++++++++------- src/Mod/TechDraw/Gui/QGIArrow.h | 3 +- src/Mod/TechDraw/Gui/QGIPrimPath.cpp | 13 ++- src/Mod/TechDraw/Gui/QGIPrimPath.h | 2 + src/Mod/TechDraw/Gui/QGIViewBalloon.cpp | 139 +++++++++++++++-------- src/Mod/TechDraw/Gui/QGIViewBalloon.h | 2 + src/Mod/TechDraw/Gui/TaskBalloon.ui | 5 + 9 files changed, 192 insertions(+), 111 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawViewBalloon.cpp b/src/Mod/TechDraw/App/DrawViewBalloon.cpp index 91293acdc7..06df033232 100644 --- a/src/Mod/TechDraw/App/DrawViewBalloon.cpp +++ b/src/Mod/TechDraw/App/DrawViewBalloon.cpp @@ -89,6 +89,7 @@ const char* DrawViewBalloon::endTypeEnums[]= { "FILLED_TRIANGLE", "OPEN_CIRCLE", "FORK", "PYRAMID", + "NONE", NULL}; //const char* DrawViewBalloon::endTypeEnums[]= {"Arrow", @@ -123,19 +124,15 @@ DrawViewBalloon::DrawViewBalloon(void) ADD_PROPERTY_TYPE(TextWrapLen,(-1),"",(App::PropertyType)(App::Prop_None),"Balloon symbol scale"); -// OriginX.setStatus(App::Property::Hidden,false); -// OriginY.setStatus(App::Property::Hidden,false); + ADD_PROPERTY_TYPE(KinkLength,(prefKinkLength()),"",(App::PropertyType)(App::Prop_None), + "Distance from symbol to leader kink"); + OriginIsSet.setStatus(App::Property::Hidden,false); OriginIsSet.setStatus(App::Property::ReadOnly,true); SourceView.setScope(App::LinkScope::Global); -// SourceView.setStatus(App::Property::Hidden,true); Rotation.setStatus(App::Property::Hidden,true); -// ScaleType.setStatus(App::Property::Hidden,true); -// Scale.setStatus(App::Property::Hidden,true); Caption.setStatus(App::Property::Hidden,true); -// X.setStatus(App::Property::Hidden,true); -// Y.setStatus(App::Property::Hidden,true); } DrawViewBalloon::~DrawViewBalloon() @@ -145,6 +142,14 @@ DrawViewBalloon::~DrawViewBalloon() void DrawViewBalloon::onChanged(const App::Property* prop) { + if (!isRestoring()) { + if ( (prop == &EndType) || + (prop == &Symbol) || + (prop == &Text) || + (prop == &KinkLength) ) { + requestPaint(); + } + } DrawView::onChanged(prop); } @@ -255,6 +260,16 @@ App::DocumentObjectExecReturn *DrawViewBalloon::execute(void) requestPaint(); return App::DocumentObject::execute(); } + +double DrawViewBalloon::prefKinkLength(void) const +{ + Base::Reference hGrp = App::GetApplication().GetUserParameter(). + GetGroup("BaseApp")->GetGroup("Preferences")-> + GetGroup("Mod/TechDraw/Dimensions"); + double length = hGrp->GetFloat("BalloonKink", 5.0); + return length; +} + /* PyObject *DrawViewBalloon::getPyObject(void) { diff --git a/src/Mod/TechDraw/App/DrawViewBalloon.h b/src/Mod/TechDraw/App/DrawViewBalloon.h index b9c89d5898..82a1a8af74 100644 --- a/src/Mod/TechDraw/App/DrawViewBalloon.h +++ b/src/Mod/TechDraw/App/DrawViewBalloon.h @@ -60,6 +60,8 @@ public: App::PropertyBool OriginIsSet; App::PropertyFloat TextWrapLen; + App::PropertyDistance KinkLength; + short mustExecute() const override; DrawViewPart* getViewPart() const; @@ -68,9 +70,7 @@ public: //virtual PyObject *getPyObject(void); virtual App::DocumentObjectExecReturn *execute(void) override; - //@} - /// returns the type name of the ViewProvider virtual const char* getViewProviderName(void) const override { return "TechDrawGui::ViewProviderBalloon"; } @@ -80,11 +80,17 @@ public: void handleXYLock(void) override; + double prefKinkLength(void) const; + + protected: void onChanged(const App::Property* prop) override; -/* virtual void onDocumentRestored();*/ - virtual void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop) override; - virtual void handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName) override; + virtual void handleChangedPropertyType(Base::XMLReader &reader, + const char *TypeName, + App::Property * prop) override; + virtual void handleChangedPropertyName(Base::XMLReader &reader, + const char * TypeName, + const char *PropName) override; private: }; diff --git a/src/Mod/TechDraw/Gui/QGIArrow.cpp b/src/Mod/TechDraw/Gui/QGIArrow.cpp index 810068910d..72d70781ab 100644 --- a/src/Mod/TechDraw/Gui/QGIArrow.cpp +++ b/src/Mod/TechDraw/Gui/QGIArrow.cpp @@ -43,7 +43,7 @@ using namespace TechDrawGui; QGIArrow::QGIArrow() : m_fill(Qt::SolidPattern), - m_size(5.0), + m_size(getPrefArrowSize()), m_style(0), m_dirMode(false), m_dir(Base::Vector3d(1.0,0.0,0.0)) @@ -63,45 +63,39 @@ QGIArrow::QGIArrow() : void QGIArrow::draw() { QPainterPath path; if (m_style == FILLED_TRIANGLE) { - setFillStyle(Qt::SolidPattern); if (m_dirMode) { path = makeFilledTriangle(getDirection(), m_size,m_size/6.0); } else { path = makeFilledTriangle(m_size,m_size/6.0,isFlipped()); //"arrow l/w sb 3/1" ?? } } else if (m_style == OPEN_ARROW) { - setFillStyle(Qt::NoBrush); if (m_dirMode) { path = makeOpenArrow(getDirection(), m_size,m_size/3.0); //broad arrow? } else { path = makeOpenArrow(m_size,m_size/3.0,isFlipped()); } } else if (m_style == HASH_MARK) { - setFillStyle(Qt::NoBrush); if (m_dirMode) { path = makeHashMark(getDirection(), m_size/2.0,m_size/2.0); //big enough? } else { path = makeHashMark(m_size/2.0,m_size/2.0,isFlipped()); //big enough? } } else if (m_style == DOT) { - setFillStyle(Qt::SolidPattern); path = makeDot(m_size/2.0,m_size/2.0,isFlipped()); } else if (m_style == OPEN_CIRCLE) { path = makeOpenDot(m_size/2.0,m_size/2.0,isFlipped()); } else if (m_style == FORK) { - setFillStyle(Qt::NoBrush); if (m_dirMode) { path = makeForkArrow(getDirection(), m_size/2.0,m_size/2.0); //big enough? } else { path = makeForkArrow(m_size/2.0,m_size/2.0,isFlipped()); //big enough? } } else if (m_style == PYRAMID){ - setFillStyle(Qt::SolidPattern); - if (m_dirMode) { - path = makePyramid(getDirection(), m_size); - } else { - path = makePyramid(m_size,isFlipped()); - } + if (m_dirMode) { + path = makePyramid(getDirection(), m_size); + } else { + path = makePyramid(m_size,isFlipped()); + } }else { path = makeFilledTriangle(m_size,m_size/6.0,isFlipped()); //sb a question mark or ??? } @@ -271,50 +265,51 @@ QPainterPath QGIArrow::makeForkArrow(Base::Vector3d dir, double length, double w QPainterPath QGIArrow::makePyramid(double length, bool flipped) { - double half_width = length/2.; - double top = -length; - double base = 0.; - // [(0,-width), (0, width)] is base of arrow - if (flipped) { - top = 0.; - base = -length; - } - top = Rez::guiX(top); - base = Rez::guiX(base); - QPainterPath path; - path.moveTo(QPointF(top, 0.)); - path.lineTo(QPointF(base,Rez::guiX(-half_width))); - path.lineTo(QPointF(base,Rez::guiX(half_width))); - path.closeSubpath(); - setFillStyle(Qt::SolidPattern); - return path; + double half_width = length/2.; + double top = -length; + double base = 0.; + // [(0,-width), (0, width)] is base of arrow + if (flipped) { + top = 0.; + base = -length; + } + top = Rez::guiX(top); + base = Rez::guiX(base); + QPainterPath path; + path.moveTo(QPointF(top, 0.)); + path.lineTo(QPointF(base,Rez::guiX(-half_width))); + path.lineTo(QPointF(base,Rez::guiX(half_width))); + path.closeSubpath(); + setFillStyle(Qt::SolidPattern); + return path; } QPainterPath QGIArrow::makePyramid(Base::Vector3d dir, double length) { - //(0,0) is tip of arrow - // dir is direction arrow points - Base::Vector3d negDir = -dir; - negDir.Normalize(); - double width = length / 2.; - Base::Vector3d perp(-negDir.y,negDir.x, 0.0); - Base::Vector3d barb1 = perp * width; - Base::Vector3d barb2 = perp * -width; - Base::Vector3d top = negDir * length; + //(0,0) is tip of arrow + // dir is direction arrow points + Base::Vector3d negDir = -dir; + negDir.Normalize(); + double width = length / 2.; + Base::Vector3d perp(-negDir.y,negDir.x, 0.0); + Base::Vector3d barb1 = perp * width; + Base::Vector3d barb2 = perp * -width; + Base::Vector3d top = negDir * length; - QPainterPath path; - path.moveTo(QPointF(Rez::guiX(top.x),Rez::guiX(top.y))); - path.lineTo(QPointF(Rez::guiX(barb1.x),Rez::guiX(barb1.y))); - path.lineTo(QPointF(Rez::guiX(barb2.x),Rez::guiX(barb2.y))); - path.closeSubpath(); - setFillStyle(Qt::SolidPattern); - return path; + QPainterPath path; + path.moveTo(QPointF(Rez::guiX(top.x),Rez::guiX(top.y))); + path.lineTo(QPointF(Rez::guiX(barb1.x),Rez::guiX(barb1.y))); + path.lineTo(QPointF(Rez::guiX(barb2.x),Rez::guiX(barb2.y))); + path.closeSubpath(); + setFillStyle(Qt::SolidPattern); + return path; } int QGIArrow::getPrefArrowStyle() { Base::Reference hGrp = App::GetApplication().GetUserParameter(). - GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions"); + GetGroup("BaseApp")->GetGroup("Preferences")-> + GetGroup("Mod/TechDraw/Dimensions"); int style = hGrp->GetInt("ArrowStyle", 0); return style; } @@ -356,8 +351,11 @@ double QGIArrow::getOverlapAdjust(int style, double size) result = 0.0; break; case PYRAMID: - result = 0.0; - break; + result = size; + break; + case NONE: + result = 0.0; + break; default: //unknown result = 1.0; } diff --git a/src/Mod/TechDraw/Gui/QGIArrow.h b/src/Mod/TechDraw/Gui/QGIArrow.h index 05b6228304..26a704ef73 100644 --- a/src/Mod/TechDraw/Gui/QGIArrow.h +++ b/src/Mod/TechDraw/Gui/QGIArrow.h @@ -42,7 +42,8 @@ enum ArrowType { DOT, OPEN_CIRCLE, FORK, - PYRAMID + PYRAMID, + NONE }; class TechDrawGuiExport QGIArrow : public QGIPrimPath diff --git a/src/Mod/TechDraw/Gui/QGIPrimPath.cpp b/src/Mod/TechDraw/Gui/QGIPrimPath.cpp index 3fea640c21..4af6fbfe2b 100644 --- a/src/Mod/TechDraw/Gui/QGIPrimPath.cpp +++ b/src/Mod/TechDraw/Gui/QGIPrimPath.cpp @@ -43,8 +43,9 @@ using namespace TechDrawGui; QGIPrimPath::QGIPrimPath(): m_width(0), m_capStyle(Qt::RoundCap), - m_fillStyleCurrent (Qt::NoBrush) -// m_fillStyleCurrent (Qt::SolidPattern) + m_fillStyleCurrent (Qt::NoBrush), +// m_fillStyleCurrent (Qt::SolidPattern), + m_fillOverride(false) { setCacheMode(QGraphicsItem::NoCache); setFlag(QGraphicsItem::ItemIsSelectable, true); @@ -128,13 +129,17 @@ void QGIPrimPath::setPrettyNormal() { void QGIPrimPath::setPrettyPre() { // Base::Console().Message("QGIPP::setPrettyPre()\n"); m_colCurrent = getPreColor(); - m_fillColorCurrent = getPreColor(); + if (!m_fillOverride) { + m_fillColorCurrent = getPreColor(); + } } void QGIPrimPath::setPrettySel() { // Base::Console().Message("QGIPP::setPrettySel()\n"); m_colCurrent = getSelectColor(); - m_fillColorCurrent = getSelectColor(); + if (!m_fillOverride) { + m_fillColorCurrent = getSelectColor(); + } } //wf: why would a face use it's parent's normal colour? diff --git a/src/Mod/TechDraw/Gui/QGIPrimPath.h b/src/Mod/TechDraw/Gui/QGIPrimPath.h index 08ae7a0220..b7b0316176 100644 --- a/src/Mod/TechDraw/Gui/QGIPrimPath.h +++ b/src/Mod/TechDraw/Gui/QGIPrimPath.h @@ -68,6 +68,7 @@ public: void resetFill(); void setFillColor(QColor c); QColor getFillColor(void) { return m_colDefFill; } + void setFillOverride(bool b) { m_fillOverride = b; } protected: virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; @@ -101,6 +102,7 @@ protected: Qt::BrushStyle m_styleNormal; //current Normal fill style Qt::BrushStyle m_styleSelect; //Select/preSelect fill style + bool m_fillOverride; private: diff --git a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp index 615aa22920..c0587194f3 100644 --- a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp @@ -265,6 +265,8 @@ QGIViewBalloon::QGIViewBalloon() : balloonShape = new QGIDimLines(); addToGroup(balloonShape); balloonShape->setNormalColor(getNormalColor()); + balloonShape->setFill(Qt::white, Qt::SolidPattern); + balloonShape->setFillOverride(true); balloonShape->setPrettyNormal(); arrow = new QGIArrow(); @@ -272,6 +274,7 @@ QGIViewBalloon::QGIViewBalloon() : arrow->setNormalColor(getNormalColor()); arrow->setFillColor(getNormalColor()); arrow->setPrettyNormal(); + arrow->setStyle(prefDefaultArrow()); balloonLabel->setZValue(ZVALUE::LABEL); arrow->setZValue(ZVALUE::DIMENSION); @@ -279,7 +282,7 @@ QGIViewBalloon::QGIViewBalloon() : balloonLines->setZValue(ZVALUE::DIMENSION); balloonLines->setStyle(Qt::SolidLine); - balloonShape->setZValue(ZVALUE::DIMENSION); + balloonShape->setZValue(ZVALUE::DIMENSION + 1); //above balloonLines! balloonShape->setStyle(Qt::SolidLine); oldLabelCenter = new QPointF; @@ -305,7 +308,6 @@ QGIViewBalloon::QGIViewBalloon() : balloonLabel, SIGNAL(hover(bool)), this , SLOT (hover(bool))); -// toggleBorder(false); setZValue(ZVALUE::DIMENSION); } @@ -441,7 +443,6 @@ void QGIViewBalloon::balloonLabelDragFinished() return; } - //this needs to be scaled? double x = Rez::appX(balloonLabel->X()), y = Rez::appX(balloonLabel->Y()); Gui::Command::openCommand("Drag Balloon"); @@ -509,7 +510,7 @@ void QGIViewBalloon::draw() void QGIViewBalloon::draw_modifier(bool modifier) { - if (!isVisible()) { //should this be controlled by parent ViewPart? + if (!isVisible()) { return; } @@ -539,9 +540,6 @@ void QGIViewBalloon::draw_modifier(bool modifier) return; } - m_colNormal = getNormalColor(); -// balloonLabel->setColor(m_colNormal); - m_lineWidth = Rez::guiX(vp->LineWidth.getValue()); double textWidth = balloonLabel->getDimText()->boundingRect().width(); @@ -556,7 +554,7 @@ void QGIViewBalloon::draw_modifier(bool modifier) Base::Vector3d dLineStart; Base::Vector3d kinkPoint; - double kinkLength = Rez::guiX(5.0); + double kinkLength = Rez::guiX(balloon->KinkLength.getValue()); float orginX = Rez::guiX(balloon->OriginX.getValue()); float orginY = Rez::guiX(balloon->OriginY.getValue()); @@ -564,7 +562,7 @@ void QGIViewBalloon::draw_modifier(bool modifier) const char *balloonType = balloon->Symbol.getValueAsString(); float scale = balloon->SymbolScale.getValue(); - double offset = 0; + double offsetLR = 0; QPainterPath balloonPath; if (strcmp(balloonType, "Circular") == 0) { @@ -572,10 +570,10 @@ void QGIViewBalloon::draw_modifier(bool modifier) balloonRadius = balloonRadius * scale; balloonPath.moveTo(lblCenter.x, lblCenter.y); balloonPath.addEllipse(lblCenter.x - balloonRadius,lblCenter.y - balloonRadius, balloonRadius * 2, balloonRadius * 2); - offset = balloonRadius; + offsetLR = balloonRadius; } else if (strcmp(balloonType, "None") == 0) { balloonPath = QPainterPath(); - offset = (textWidth / 2.0) + Rez::guiX(2.0); + offsetLR = (textWidth / 2.0) + Rez::guiX(2.0); } else if (strcmp(balloonType, "Rectangle") == 0) { //Add some room textHeight = (textHeight * scale) + Rez::guiX(1.0); @@ -586,13 +584,14 @@ void QGIViewBalloon::draw_modifier(bool modifier) } } textWidth = (textWidth * scale) + Rez::guiX(2.0); + textHeight = (textHeight * scale) + Rez::guiX(2.0); balloonPath.addRect(lblCenter.x -(textWidth / 2.0), lblCenter.y - (textHeight / 2.0), textWidth, textHeight); - offset = (textWidth / 2.0); + offsetLR = (textWidth / 2.0); } else if (strcmp(balloonType, "Triangle") == 0) { double radius = sqrt(pow((textHeight / 2.0), 2) + pow((textWidth / 2.0), 2)); radius = radius * scale; radius += Rez::guiX(3.0); - offset = (tan(30 * M_PI / 180) * radius); + offsetLR = (tan(30 * M_PI / 180) * radius); QPolygonF triangle; double startAngle = -M_PI / 2; double angle = startAngle; @@ -612,19 +611,19 @@ void QGIViewBalloon::draw_modifier(bool modifier) balloonPath.arcTo(textBoxCorner.x() + textWidth - (textHeight / 2.0), textBoxCorner.y(), textHeight, textHeight, 90, -180); balloonPath.lineTo(textBoxCorner.x(), textBoxCorner.y() + textHeight); balloonPath.arcTo(textBoxCorner.x() - (textHeight / 2), textBoxCorner.y(), textHeight, textHeight, -90, -180); - offset = (textWidth / 2.0) + (textHeight / 2.0); + offsetLR = (textWidth / 2.0) + (textHeight / 2.0); } else if (strcmp(balloonType, "Square") == 0) { //Add some room textWidth = (textWidth * scale) + Rez::guiX(2.0); textHeight = (textHeight * scale) + Rez::guiX(1.0); double max = std::max(textWidth, textHeight); balloonPath.addRect(lblCenter.x -(max / 2.0), lblCenter.y - (max / 2.0), max, max); - offset = (max / 2.0); + offsetLR = (max / 2.0); } else if (strcmp(balloonType, "Hexagon") == 0) { double radius = sqrt(pow((textHeight / 2.0), 2) + pow((textWidth / 2.0), 2)); radius = radius * scale; radius += Rez::guiX(1.0); - offset = radius; + offsetLR = radius; QPolygonF triangle; double startAngle = -2 * M_PI / 3; double angle = startAngle; @@ -636,12 +635,20 @@ void QGIViewBalloon::draw_modifier(bool modifier) balloonPath.addPolygon(triangle); } - offset = (lblCenter.x < orginX) ? offset : -offset; - dLineStart.y = lblCenter.y; - dLineStart.x = lblCenter.x + offset; - kinkLength = (lblCenter.x < orginX) ? kinkLength : -kinkLength; - kinkPoint.y = dLineStart.y; - kinkPoint.x = dLineStart.x + kinkLength; + balloonShape->setPath(balloonPath); + + offsetLR = (lblCenter.x < orginX) ? offsetLR : -offsetLR ; + + if (DrawUtil::fpCompare(kinkLength, 0.0)) { //if no kink, then dLine start sb on line from center to arrow + dLineStart = lblCenter; + kinkPoint = dLineStart; + } else { + dLineStart.y = lblCenter.y; + dLineStart.x = lblCenter.x + offsetLR ; + kinkLength = (lblCenter.x < orginX) ? kinkLength : -kinkLength; + kinkPoint.y = dLineStart.y; + kinkPoint.x = dLineStart.x + kinkLength; + } QPainterPath dLinePath; dLinePath.moveTo(dLineStart.x, dLineStart.y); @@ -655,35 +662,61 @@ void QGIViewBalloon::draw_modifier(bool modifier) orginX = Rez::guiX(balloon->OriginX.getValue()); orginY = Rez::guiX(balloon->OriginY.getValue()); - dLinePath.lineTo(orginX, orginY); - oldLabelCenter->setX(lblCenter.x); oldLabelCenter->setY(lblCenter.y); - balloonLines->setPath(dLinePath); - balloonShape->setPath(balloonPath); - -// const char *endType = balloon->EndType.getValueAsString(); - -// if (strcmp(endType, "FILLED_TRIANGLE") == 0) { -// arrow->setStyle(QGIArrow::getPrefArrowStyle()); -// } else if (strcmp(endType, "DOT") == 0) { -// arrow->setStyle(3); -// } - + double xAdj = 0.0; + double yAdj = 0.0; int endType = balloon->EndType.getValue(); - arrow->setStyle(endType); + std::string endTypeString = balloon->EndType.getValueAsString(); + double arrowAdj = QGIArrow::getOverlapAdjust(endType, + QGIArrow::getPrefArrowSize()); - arrow->setSize(QGIArrow::getPrefArrowSize()); - arrow->draw(); + if (endTypeString == "NONE") { + arrow->hide(); + } else { + arrow->setStyle(endType); - Base::Vector3d orign(orginX, orginY, 0.0); - Base::Vector3d dirballoonLinesLine = (orign - kinkPoint).Normalize(); - float arAngle = atan2(dirballoonLinesLine.y, dirballoonLinesLine.x) * 180 / M_PI; + arrow->setSize(QGIArrow::getPrefArrowSize()); + arrow->draw(); - arrow->setPos(orginX, orginY); - arrow->setRotation(arAngle); - arrow->show(); + Base::Vector3d orign(orginX, orginY, 0.0); + Base::Vector3d dirballoonLinesLine; + if (!DrawUtil::fpCompare(kinkLength, 0.0)) { + dirballoonLinesLine = (orign - kinkPoint).Normalize(); + } else { + dirballoonLinesLine = (orign - dLineStart).Normalize(); + } + + float arAngle = atan2(dirballoonLinesLine.y, dirballoonLinesLine.x) * 180 / M_PI; + + arrow->setPos(orginX, orginY); + if ( (endTypeString == "PYRAMID") && + (prefOrthoPyramid()) ) { + if (arAngle < 0.0) { + arAngle += 360.0; + } + //set the angle to closest cardinal direction + if ( (45.0 < arAngle) && (arAngle < 135.0) ) { + arAngle = 90.0; + } else if ( (135.0 < arAngle) && (arAngle < 225.0) ) { + arAngle = 180.0; + } else if ( (225.0 < arAngle) && (arAngle < 315.0) ) { + arAngle = 270.0; + } else { + arAngle = 0; + } + double radAngle = arAngle * M_PI / 180.0; + double sinAngle = sin(radAngle); + double cosAngle = cos(radAngle); + xAdj = Rez::guiX(arrowAdj * cosAngle); + yAdj = Rez::guiX(arrowAdj * sinAngle); + } + arrow->setRotation(arAngle); + arrow->show(); + } + dLinePath.lineTo(orginX - xAdj, orginY - yAdj); + balloonLines->setPath(dLinePath); // redraw the Balloon and the parent View if (hasHover && !isSelected()) { @@ -694,9 +727,7 @@ void QGIViewBalloon::draw_modifier(bool modifier) setPrettyNormal(); } - update(); if (parentItem()) { - //TODO: parent redraw still required with new frame/label?? parentItem()->update(); } else { Base::Console().Log("INFO - QGIVB::draw - no parent to update\n"); @@ -707,6 +738,9 @@ void QGIViewBalloon::draw_modifier(bool modifier) void QGIViewBalloon::setPrettyPre(void) { arrow->setPrettyPre(); + //TODO: primPath needs override for fill + //balloonShape->setFillOverride(true); //don't fill with pre or select colours. +// balloonShape->setFill(Qt::white, Qt::NoBrush); balloonShape->setPrettyPre(); balloonLines->setPrettyPre(); } @@ -715,6 +749,7 @@ void QGIViewBalloon::setPrettySel(void) { // Base::Console().Message("QGIVBal::setPrettySel()\n"); arrow->setPrettySel(); +// balloonShape->setFill(Qt::white, Qt::NoBrush); balloonShape->setPrettySel(); balloonLines->setPrettySel(); } @@ -722,6 +757,7 @@ void QGIViewBalloon::setPrettySel(void) void QGIViewBalloon::setPrettyNormal(void) { arrow->setPrettyNormal(); +// balloonShape->setFill(Qt::white, Qt::SolidPattern); balloonShape->setPrettyNormal(); balloonLines->setPrettyNormal(); } @@ -794,4 +830,15 @@ int QGIViewBalloon::prefDefaultArrow() const return arrow; } + +//should this be an object property or global preference? +//when would you want a crooked pyramid? +bool QGIViewBalloon::prefOrthoPyramid() const +{ + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions"); + bool ortho = hGrp->GetBool("OrthoPyramid", true); + return ortho; +} + #include diff --git a/src/Mod/TechDraw/Gui/QGIViewBalloon.h b/src/Mod/TechDraw/Gui/QGIViewBalloon.h index 2351f5f016..06de3cce51 100644 --- a/src/Mod/TechDraw/Gui/QGIViewBalloon.h +++ b/src/Mod/TechDraw/Gui/QGIViewBalloon.h @@ -151,6 +151,8 @@ public: virtual QColor getNormalColor(void) override; int prefDefaultArrow() const; + bool prefOrthoPyramid() const; + public Q_SLOTS: void balloonLabelDragged(bool ctrl); diff --git a/src/Mod/TechDraw/Gui/TaskBalloon.ui b/src/Mod/TechDraw/Gui/TaskBalloon.ui index d568ffef22..66cdec699e 100644 --- a/src/Mod/TechDraw/Gui/TaskBalloon.ui +++ b/src/Mod/TechDraw/Gui/TaskBalloon.ui @@ -92,6 +92,11 @@ :/icons/arrowpyramid.svg:/icons/arrowpyramid.svg + + + NONE + + From 1665aee5a391a68f4e5164adf20053a1bb096fc3 Mon Sep 17 00:00:00 2001 From: WandererFan Date: Wed, 15 Jan 2020 22:52:00 -0500 Subject: [PATCH 09/11] [TD]fix crash on Section apply --- src/Mod/TechDraw/Gui/TaskSectionView.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Mod/TechDraw/Gui/TaskSectionView.cpp b/src/Mod/TechDraw/Gui/TaskSectionView.cpp index 7b7a16bf35..964a63ebd5 100644 --- a/src/Mod/TechDraw/Gui/TaskSectionView.cpp +++ b/src/Mod/TechDraw/Gui/TaskSectionView.cpp @@ -277,19 +277,23 @@ void TaskSectionView::onApplyClicked(bool b) bool TaskSectionView::apply(void) { // Base::Console().Message("TSV::apply() - m_dirName: %s\n", m_dirName.c_str()); + if (m_dirName.empty()) { + std::string msg = Base::Tools::toStdString(tr("TaskSectionView::apply - No section direction picked yet")); + Base::Console().Error((msg + "\n").c_str()); + return false; + } + if (m_section == nullptr) { + return false; + } App::Document* doc = m_section->getDocument(); App::DocumentObject* baseObj = doc->getObject(m_saveBaseName.c_str()); TechDraw::DrawViewPart* dvp = dynamic_cast(baseObj); if (dvp == nullptr) { return false; } - if (m_dirName.empty()) { - std::string msg = Base::Tools::toStdString(tr("TSV::apply - No section direction picked yet")); - Base::Console().Error((msg + "\n").c_str()); - } else { - checkAll(false); - applyQuick(m_dirName); - } + + checkAll(false); + applyQuick(m_dirName); return true; } From 6985ecec0761067106d0cd6022b515714cc732a8 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 16 Jan 2020 13:53:26 +0100 Subject: [PATCH 10/11] CMake: [skip ci] report which C++ standard is required --- cMake/FreeCAD_Helpers/PrintFinalReport.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cMake/FreeCAD_Helpers/PrintFinalReport.cmake b/cMake/FreeCAD_Helpers/PrintFinalReport.cmake index d464ae1585..7ca07d2b02 100644 --- a/cMake/FreeCAD_Helpers/PrintFinalReport.cmake +++ b/cMake/FreeCAD_Helpers/PrintFinalReport.cmake @@ -10,6 +10,7 @@ macro(PrintFinalReport) message(STATUS "Compiler: ${CMAKE_CXX_COMPILER} (${CMAKE_CXX_COMPILER_VERSION})") message(STATUS "Flags: ${CMAKE_CXX_FLAGS}") + message(STATUS "Standard: Requires C++${CMAKE_CXX_STANDARD}") # Qt5 needs/sets PYTHON_CONFIG_SUFFIX regarding Shiboken message(STATUS "Python: [${PYTHON_EXECUTABLE}] [${PYTHON_CONFIG_SUFFIX}]") From 0691ba92814ec14ee059a451b9f6e7296e6ce489 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Thu, 16 Jan 2020 13:56:30 +0100 Subject: [PATCH 11/11] FEM: examples, set input splitted input file writing to False --- src/Mod/Fem/femexamples/boxanalysis.py | 1 + src/Mod/Fem/femexamples/ccx_cantilever_std.py | 1 + src/Mod/Fem/femexamples/material_multiple_twoboxes.py | 1 + src/Mod/Fem/femexamples/material_nl_platewithhole.py | 1 + src/Mod/Fem/femexamples/rc_wall_2d.py | 1 + src/Mod/Fem/femexamples/thermomech_flow1d.py | 1 + src/Mod/Fem/femexamples/thermomech_spine.py | 1 + 7 files changed, 7 insertions(+) diff --git a/src/Mod/Fem/femexamples/boxanalysis.py b/src/Mod/Fem/femexamples/boxanalysis.py index 409b8db6a9..e5092c76dd 100644 --- a/src/Mod/Fem/femexamples/boxanalysis.py +++ b/src/Mod/Fem/femexamples/boxanalysis.py @@ -105,6 +105,7 @@ def setup_static(doc=None, solvertype="ccxtools"): elif solvertype == "z88": analysis.addObject(ObjectsFem.makeSolverZ88(doc, "SolverZ88")) if solvertype == "calculix" or solvertype == "ccxtools": + solver_object.SplitInputWriter = False solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_std.py b/src/Mod/Fem/femexamples/ccx_cantilever_std.py index 077d6e7977..ef46e173d1 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_std.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_std.py @@ -70,6 +70,7 @@ def setup_cantileverbase(doc=None, solvertype="ccxtools"): elif solvertype == "z88": analysis.addObject(ObjectsFem.makeSolverZ88(doc, "SolverZ88")) if solvertype == "calculix" or solvertype == "ccxtools": + solver_object.SplitInputWriter = False solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False diff --git a/src/Mod/Fem/femexamples/material_multiple_twoboxes.py b/src/Mod/Fem/femexamples/material_multiple_twoboxes.py index 4aa61038eb..603a95bf02 100644 --- a/src/Mod/Fem/femexamples/material_multiple_twoboxes.py +++ b/src/Mod/Fem/femexamples/material_multiple_twoboxes.py @@ -89,6 +89,7 @@ def setup(doc=None, solvertype="ccxtools"): )[0] solver_object.WorkingDir = u"" if solvertype == "calculix" or solvertype == "ccxtools": + solver_object.SplitInputWriter = False solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False diff --git a/src/Mod/Fem/femexamples/material_nl_platewithhole.py b/src/Mod/Fem/femexamples/material_nl_platewithhole.py index 646cbf3047..3c060369cc 100644 --- a/src/Mod/Fem/femexamples/material_nl_platewithhole.py +++ b/src/Mod/Fem/femexamples/material_nl_platewithhole.py @@ -96,6 +96,7 @@ def setup(doc=None, solvertype="ccxtools"): )[0] solver.WorkingDir = u"" if solvertype == "calculix" or solvertype == "ccxtools": + solver.SplitInputWriter = False solver.AnalysisType = "static" solver.GeometricalNonlinearity = "linear" solver.ThermoMechSteadyState = False diff --git a/src/Mod/Fem/femexamples/rc_wall_2d.py b/src/Mod/Fem/femexamples/rc_wall_2d.py index 1f19b6f24f..ac22afa666 100644 --- a/src/Mod/Fem/femexamples/rc_wall_2d.py +++ b/src/Mod/Fem/femexamples/rc_wall_2d.py @@ -85,6 +85,7 @@ def setup(doc=None, solvertype="ccxtools"): )[0] solver.WorkingDir = u"" if solvertype == "calculix" or solvertype == "ccxtools": + solver.SplitInputWriter = False solver.AnalysisType = "static" solver.GeometricalNonlinearity = "linear" solver.ThermoMechSteadyState = False diff --git a/src/Mod/Fem/femexamples/thermomech_flow1d.py b/src/Mod/Fem/femexamples/thermomech_flow1d.py index 929e0ab06b..0e4532030e 100644 --- a/src/Mod/Fem/femexamples/thermomech_flow1d.py +++ b/src/Mod/Fem/femexamples/thermomech_flow1d.py @@ -101,6 +101,7 @@ def setup(doc=None, solvertype="ccxtools"): )[0] solver_object.WorkingDir = u"" if solvertype == "calculix" or solvertype == "ccxtools": + solver_object.SplitInputWriter = False solver_object.AnalysisType = "thermomech" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = True diff --git a/src/Mod/Fem/femexamples/thermomech_spine.py b/src/Mod/Fem/femexamples/thermomech_spine.py index 28bd4c4e32..ebd85ce6f1 100644 --- a/src/Mod/Fem/femexamples/thermomech_spine.py +++ b/src/Mod/Fem/femexamples/thermomech_spine.py @@ -70,6 +70,7 @@ def setup(doc=None, solvertype="ccxtools"): # elif solvertype == "elmer": # analysis.addObject(ObjectsFem.makeSolverElmer(doc, "SolverElmer")) if solvertype == "calculix" or solvertype == "ccxtools": + solver_object.SplitInputWriter = False solver_object.AnalysisType = "thermomech" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = True