diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp
index 2543ad72b..62a1c09ba 100644
--- a/src/Gui/Application.cpp
+++ b/src/Gui/Application.cpp
@@ -1036,7 +1036,7 @@ bool Application::activateWorkbench(const char* name)
}
Base::Console().Error("%s\n", (const char*)msg.toLatin1());
- Base::Console().Log("%s\n", e.getStackTrace().c_str());
+ Base::Console().Error("%s\n", e.getStackTrace().c_str());
if (!d->startingUp) {
wc.restoreCursor();
QMessageBox::critical(getMainWindow(), QObject::tr("Workbench failure"),
@@ -1279,10 +1279,9 @@ typedef void (*_qt_msg_handler_old)(QtMsgType type, const char *msg);
_qt_msg_handler_old old_qtmsg_handler = 0;
#if QT_VERSION >= 0x050000
-void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &qmsg)
+void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(context);
- const QChar *msg = qmsg.unicode();
#ifdef FC_DEBUG
switch (type)
{
@@ -1290,26 +1289,26 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
case QtInfoMsg:
#endif
case QtDebugMsg:
- Base::Console().Message("%s\n", msg);
+ Base::Console().Message("%s\n", msg.toUtf8().constData());
break;
case QtWarningMsg:
- Base::Console().Warning("%s\n", msg);
+ Base::Console().Warning("%s\n", msg.toUtf8().constData());
break;
case QtCriticalMsg:
- Base::Console().Error("%s\n", msg);
+ Base::Console().Error("%s\n", msg.toUtf8().constData());
break;
case QtFatalMsg:
- Base::Console().Error("%s\n", msg);
+ Base::Console().Error("%s\n", msg.toUtf8().constData());
abort(); // deliberately core dump
}
#ifdef FC_OS_WIN32
if (old_qtmsg_handler)
- (*old_qtmsg_handler)(type, context, qmsg);
+ (*old_qtmsg_handler)(type, context, msg);
#endif
#else
// do not stress user with Qt internals but write to log file if enabled
Q_UNUSED(type);
- Base::Console().Log("%s\n", msg);
+ Base::Console().Log("%s\n", msg.toUtf8().constData());
#endif
}
#else
diff --git a/src/Gui/OnlineDocumentation.h b/src/Gui/OnlineDocumentation.h
index b4ec736e7..3a7cf5744 100644
--- a/src/Gui/OnlineDocumentation.h
+++ b/src/Gui/OnlineDocumentation.h
@@ -69,7 +69,7 @@ public:
void pause();
void resume();
-private slots:
+private Q_SLOTS:
void readClient();
void discardClient();
diff --git a/src/Gui/QSint/actionpanel/taskheader_p.cpp b/src/Gui/QSint/actionpanel/taskheader_p.cpp
index 8ea426a25..42f18b9dc 100644
--- a/src/Gui/QSint/actionpanel/taskheader_p.cpp
+++ b/src/Gui/QSint/actionpanel/taskheader_p.cpp
@@ -195,7 +195,7 @@ void TaskHeader::leaveEvent ( QEvent * /*event*/ )
void TaskHeader::fold()
{
if (myExpandable) {
- emit activated();
+ Q_EMIT activated();
// Toggling the 'm_fold' member here may lead to inconsistencies with its ActionGroup.
// Thus, the method setFold() was added and called from ActionGroup when required.
#if 0
@@ -254,7 +254,7 @@ void TaskHeader::changeIcons()
void TaskHeader::mouseReleaseEvent ( QMouseEvent * event )
{
if (event->button() == Qt::LeftButton) {
- emit activated();
+ Q_EMIT activated();
}
}
diff --git a/src/Gui/Quarter/ContextMenu.h b/src/Gui/Quarter/ContextMenu.h
index ac44f98dd..a9965001e 100644
--- a/src/Gui/Quarter/ContextMenu.h
+++ b/src/Gui/Quarter/ContextMenu.h
@@ -50,7 +50,7 @@ public:
QMenu * getMenu(void) const;
-public slots:
+public Q_SLOTS:
void changeRenderMode(QAction * action);
void changeStereoMode(QAction * action);
void changeTransparencyType(QAction * action);
diff --git a/src/Gui/Quarter/SensorManager.h b/src/Gui/Quarter/SensorManager.h
index 4b3fb7d0d..6344cf93e 100644
--- a/src/Gui/Quarter/SensorManager.h
+++ b/src/Gui/Quarter/SensorManager.h
@@ -48,7 +48,7 @@ public:
SensorManager(void);
~SensorManager();
-public slots:
+public Q_SLOTS:
void idleTimeout(void);
void delayTimeout(void);
void timerQueueTimeout(void);
diff --git a/src/Gui/Quarter/SignalThread.cpp b/src/Gui/Quarter/SignalThread.cpp
index 2b7254d3c..6d18f8636 100644
--- a/src/Gui/Quarter/SignalThread.cpp
+++ b/src/Gui/Quarter/SignalThread.cpp
@@ -70,7 +70,7 @@ SignalThread::run(void)
// just wait, and trigger every time we receive a signal
this->waitcond.wait(&this->mutex);
if (!this->isstopped) {
- emit triggerSignal();
+ Q_EMIT triggerSignal();
}
}
}
diff --git a/src/Gui/iisTaskPanel/src/iisiconlabel.cpp b/src/Gui/iisTaskPanel/src/iisiconlabel.cpp
index f014cbf3c..f967eacc3 100644
--- a/src/Gui/iisTaskPanel/src/iisiconlabel.cpp
+++ b/src/Gui/iisTaskPanel/src/iisiconlabel.cpp
@@ -9,193 +9,193 @@
#include "iistaskpanelscheme.h"
iisIconLabel::iisIconLabel(const QIcon &icon, const QString &title, QWidget *parent)
- : QWidget(parent),
- myPixmap(icon),
- myText(title),
- mySchemePointer(0),
- m_over(false),
- m_pressed(false),
- m_changeCursorOver(true),
- m_underlineOver(true)
+ : QWidget(parent),
+ myPixmap(icon),
+ myText(title),
+ mySchemePointer(0),
+ m_over(false),
+ m_pressed(false),
+ m_changeCursorOver(true),
+ m_underlineOver(true)
{
- setFocusPolicy(Qt::StrongFocus);
- setCursor(Qt::PointingHandCursor);
+ setFocusPolicy(Qt::StrongFocus);
+ setCursor(Qt::PointingHandCursor);
- myFont.setWeight(0);
- myPen.setStyle(Qt::NoPen);
+ myFont.setWeight(0);
+ myPen.setStyle(Qt::NoPen);
- myColor = myColorOver = myColorDisabled = QColor();
+ myColor = myColorOver = myColorDisabled = QColor();
}
iisIconLabel::~iisIconLabel()
{
- //if (m_changeCursorOver)
- // QApplication::restoreOverrideCursor();
+ //if (m_changeCursorOver)
+ // QApplication::restoreOverrideCursor();
}
void iisIconLabel::setSchemePointer(iisIconLabelScheme **pointer)
{
- mySchemePointer = pointer;
- update();
+ mySchemePointer = pointer;
+ update();
}
void iisIconLabel::setColors(const QColor &color, const QColor &colorOver, const QColor &colorOff)
{
- myColor = color;
- myColorOver = colorOver;
- myColorDisabled = colorOff;
- update();
+ myColor = color;
+ myColorOver = colorOver;
+ myColorDisabled = colorOff;
+ update();
}
void iisIconLabel::setFont(const QFont &font)
{
- myFont = font;
- update();
+ myFont = font;
+ update();
}
void iisIconLabel::setFocusPen(const QPen &pen)
{
- myPen = pen;
- update();
+ myPen = pen;
+ update();
}
QSize iisIconLabel::sizeHint() const
{
- return minimumSize();
+ return minimumSize();
}
QSize iisIconLabel::minimumSizeHint() const
{
- int s = (mySchemePointer && *mySchemePointer) ? (*mySchemePointer)->iconSize : 16;
- QPixmap px = myPixmap.pixmap(s,s,
- isEnabled() ? QIcon::Normal : QIcon::Disabled);
+ int s = (mySchemePointer && *mySchemePointer) ? (*mySchemePointer)->iconSize : 16;
+ QPixmap px = myPixmap.pixmap(s,s,
+ isEnabled() ? QIcon::Normal : QIcon::Disabled);
- int h = 4+px.height();
- int w = 8 + px.width();
- if (!myText.isEmpty()) {
- QFontMetrics fm(myFont);
- w += fm.width(myText);
- h = qMax(h, 4+fm.height());
- }
+ int h = 4+px.height();
+ int w = 8 + px.width();
+ if (!myText.isEmpty()) {
+ QFontMetrics fm(myFont);
+ w += fm.width(myText);
+ h = qMax(h, 4+fm.height());
+ }
- return QSize(w+2,h+2);
+ return QSize(w+2,h+2);
}
-void iisIconLabel::paintEvent ( QPaintEvent * event )
+void iisIconLabel::paintEvent ( QPaintEvent * event )
{
- Q_UNUSED(event);
- QPainter p(this);
+ Q_UNUSED(event);
+ QPainter p(this);
- QRect textRect(rect().adjusted(0,0,-1,0));
+ QRect textRect(rect().adjusted(0,0,-1,0));
- int x = 2;
+ int x = 2;
- if (!myPixmap.isNull()) {
- int s = (mySchemePointer && *mySchemePointer) ? (*mySchemePointer)->iconSize : 16;
- QPixmap px = myPixmap.pixmap(s,s,
- isEnabled() ? QIcon::Normal : QIcon::Disabled);
- p.drawPixmap(x,0,px);
- x += px.width() + 4;
- }
+ if (!myPixmap.isNull()) {
+ int s = (mySchemePointer && *mySchemePointer) ? (*mySchemePointer)->iconSize : 16;
+ QPixmap px = myPixmap.pixmap(s,s,
+ isEnabled() ? QIcon::Normal : QIcon::Disabled);
+ p.drawPixmap(x,0,px);
+ x += px.width() + 4;
+ }
- if (!myText.isEmpty()) {
- QColor text = myColor, textOver = myColorOver, textOff = myColorDisabled;
- QFont fnt = myFont;
- QPen focusPen = myPen;
- bool underline = m_underlineOver/*, cursover = m_changeCursorOver*/;
- if (mySchemePointer && *mySchemePointer) {
- if (!text.isValid()) text = (*mySchemePointer)->text;
- if (!textOver.isValid()) textOver = (*mySchemePointer)->textOver;
- if (!textOff.isValid()) textOff = (*mySchemePointer)->textOff;
- if (!fnt.weight()) fnt = (*mySchemePointer)->font;
- if (focusPen.style() == Qt::NoPen) focusPen = (*mySchemePointer)->focusPen;
- underline = (*mySchemePointer)->underlineOver;
- //cursover = (*mySchemePointer)->cursorOver;
- }
+ if (!myText.isEmpty()) {
+ QColor text = myColor, textOver = myColorOver, textOff = myColorDisabled;
+ QFont fnt = myFont;
+ QPen focusPen = myPen;
+ bool underline = m_underlineOver/*, cursover = m_changeCursorOver*/;
+ if (mySchemePointer && *mySchemePointer) {
+ if (!text.isValid()) text = (*mySchemePointer)->text;
+ if (!textOver.isValid()) textOver = (*mySchemePointer)->textOver;
+ if (!textOff.isValid()) textOff = (*mySchemePointer)->textOff;
+ if (!fnt.weight()) fnt = (*mySchemePointer)->font;
+ if (focusPen.style() == Qt::NoPen) focusPen = (*mySchemePointer)->focusPen;
+ underline = (*mySchemePointer)->underlineOver;
+ //cursover = (*mySchemePointer)->cursorOver;
+ }
- p.setPen(isEnabled() ? m_over ? textOver : text : textOff);
+ p.setPen(isEnabled() ? m_over ? textOver : text : textOff);
- if (isEnabled() && underline && m_over)
- fnt.setUnderline(true);
- p.setFont(fnt);
+ if (isEnabled() && underline && m_over)
+ fnt.setUnderline(true);
+ p.setFont(fnt);
- textRect.setLeft(x);
- QRect boundingRect;
+ textRect.setLeft(x);
+ QRect boundingRect;
- QFontMetrics fm(fnt);
+ QFontMetrics fm(fnt);
#if QT_VERSION >= 0x040203
- QString txt(fm.elidedText(myText, Qt::ElideRight, textRect.width()));
+ QString txt(fm.elidedText(myText, Qt::ElideRight, textRect.width()));
#else
- QString txt = myText;
+ QString txt = myText;
#endif
- p.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, txt, &boundingRect);
+ p.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, txt, &boundingRect);
- if (hasFocus()) {
- p.setPen(focusPen);
- p.drawRect(boundingRect.adjusted(-2,-1,0,0));
- }
- }
+ if (hasFocus()) {
+ p.setPen(focusPen);
+ p.drawRect(boundingRect.adjusted(-2,-1,0,0));
+ }
+ }
}
void iisIconLabel::enterEvent ( QEvent * /*event*/ )
{
- m_over = true;
+ m_over = true;
- //if (m_changeCursorOver)
- // QApplication::setOverrideCursor(Qt::PointingHandCursor);
+ //if (m_changeCursorOver)
+ // QApplication::setOverrideCursor(Qt::PointingHandCursor);
- update();
+ update();
}
void iisIconLabel::leaveEvent ( QEvent * /*event*/ )
{
- m_over = false;
- update();
+ m_over = false;
+ update();
- //if (m_changeCursorOver)
- // QApplication::restoreOverrideCursor();
+ //if (m_changeCursorOver)
+ // QApplication::restoreOverrideCursor();
}
void iisIconLabel::mousePressEvent ( QMouseEvent * event )
{
- if (event->button() == Qt::LeftButton) {
- m_pressed = true;
- emit pressed();
- } else
- if (event->button() == Qt::RightButton)
- emit contextMenu();
+ if (event->button() == Qt::LeftButton) {
+ m_pressed = true;
+ Q_EMIT pressed();
+ } else
+ if (event->button() == Qt::RightButton)
+ Q_EMIT contextMenu();
- update();
+ update();
}
void iisIconLabel::mouseReleaseEvent ( QMouseEvent * event )
{
- if (event->button() == Qt::LeftButton) {
- m_pressed = false;
- emit released();
+ if (event->button() == Qt::LeftButton) {
+ m_pressed = false;
+ Q_EMIT released();
- if (rect().contains( event->pos() )) {
- emit clicked();
- emit activated();
- }
- }
+ if (rect().contains( event->pos() )) {
+ Q_EMIT clicked();
+ Q_EMIT activated();
+ }
+ }
- update();
+ update();
}
void iisIconLabel::keyPressEvent ( QKeyEvent * event )
{
- switch (event->key()) {
- case Qt::Key_Space:
- case Qt::Key_Return:
- emit activated();
- break;
+ switch (event->key()) {
+ case Qt::Key_Space:
+ case Qt::Key_Return:
+ Q_EMIT activated();
+ break;
- default:;
- }
+ default:;
+ }
- QWidget::keyPressEvent(event);
+ QWidget::keyPressEvent(event);
}
diff --git a/src/Gui/iisTaskPanel/src/iistaskheader.cpp b/src/Gui/iisTaskPanel/src/iistaskheader.cpp
index 12e75cc20..4d1cd4243 100644
--- a/src/Gui/iisTaskPanel/src/iistaskheader.cpp
+++ b/src/Gui/iisTaskPanel/src/iistaskheader.cpp
@@ -16,38 +16,38 @@
#include "iisiconlabel.h"
iisTaskHeader::iisTaskHeader(const QIcon &icon, const QString &title, bool expandable, QWidget *parent)
- : QFrame(parent),
- myExpandable(expandable),
- m_over(false),
- m_buttonOver(false),
- m_fold(true),
- m_opacity(0.1),
- myButton(0)
+ : QFrame(parent),
+ myExpandable(expandable),
+ m_over(false),
+ m_buttonOver(false),
+ m_fold(true),
+ m_opacity(0.1),
+ myButton(0)
{
- myTitle = new iisIconLabel(icon, title, this);
- myTitle->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+ myTitle = new iisIconLabel(icon, title, this);
+ myTitle->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
- connect(myTitle, SIGNAL(activated()), this, SLOT(fold()));
+ connect(myTitle, SIGNAL(activated()), this, SLOT(fold()));
- QHBoxLayout *hbl = new QHBoxLayout();
- hbl->setMargin(2);
- setLayout(hbl);
+ QHBoxLayout *hbl = new QHBoxLayout();
+ hbl->setMargin(2);
+ setLayout(hbl);
- hbl->addWidget(myTitle);
+ hbl->addWidget(myTitle);
- setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
- setScheme(iisTaskPanelScheme::defaultScheme());
- myTitle->setSchemePointer(&myLabelScheme);
+ setScheme(iisTaskPanelScheme::defaultScheme());
+ myTitle->setSchemePointer(&myLabelScheme);
- if (myExpandable) {
- myButton = new QLabel(this);
- hbl->addWidget(myButton);
- myButton->installEventFilter(this);
- myButton->setFixedWidth(myScheme->headerButtonSize.width());
- changeIcons();
- }
+ if (myExpandable) {
+ myButton = new QLabel(this);
+ hbl->addWidget(myButton);
+ myButton->installEventFilter(this);
+ myButton->setFixedWidth(myScheme->headerButtonSize.width());
+ changeIcons();
+ }
}
iisTaskHeader::~iisTaskHeader()
@@ -57,145 +57,145 @@ iisTaskHeader::~iisTaskHeader()
bool iisTaskHeader::eventFilter(QObject *obj, QEvent *event)
{
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- fold();
- return true;
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ fold();
+ return true;
- case QEvent::Enter:
- m_buttonOver = true;
- changeIcons();
- return true;
+ case QEvent::Enter:
+ m_buttonOver = true;
+ changeIcons();
+ return true;
- case QEvent::Leave:
- m_buttonOver = false;
- changeIcons();
- return true;
+ case QEvent::Leave:
+ m_buttonOver = false;
+ changeIcons();
+ return true;
- default:;
- }
+ default:;
+ }
- return QFrame::eventFilter(obj, event);
+ return QFrame::eventFilter(obj, event);
}
void iisTaskHeader::setScheme(iisTaskPanelScheme *scheme)
{
- if (scheme) {
- myScheme = scheme;
- myLabelScheme = &(scheme->headerLabelScheme);
+ if (scheme) {
+ myScheme = scheme;
+ myLabelScheme = &(scheme->headerLabelScheme);
- if (myExpandable) {
- setCursor(myLabelScheme->cursorOver ? Qt::PointingHandCursor : cursor());
- changeIcons();
- }
+ if (myExpandable) {
+ setCursor(myLabelScheme->cursorOver ? Qt::PointingHandCursor : cursor());
+ changeIcons();
+ }
- setFixedHeight(scheme->headerSize);
+ setFixedHeight(scheme->headerSize);
- update();
- }
+ update();
+ }
}
-void iisTaskHeader::paintEvent ( QPaintEvent * event )
+void iisTaskHeader::paintEvent ( QPaintEvent * event )
{
- Q_UNUSED(event);
- QPainter p(this);
+ Q_UNUSED(event);
+ QPainter p(this);
#if QT_VERSION >= 0x040203
- if (myScheme->headerAnimation)
- p.setOpacity(m_opacity+0.7);
+ if (myScheme->headerAnimation)
+ p.setOpacity(m_opacity+0.7);
#endif
- p.setPen(myScheme->headerBorder);
- p.setBrush(myScheme->headerBackground);
- if (myScheme->headerBorder.style() == Qt::NoPen)
- p.drawRect(rect());
- else
- p.drawRect(rect().adjusted(0,0,-1,-1));
+ p.setPen(myScheme->headerBorder);
+ p.setBrush(myScheme->headerBackground);
+ if (myScheme->headerBorder.style() == Qt::NoPen)
+ p.drawRect(rect());
+ else
+ p.drawRect(rect().adjusted(0,0,-1,-1));
}
void iisTaskHeader::animate()
{
- if (!myScheme->headerAnimation)
- return;
+ if (!myScheme->headerAnimation)
+ return;
- if (!isEnabled()) {
- m_opacity = 0.1;
- update();
- return;
- }
+ if (!isEnabled()) {
+ m_opacity = 0.1;
+ update();
+ return;
+ }
- if (m_over) {
- if (m_opacity >= 0.3) {
- m_opacity = 0.3;
- return;
- }
- m_opacity += 0.05;
- } else {
- if (m_opacity <= 0.1) {
- m_opacity = 0.1;
- return;
- }
- m_opacity = qMax(0.1, m_opacity-0.05);
- }
+ if (m_over) {
+ if (m_opacity >= 0.3) {
+ m_opacity = 0.3;
+ return;
+ }
+ m_opacity += 0.05;
+ } else {
+ if (m_opacity <= 0.1) {
+ m_opacity = 0.1;
+ return;
+ }
+ m_opacity = qMax(0.1, m_opacity-0.05);
+ }
- QTimer::singleShot(100, this, SLOT(animate()));
- update();
+ QTimer::singleShot(100, this, SLOT(animate()));
+ update();
}
void iisTaskHeader::enterEvent ( QEvent * /*event*/ )
{
- m_over = true;
+ m_over = true;
- if (isEnabled())
- QTimer::singleShot(100, this, SLOT(animate()));
+ if (isEnabled())
+ QTimer::singleShot(100, this, SLOT(animate()));
- update();
+ update();
}
void iisTaskHeader::leaveEvent ( QEvent * /*event*/ )
{
- m_over = false;
-
- if (isEnabled())
- QTimer::singleShot(100, this, SLOT(animate()));
+ m_over = false;
- update();
+ if (isEnabled())
+ QTimer::singleShot(100, this, SLOT(animate()));
+
+ update();
}
void iisTaskHeader::fold()
{
- if (myExpandable) {
- emit activated();
+ if (myExpandable) {
+ Q_EMIT activated();
- m_fold = !m_fold;
- changeIcons();
- }
+ m_fold = !m_fold;
+ changeIcons();
+ }
}
void iisTaskHeader::changeIcons()
{
- if (!myButton)
- return;
+ if (!myButton)
+ return;
- if (m_buttonOver)
- {
- if (m_fold)
- myButton->setPixmap(myScheme->headerButtonFoldOver.pixmap(myScheme->headerButtonSize));
- else
- myButton->setPixmap(myScheme->headerButtonUnfoldOver.pixmap(myScheme->headerButtonSize));
- } else
- {
- if (m_fold)
- myButton->setPixmap(myScheme->headerButtonFold.pixmap(myScheme->headerButtonSize));
- else
- myButton->setPixmap(myScheme->headerButtonUnfold.pixmap(myScheme->headerButtonSize));
- }
+ if (m_buttonOver)
+ {
+ if (m_fold)
+ myButton->setPixmap(myScheme->headerButtonFoldOver.pixmap(myScheme->headerButtonSize));
+ else
+ myButton->setPixmap(myScheme->headerButtonUnfoldOver.pixmap(myScheme->headerButtonSize));
+ } else
+ {
+ if (m_fold)
+ myButton->setPixmap(myScheme->headerButtonFold.pixmap(myScheme->headerButtonSize));
+ else
+ myButton->setPixmap(myScheme->headerButtonUnfold.pixmap(myScheme->headerButtonSize));
+ }
}
void iisTaskHeader::mouseReleaseEvent ( QMouseEvent * event )
{
- if (event->button() == Qt::LeftButton) {
- emit activated();
- }
+ if (event->button() == Qt::LeftButton) {
+ Q_EMIT activated();
+ }
}
diff --git a/src/Mod/Draft/Resources/ui/preferences-draft.ui b/src/Mod/Draft/Resources/ui/preferences-draft.ui
index 5eda20018..25a3af1df 100755
--- a/src/Mod/Draft/Resources/ui/preferences-draft.ui
+++ b/src/Mod/Draft/Resources/ui/preferences-draft.ui
@@ -222,46 +222,6 @@
- -
-
-
-
-
-
- Dimensions precision level
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- 8
-
-
- 2
-
-
- dimPrecision
-
-
- Mod/Draft
-
-
-
-
-
-
-
diff --git a/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui b/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui
index 4c8629c7e..213e2cc6a 100644
--- a/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui
+++ b/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui
@@ -7,7 +7,7 @@
0
0
522
- 462
+ 473
@@ -153,6 +153,46 @@ such as "Arial:Bold"
+ -
+
+
-
+
+
+ Number of decimals
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ 8
+
+
+ 2
+
+
+ dimPrecision
+
+
+ Mod/Draft
+
+
+
+
+
-
-
@@ -364,7 +404,7 @@ such as "Arial:Bold"
-
-
+
300
@@ -405,6 +445,21 @@ such as "Arial:Bold"
qPixmapFromMimeSource
+
+ Gui::FileChooser
+ QWidget
+
+
+
+ Gui::PrefFileChooser
+ Gui::FileChooser
+
+
+
+ Gui::PrefSpinBox
+ QSpinBox
+
+
Gui::PrefCheckBox
QCheckBox
@@ -425,16 +480,6 @@ such as "Arial:Bold"
QDoubleSpinBox
-
- Gui::FileChooser
- QWidget
-
-
-
- Gui::PrefFileChooser
- Gui::FileChooser
-
-
diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py
index 9d2b864c1..9b5a32ff7 100644
--- a/src/Mod/Draft/importDXF.py
+++ b/src/Mod/Draft/importDXF.py
@@ -776,6 +776,8 @@ non-parametric curve"""
warn('polygon fallback on %s' %spline)
return drawSplineIterpolation(controlpoints,closed=closed,\
forceShape=forceShape,alwaysDiscretize=True)
+ if fitpoints and not(controlpoints):
+ return drawSplineIterpolation(fitpoints,closed=closed,forceShape=forceShape)
try:
bspline=Part.BSplineCurve()
bspline.buildFromPolesMultsKnots(poles=controlpoints,mults=multvector,\
diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt
index 9502efc15..551d956c2 100755
--- a/src/Mod/Fem/App/CMakeLists.txt
+++ b/src/Mod/Fem/App/CMakeLists.txt
@@ -71,6 +71,7 @@ SET(FemScripts_SRCS
_CommandMaterial.py
_CommandMeshGmshFromShape.py
_CommandMeshNetgenFromShape.py
+ _CommandMeshGroup.py
_CommandMeshRegion.py
_CommandPrintMeshInfo.py
_CommandPurgeResults.py
@@ -83,6 +84,7 @@ SET(FemScripts_SRCS
_FemConstraintSelfWeight.py
_FemMaterialMechanicalNonlinear.py
_FemMeshGmsh.py
+ _FemMeshGroup.py
_FemMeshRegion.py
_FemShellThickness.py
_FemSolverCalculix.py
@@ -90,6 +92,7 @@ SET(FemScripts_SRCS
_FemMaterial.py
_TaskPanelFemBeamSection.py
_TaskPanelFemMeshGmsh.py
+ _TaskPanelFemMeshGroup.py
_TaskPanelFemMeshRegion.py
_TaskPanelFemShellThickness.py
_TaskPanelFemSolverCalculix.py
@@ -99,6 +102,7 @@ SET(FemScripts_SRCS
_ViewProviderFemConstraintSelfWeight.py
_ViewProviderFemMaterialMechanicalNonlinear.py
_ViewProviderFemMeshGmsh.py
+ _ViewProviderFemMeshGroup.py
_ViewProviderFemMeshRegion.py
_ViewProviderFemShellThickness.py
_ViewProviderFemSolverCalculix.py
@@ -122,6 +126,7 @@ SET(FemScripts_SRCS
FemMaterialMechanicalNonlinear.py
FemMesh2Mesh.py
FemMeshGmsh.py
+ FemMeshGroup.py
FemMeshRegion.py
FemMeshTools.py
FemShellThickness.py
@@ -136,6 +141,7 @@ SET(FemScripts_SRCS
z88DispReader.py
TaskPanelFemBeamSection.ui
TaskPanelFemMeshGmsh.ui
+ TaskPanelFemMeshGroup.ui
TaskPanelFemMeshRegion.ui
TaskPanelFemShellThickness.ui
TaskPanelFemSolverCalculix.ui
diff --git a/src/Mod/Fem/App/FemResultObject.cpp b/src/Mod/Fem/App/FemResultObject.cpp
index 20915c414..5a793f786 100644
--- a/src/Mod/Fem/App/FemResultObject.cpp
+++ b/src/Mod/Fem/App/FemResultObject.cpp
@@ -42,6 +42,8 @@ FemResultObject::FemResultObject()
ADD_PROPERTY_TYPE(Stats,(0), "Fem",Prop_None,"Statistics of the results");
ADD_PROPERTY_TYPE(DisplacementVectors,(), "Fem",Prop_None,"List of displacement vectors");
ADD_PROPERTY_TYPE(DisplacementLengths,(0), "Fem",Prop_None,"List of displacement lengths");
+ ADD_PROPERTY_TYPE(StressVectors,(), "Fem",Prop_None,"List of Stress vectors");
+ ADD_PROPERTY_TYPE(StrainVectors,(), "Fem",Prop_None,"List of Strain vectors");
ADD_PROPERTY_TYPE(StressValues,(0), "Fem",Prop_None,"List of Von Misses stress values");
ADD_PROPERTY_TYPE(PrincipalMax,(0), "Fem",Prop_None,"List of First Principal (Max) stress values");
ADD_PROPERTY_TYPE(PrincipalMed,(0), "Fem",Prop_None,"List of Second Principal (Med) stress values");
@@ -59,6 +61,8 @@ FemResultObject::FemResultObject()
Stats.setStatus(App::Property::ReadOnly, true);
DisplacementVectors.setStatus(App::Property::ReadOnly, true);
DisplacementLengths.setStatus(App::Property::ReadOnly, true);
+ StressVectors.setStatus(App::Property::ReadOnly, true);
+ StrainVectors.setStatus(App::Property::ReadOnly, true);
StressValues.setStatus(App::Property::ReadOnly, true);
PrincipalMax.setStatus(App::Property::ReadOnly, true);
PrincipalMed.setStatus(App::Property::ReadOnly, true);
diff --git a/src/Mod/Fem/App/FemResultObject.h b/src/Mod/Fem/App/FemResultObject.h
index a6202024f..1d765385e 100644
--- a/src/Mod/Fem/App/FemResultObject.h
+++ b/src/Mod/Fem/App/FemResultObject.h
@@ -49,8 +49,12 @@ public:
App::PropertyFloatList Stats;
/// Displacement vectors of analysis
App::PropertyVectorList DisplacementVectors;
- /// Lengths of displacement vestors of analysis
+ /// Lengths of displacement vectors of analysis
App::PropertyFloatList DisplacementLengths;
+ /// Stress vectors of analysis
+ App::PropertyVectorList StressVectors;
+ /// Strain vectors of analysis
+ App::PropertyVectorList StrainVectors;
/// Von Mises Stress values of analysis
App::PropertyFloatList StressValues;
/// First principal Stress values of analysis
diff --git a/src/Mod/Fem/App/FemVTKTools.cpp b/src/Mod/Fem/App/FemVTKTools.cpp
index c767beb8c..c5f8d337b 100644
--- a/src/Mod/Fem/App/FemVTKTools.cpp
+++ b/src/Mod/Fem/App/FemVTKTools.cpp
@@ -108,7 +108,7 @@ template void writeVTKFile(const char* filename, vtkSmartPointer<
writer->SetInputData(dataset);
writer->Write();
}
-
+
void FemVTKTools::importVTKMesh(vtkSmartPointer dataset, FemMesh* mesh)
{
const vtkIdType nPoints = dataset->GetNumberOfPoints();
@@ -184,7 +184,7 @@ FemMesh* FemVTKTools::readVTKMesh(const char* filename, FemMesh* mesh)
Base::TimeInfo Start;
Base::Console().Log("Start: read FemMesh from VTK unstructuredGrid ======================\n");
Base::FileInfo f(filename);
-
+
if(f.hasExtension("vtu"))
{
vtkSmartPointer dataset = readVTKFile(filename);
@@ -236,7 +236,7 @@ void exportFemMeshFaces(vtkSmartPointer grid, const SMDS_Fa
quad->GetPointIds()->SetId(1, aFace->GetNode(1)->GetID()-1);
quad->GetPointIds()->SetId(2, aFace->GetNode(2)->GetID()-1);
quad->GetPointIds()->SetId(3, aFace->GetNode(3)->GetID()-1);
-
+
quadArray->InsertNextCell(quad);
}
//quadratic triangle
@@ -263,7 +263,7 @@ void exportFemMeshFaces(vtkSmartPointer grid, const SMDS_Fa
quad->GetPointIds()->SetId(5, aFace->GetNode(5)->GetID()-1);
quad->GetPointIds()->SetId(6, aFace->GetNode(6)->GetID()-1);
quad->GetPointIds()->SetId(7, aFace->GetNode(7)->GetID()-1);
-
+
quadQuadArray->InsertNextCell(quad);
}
}
@@ -275,7 +275,7 @@ void exportFemMeshFaces(vtkSmartPointer grid, const SMDS_Fa
if(quadTriangleArray->GetNumberOfCells()>0)
grid->SetCells(VTK_QUADRATIC_TRIANGLE, quadTriangleArray);
-
+
if(quadQuadArray->GetNumberOfCells()>0)
grid->SetCells(VTK_QUADRATIC_QUAD, quadQuadArray);
@@ -291,7 +291,7 @@ void exportFemMeshCells(vtkSmartPointer grid, const SMDS_Vo
// quadratic elemnts with 13 and 15 nodes are not added yet
vtkSmartPointer quadTetraArray = vtkSmartPointer::New();
vtkSmartPointer quadHexaArray = vtkSmartPointer::New();
-
+
for (;aVolIter->more();)
{
const SMDS_MeshVolume* aVol = aVolIter->next();
@@ -314,7 +314,7 @@ void exportFemMeshCells(vtkSmartPointer grid, const SMDS_Vo
cell->GetPointIds()->SetId(2, aVol->GetNode(2)->GetID()-1);
cell->GetPointIds()->SetId(3, aVol->GetNode(3)->GetID()-1);
cell->GetPointIds()->SetId(4, aVol->GetNode(4)->GetID()-1);
-
+
pyramidArray->InsertNextCell(cell);
}
if(aVol->NbNodes() == 6) {
@@ -325,7 +325,7 @@ void exportFemMeshCells(vtkSmartPointer grid, const SMDS_Vo
cell->GetPointIds()->SetId(3, aVol->GetNode(3)->GetID()-1);
cell->GetPointIds()->SetId(4, aVol->GetNode(4)->GetID()-1);
cell->GetPointIds()->SetId(5, aVol->GetNode(5)->GetID()-1);
-
+
wedgeArray->InsertNextCell(cell);
}
if(aVol->NbNodes() == 8) {
@@ -338,7 +338,7 @@ void exportFemMeshCells(vtkSmartPointer grid, const SMDS_Vo
cell->GetPointIds()->SetId(5, aVol->GetNode(5)->GetID()-1);
cell->GetPointIds()->SetId(6, aVol->GetNode(6)->GetID()-1);
cell->GetPointIds()->SetId(7, aVol->GetNode(7)->GetID()-1);
-
+
hexaArray->InsertNextCell(cell);
}
//quadratic tetrahedra
@@ -371,10 +371,10 @@ void exportFemMeshCells(vtkSmartPointer grid, const SMDS_Vo
if(hexaArray->GetNumberOfCells()>0)
grid->SetCells(VTK_HEXAHEDRON, hexaArray);
-
+
if(quadTetraArray->GetNumberOfCells()>0)
grid->SetCells(VTK_QUADRATIC_TETRA, quadTetraArray);
-
+
if(quadHexaArray->GetNumberOfCells()>0)
grid->SetCells(VTK_QUADRATIC_HEXAHEDRON, quadHexaArray);
@@ -382,11 +382,11 @@ void exportFemMeshCells(vtkSmartPointer grid, const SMDS_Vo
void FemVTKTools::exportVTKMesh(const FemMesh* mesh, vtkSmartPointer grid)
{
-
+
SMESH_Mesh* smesh = const_cast(mesh->getSMesh());
SMESHDS_Mesh* meshDS = smesh->GetMeshDS();
const SMDS_MeshInfo& info = meshDS->GetMeshInfo();
-
+
//start with the nodes
vtkSmartPointer points = vtkSmartPointer::New();
SMDS_NodeIteratorPtr aNodeIter = meshDS->nodesIterator();
@@ -409,11 +409,11 @@ void FemVTKTools::exportVTKMesh(const FemMesh* mesh, vtkSmartPointer grid = vtkSmartPointer::New();
exportVTKMesh(mesh, grid);
//vtkSmartPointer dataset = vtkDataSet::SafeDownCast(grid);
@@ -426,7 +426,7 @@ void FemVTKTools::writeVTKMesh(const char* filename, const FemMesh* mesh)
else{
Base::Console().Error("file name extension is not supported to write VTK\n");
}
-
+
Base::Console().Log(" %f: Done \n",Base::TimeInfo::diffTimeF(Start, Base::TimeInfo()));
}
@@ -487,7 +487,7 @@ App::DocumentObject* FemVTKTools::readFluidicResult(const char* filename, App::D
Base::TimeInfo Start;
Base::Console().Log("Start: read FemResult with FemMesh from VTK file ======================\n");
Base::FileInfo f(filename);
-
+
vtkSmartPointer ds;
if(f.hasExtension("vtu"))
{
@@ -501,7 +501,7 @@ App::DocumentObject* FemVTKTools::readFluidicResult(const char* filename, App::D
{
Base::Console().Error("file name extension is not supported\n");
}
-
+
App::Document* pcDoc = App::GetApplication().getActiveDocument();
if(!pcDoc)
{
@@ -532,12 +532,12 @@ App::DocumentObject* FemVTKTools::readFluidicResult(const char* filename, App::D
static_cast(mesh->getPropertyByName("FemMesh"))->setValue(*fmesh);
static_cast(result->getPropertyByName("Mesh"))->setValue(mesh);
// PropertyLink is the property type to store DocumentObject pointer
-
+
importFluidicResult(dataset, result);
pcDoc->recompute();
-
+
Base::Console().Log(" %f: Done \n", Base::TimeInfo::diffTimeF(Start, Base::TimeInfo()));
-
+
return result;
}
@@ -561,12 +561,12 @@ void FemVTKTools::writeResult(const char* filename, const App::DocumentObject* r
Base::TimeInfo Start;
Base::Console().Log("Start: write FemResult or CfdResult to VTK unstructuredGrid dataset =======\n");
Base::FileInfo f(filename);
-
+
vtkSmartPointer grid = vtkSmartPointer::New();
App::DocumentObject* mesh = static_cast(res->getPropertyByName("Mesh"))->getValue();
const FemMesh& fmesh = static_cast(mesh->getPropertyByName("FemMesh"))->getValue();
FemVTKTools::exportVTKMesh(&fmesh, grid);
-
+
if(res->getPropertyByName("Velocity")){
FemVTKTools::exportFluidicResult(res, grid);
}
@@ -576,7 +576,7 @@ void FemVTKTools::writeResult(const char* filename, const App::DocumentObject* r
else{
return;
}
-
+
//vtkSmartPointer dataset = vtkDataSet::SafeDownCast(grid);
if(f.hasExtension("vtu")){
writeVTKFile(filename, grid);
@@ -587,7 +587,7 @@ void FemVTKTools::writeResult(const char* filename, const App::DocumentObject* r
else{
Base::Console().Error("file name extension is not supported to write VTK\n");
}
-
+
Base::Console().Log(" %f: Done \n",Base::TimeInfo::diffTimeF(Start, Base::TimeInfo()));
}
@@ -604,7 +604,7 @@ void FemVTKTools::importFluidicResult(vtkSmartPointer dataset, App::
vars["TurbulenceEnergy"] = "k";
vars["TurbulenceDissipationRate"] = "epsilon";
vars["TurbulenceSpecificDissipation"] = "omega";
-
+
const int max_var_index = 11;
std::vector stats(3*max_var_index, 0.0);
@@ -620,10 +620,10 @@ void FemVTKTools::importFluidicResult(vtkSmartPointer dataset, App::
varids["TurbulenceDissipationRate"] = 8;
//varids["TurbulenceThermalDiffusivity"] = 9;
//varids["TurbulenceSpecificDissipation"] = 10;
-
+
double ts = 0.0; // t=0.0 for static simulation
static_cast(res->getPropertyByName("Time"))->setValue(ts);
-
+
vtkSmartPointer pd = dataset->GetPointData();
const vtkIdType nPoints = dataset->GetNumberOfPoints();
if(pd->GetNumberOfArrays() == 0) {
@@ -631,7 +631,7 @@ void FemVTKTools::importFluidicResult(vtkSmartPointer dataset, App::
// if pointData is empty, data may be in cellDate, cellData -> pointData interpolation is possible in VTK
return;
}
-
+
std::vector nodeIds(nPoints);
vtkSmartPointer vel = pd->GetArray(vars["Velocity"]);
if(nPoints && vel && vel->GetNumberOfComponents() == 3) {
@@ -692,7 +692,7 @@ void FemVTKTools::importFluidicResult(vtkSmartPointer dataset, App::
stats[index*3] = vmin;
stats[index*3 + 2] = vmax;
stats[index*3 + 1] = vmean/nPoints;
-
+
Base::Console().Message("field \"%s\" has been loaded \n", kv.first);
}
}
@@ -760,6 +760,7 @@ void FemVTKTools::exportMechanicalResult(const App::DocumentObject* obj, vtkSmar
const FemResultObject* res = static_cast(obj);
if(!res->StressValues.getValues().empty()) {
const std::vector& vec = res->StressValues.getValues();
+ if (vec.size()>1) {
vtkSmartPointer data = vtkSmartPointer::New();
data->SetNumberOfValues(vec.size());
data->SetName("Von Mises stress");
@@ -768,10 +769,11 @@ void FemVTKTools::exportMechanicalResult(const App::DocumentObject* obj, vtkSmar
data->SetValue(i, vec[i]);
grid->GetPointData()->AddArray(data);
- }
+ }}
- if(!res->StressValues.getValues().empty()) {
+ if(!res->MaxShear.getValues().empty()) {
const std::vector& vec = res->MaxShear.getValues();
+ if (vec.size()>1) {
vtkSmartPointer data = vtkSmartPointer::New();
data->SetNumberOfValues(vec.size());
data->SetName("Max shear stress (Tresca)");
@@ -780,10 +782,11 @@ void FemVTKTools::exportMechanicalResult(const App::DocumentObject* obj, vtkSmar
data->SetValue(i, vec[i]);
grid->GetPointData()->AddArray(data);
- }
+ }}
- if(!res->StressValues.getValues().empty()) {
+ if(!res->PrincipalMax.getValues().empty()) {
const std::vector& vec = res->PrincipalMax.getValues();
+ if (vec.size()>1) {
vtkSmartPointer data = vtkSmartPointer::New();
data->SetNumberOfValues(vec.size());
data->SetName("Maximum Principal stress");
@@ -792,10 +795,11 @@ void FemVTKTools::exportMechanicalResult(const App::DocumentObject* obj, vtkSmar
data->SetValue(i, vec[i]);
grid->GetPointData()->AddArray(data);
- }
+ }}
- if(!res->StressValues.getValues().empty()) {
+ if(!res->PrincipalMax.getValues().empty()) {
const std::vector& vec = res->PrincipalMin.getValues();
+ if (vec.size()>1) {
vtkSmartPointer data = vtkSmartPointer::New();
data->SetNumberOfValues(vec.size());
data->SetName("Minimum Principal stress");
@@ -804,10 +808,11 @@ void FemVTKTools::exportMechanicalResult(const App::DocumentObject* obj, vtkSmar
data->SetValue(i, vec[i]);
grid->GetPointData()->AddArray(data);
- }
+ }}
- if(!res->StressValues.getValues().empty()) {
+ if (!res->Temperature.getValues().empty()) {
const std::vector& vec = res->Temperature.getValues();
+ if (vec.size()>1) {
vtkSmartPointer data = vtkSmartPointer::New();
data->SetNumberOfValues(vec.size());
data->SetName("Temperature");
@@ -816,10 +821,11 @@ void FemVTKTools::exportMechanicalResult(const App::DocumentObject* obj, vtkSmar
data->SetValue(i, vec[i]);
grid->GetPointData()->AddArray(data);
- }
+ }}
- if(!res->StressValues.getValues().empty()) {
+ if (!res->UserDefined.getValues().empty()) {
const std::vector& vec = res->UserDefined.getValues();
+ if (vec.size()>1) {
vtkSmartPointer data = vtkSmartPointer::New();
data->SetNumberOfValues(vec.size());
data->SetName("User Defined Results");
@@ -828,11 +834,12 @@ void FemVTKTools::exportMechanicalResult(const App::DocumentObject* obj, vtkSmar
data->SetValue(i, vec[i]);
grid->GetPointData()->AddArray(data);
- }
+ }}
- if(!res->StressValues.getValues().empty()) {
+ if(!res->DisplacementVectors.getValues().empty()) {
const std::vector& vec = res->DisplacementVectors.getValues();
+ if (vec.size()>1) {
vtkSmartPointer data = vtkSmartPointer::New();
data->SetNumberOfComponents(3);
data->SetName("Displacement");
@@ -843,7 +850,38 @@ void FemVTKTools::exportMechanicalResult(const App::DocumentObject* obj, vtkSmar
}
grid->GetPointData()->AddArray(data);
- }
+ }}
+
+ if(!res->StressVectors.getValues().empty()) {
+ const std::vector& vec = res->StressVectors.getValues();
+ if (vec.size()>1) {
+ vtkSmartPointer data = vtkSmartPointer::New();
+ data->SetNumberOfComponents(3);
+ data->SetName("Stress Vectors");
+
+ for(std::vector::const_iterator it=vec.begin(); it!=vec.end(); ++it) {
+ double tuple[] = {it->x, it->y , it->z};
+ data->InsertNextTuple(tuple);
+ }
+
+ grid->GetPointData()->AddArray(data);
+ }}
+
+ if(!res->StrainVectors.getValues().empty()) {
+ const std::vector& vec = res->StrainVectors.getValues();
+ if (vec.size()>1) {
+ vtkSmartPointer data = vtkSmartPointer::New();
+ data->SetNumberOfComponents(3);
+ data->SetName("Strain Vectors");
+
+ for(std::vector::const_iterator it=vec.begin(); it!=vec.end(); ++it) {
+ double tuple[] = {it->x, it->y, it->z};
+ data->InsertNextTuple(tuple);
+ }
+
+ grid->GetPointData()->AddArray(data);
+ }}
+
}
} // namespace
diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt
index 6a318ae8c..308e3d580 100755
--- a/src/Mod/Fem/CMakeLists.txt
+++ b/src/Mod/Fem/CMakeLists.txt
@@ -55,6 +55,13 @@ INSTALL(
FemMesh2Mesh.py
_CommandFEMMesh2Mesh.py
+ FemMeshGroup.py
+ _FemMeshGroup.py
+ _ViewProviderFemMeshGroup.py
+ _CommandMeshGroup.py
+ _TaskPanelFemMeshGroup.py
+ TaskPanelFemMeshGroup.ui
+
FemMeshRegion.py
_FemMeshRegion.py
_ViewProviderFemMeshRegion.py
diff --git a/src/Mod/Fem/FemGmshTools.py b/src/Mod/Fem/FemGmshTools.py
index bd9258dc7..f214c03a6 100644
--- a/src/Mod/Fem/FemGmshTools.py
+++ b/src/Mod/Fem/FemGmshTools.py
@@ -215,17 +215,39 @@ class FemGmshTools():
print(' ' + self.gmsh_bin)
def get_group_data(self):
+ self.group_elements = {}
+ # TODO solid, face, edge seam not work together, some print or make it work together
+ # TODO handle groups for Edges and Vertexes
+
+ # mesh groups and groups of analysis member
+ if not self.mesh_obj.MeshGroupList:
+ print (' No mesh group objects.')
+ else:
+ print (' Mesh group objects, we need to get the elements.')
+ for mg in self.mesh_obj.MeshGroupList:
+ new_group_elements = FemMeshTools.get_mesh_group_elements(mg, self.part_obj)
+ for ge in new_group_elements:
+ if ge not in self.group_elements:
+ self.group_elements[ge] = new_group_elements[ge]
+ else:
+ FreeCAD.Console.PrintError(" A group with this name exists already.\n")
if self.analysis:
print(' Group meshing.')
- self.group_elements = FemMeshTools.get_analysis_group_elements(self.analysis, self.part_obj)
- print(' {}'.format(self.group_elements))
+ new_group_elements = FemMeshTools.get_analysis_group_elements(self.analysis, self.part_obj)
+ for ge in new_group_elements:
+ if ge not in self.group_elements:
+ self.group_elements[ge] = new_group_elements[ge]
+ else:
+ FreeCAD.Console.PrintError(" A group with this name exists already.\n")
else:
- print(' NO group meshing.')
+ print(' No anlysis members for group meshing.')
+ print(' {}'.format(self.group_elements))
+ # mesh regions
self.ele_length_map = {} # { 'ElementString' : element length }
self.ele_node_map = {} # { 'ElementString' : [element nodes] }
if not self.mesh_obj.MeshRegionList:
- print (' No Mesh regions.')
+ print (' No mesh regions.')
else:
print (' Mesh regions, we need to get the elements.')
if self.part_obj.Shape.ShapeType == 'Compound':
@@ -279,7 +301,7 @@ class FemGmshTools():
geo = open(self.temp_file_geo, "w")
geo.write('Merge "' + self.temp_file_geometry + '";\n')
geo.write("\n")
- if self.analysis and self.group_elements:
+ if self.group_elements:
# print(' We gone have found elements to make mesh groups for.')
geo.write("// group data\n")
# we use the element name of FreeCAD which starts with 1 (example: 'Face1'), same as GMSH
diff --git a/src/Mod/Fem/FemMeshGroup.py b/src/Mod/Fem/FemMeshGroup.py
new file mode 100644
index 000000000..d937ca236
--- /dev/null
+++ b/src/Mod/Fem/FemMeshGroup.py
@@ -0,0 +1,49 @@
+# ***************************************************************************
+# * *
+# * Copyright (c) 2016 - Bernd Hahnebach *
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU Lesser General Public License (LGPL) *
+# * as published by the Free Software Foundation; either version 2 of *
+# * the License, or (at your option) any later version. *
+# * for detail see the LICENCE text file. *
+# * *
+# * This program is distributed in the hope that it will be useful, *
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# * GNU Library General Public License for more details. *
+# * *
+# * You should have received a copy of the GNU Library General Public *
+# * License along with this program; if not, write to the Free Software *
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+# * USA *
+# * *
+# ***************************************************************************
+
+__title__ = "FemMeshGroup"
+__author__ = "Bernd Hahnebach"
+__url__ = "http://www.freecadweb.org"
+
+## \addtogroup FEM
+# @{
+
+import FreeCAD
+import _FemMeshGroup
+
+
+def makeFemMeshGroup(base_mesh, use_label=False, name="FEMMeshGroup"):
+ '''makeFemMeshGroup([length], [name]): creates a FEM mesh region object to define properties for a regon of a FEM mesh'''
+ obj = FreeCAD.ActiveDocument.addObject("Fem::FeaturePython", name)
+ _FemMeshGroup._FemMeshGroup(obj)
+ obj.UseLabel = use_label
+ # obj.BaseMesh = base_mesh
+ # App::PropertyLinkList does not support append, we will use a temporary list to append the mesh group obj. to the list
+ tmplist = base_mesh.MeshGroupList
+ tmplist.append(obj)
+ base_mesh.MeshGroupList = tmplist
+ if FreeCAD.GuiUp:
+ import _ViewProviderFemMeshGroup
+ _ViewProviderFemMeshGroup._ViewProviderFemMeshGroup(obj.ViewObject)
+ return obj
+
+# @}
diff --git a/src/Mod/Fem/FemMeshTools.py b/src/Mod/Fem/FemMeshTools.py
index 3cc1b6c4c..e35940d48 100644
--- a/src/Mod/Fem/FemMeshTools.py
+++ b/src/Mod/Fem/FemMeshTools.py
@@ -995,54 +995,43 @@ def get_ref_shape_node_sum_geom_table(node_geom_table):
return node_sum_geom_table
+def get_mesh_group_elements(mesh_group_obj, aPart):
+ '''the Reference shapes of the mesh_group_object are searched in the Shape of aPart. If found in shape they are added to a dict
+ {MeshGroupIdentifier : ['ShapeType of the Elements'], [ElementID, ElementID, ...], ...}
+ '''
+ group_elements = {} # { name : [element, element, ... , element]}
+ if mesh_group_obj.References:
+ grp_ele = get_reference_group_elements(mesh_group_obj, aPart)
+ group_elements[grp_ele[0]] = grp_ele[1]
+ else:
+ FreeCAD.Console.PrintError(' Empty reference in mesh group object: ' + mesh_group_obj.Name + ' ' + mesh_group_obj.Label)
+ return group_elements
+
+
def get_analysis_group_elements(aAnalysis, aPart):
''' all Reference shapes of all Analysis member are searched in the Shape of aPart. If found in shape they are added to a dict
{ConstraintName : ['ShapeType of the Elements'], [ElementID, ElementID, ...], ...}
'''
- aShape = aPart.Shape
group_elements = {} # { name : [element, element, ... , element]}
empty_references = []
for m in aAnalysis.Member:
if hasattr(m, "References"):
- # print(m.Name)
- key = m.Name
- elements = []
- stype = None
if m.References:
- for r in m.References:
- parent = r[0]
- childs = r[1]
- # print(parent)
- # print(childs)
- for child in childs:
- ref_shape = get_element(parent, child) # the method getElement(element) does not return Solid elements
- if not stype:
- stype = ref_shape.ShapeType
- elif stype != ref_shape.ShapeType:
- FreeCAD.Console.PrintError('Error, two refschapes in References with different ShapeTypes.\n')
- # print(ref_shape)
- found_element = find_element_in_shape(aShape, ref_shape)
- if found_element is not None:
- elements.append(found_element)
- else:
- FreeCAD.Console.PrintError('Problem: No element found for: ' + str(ref_shape) + '\n')
- print(' ' + m.Name)
- print(' ' + str(m.References))
- print(' ' + r[0].Name)
- group_elements[key] = sorted(elements)
+ grp_ele = get_reference_group_elements(m, aPart)
+ group_elements[grp_ele[0]] = grp_ele[1]
else:
print(' Empty reference: ' + m.Name)
empty_references.append(m)
if empty_references:
if len(empty_references) == 1:
- group_elements = get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aShape)
+ group_elements = get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aPart.Shape)
else:
FreeCAD.Console.PrintError('Problem: more than one object with empty references.\n')
print('We gone try to get the empty material references anyway.\n')
# ShellThickness and BeamSection could have empty references, but on solid meshes only materials should have empty references
for er in empty_references:
print(er.Name)
- group_elements = get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aShape)
+ group_elements = get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aPart.Shape)
# check if all groups have elements:
for g in group_elements:
# print(group_elements[g])
@@ -1051,6 +1040,37 @@ def get_analysis_group_elements(aAnalysis, aPart):
return group_elements
+def get_reference_group_elements(obj, aPart):
+ aShape = aPart.Shape
+ if hasattr(obj, "UseLabel") and obj.UseLabel:
+ key = obj.Label # TODO check the character of the Label, only allow underline and standard english character
+ else:
+ key = obj.Name
+ elements = []
+ stype = None
+ for r in obj.References:
+ parent = r[0]
+ childs = r[1]
+ # print(parent)
+ # print(childs)
+ for child in childs:
+ ref_shape = get_element(parent, child) # the method getElement(element) does not return Solid elements
+ if not stype:
+ stype = ref_shape.ShapeType
+ elif stype != ref_shape.ShapeType:
+ FreeCAD.Console.PrintError('Error, two refschapes in References with different ShapeTypes.\n')
+ # print(ref_shape)
+ found_element = find_element_in_shape(aShape, ref_shape)
+ if found_element is not None:
+ elements.append(found_element)
+ else:
+ FreeCAD.Console.PrintError('Problem: No element found for: ' + str(ref_shape) + '\n')
+ print(' ' + obj.Name)
+ print(' ' + str(obj.References))
+ print(' ' + r[0].Name)
+ return (key, sorted(elements))
+
+
def get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aShape):
'''get the elementIDs if the Reference shape is empty
see get_analysis_group_elements() for more informatations
diff --git a/src/Mod/Fem/FemTools.py b/src/Mod/Fem/FemTools.py
index 3d11fb989..93ed055f2 100644
--- a/src/Mod/Fem/FemTools.py
+++ b/src/Mod/Fem/FemTools.py
@@ -378,9 +378,7 @@ class FemTools(QtCore.QRunnable, QtCore.QObject):
if self.analysis_type == "static":
if not (self.fixed_constraints or self.displacement_constraints):
message += "Static analysis: Neither constraint fixed nor constraint displacement defined.\n"
- if self.analysis_type == "static":
- if not (self.force_constraints or self.pressure_constraints or self.selfweight_constraints):
- message += "Static analysis: Neither constraint force nor constraint pressure or a constraint selfweight defined.\n"
+ # no check in the regard of loads (constraint force, pressure, self weight) is done because an analysis without loads at all is an valid analysis too
if self.analysis_type == "thermomech":
if not self.initialtemperature_constraints:
message += "Thermomechanical analysis: No initial temperature defined.\n"
diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp
index 63b25d258..7f586c73b 100755
--- a/src/Mod/Fem/Gui/Workbench.cpp
+++ b/src/Mod/Fem/Gui/Workbench.cpp
@@ -71,6 +71,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
<< "Fem_MeshNetgenFromShape"
<< "Fem_MeshGmshFromShape"
<< "Fem_MeshRegion"
+ << "Fem_MeshGroup"
//<< "Fem_CreateNodesSet"
<< "Separator"
<< "Fem_Material"
@@ -143,6 +144,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
<< "Fem_MeshNetgenFromShape"
<< "Fem_MeshGmshFromShape"
<< "Fem_MeshRegion"
+ << "Fem_MeshGroup"
<< "Fem_CreateNodesSet"
<< "Separator"
<< "Fem_Material"
diff --git a/src/Mod/Fem/InitGui.py b/src/Mod/Fem/InitGui.py
index dbe0ce629..c9832faa7 100644
--- a/src/Mod/Fem/InitGui.py
+++ b/src/Mod/Fem/InitGui.py
@@ -54,6 +54,7 @@ class FemWorkbench (Workbench):
import _CommandFEMMesh2Mesh
import _CommandMeshGmshFromShape
import _CommandMeshNetgenFromShape
+ import _CommandMeshGroup
import _CommandMeshRegion
import _CommandAnalysis
import _CommandShellThickness
diff --git a/src/Mod/Fem/TaskPanelFemMeshGroup.ui b/src/Mod/Fem/TaskPanelFemMeshGroup.ui
new file mode 100644
index 000000000..6a7cf9bb9
--- /dev/null
+++ b/src/Mod/Fem/TaskPanelFemMeshGroup.ui
@@ -0,0 +1,120 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 350
+ 500
+
+
+
+ Mesh group
+
+
+
-
+
+
+
+ 16777215
+ 1677215
+
+
+
+ Identifier used for mesh export
+
+
+
-
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+ Name
+
+
+ true
+
+
+
+ -
+
+
+ Label
+
+
+
+
+
+
+
+
+ -
+
+
+ References
+
+
+
-
+
+
+ Add reference
+
+
+
+ -
+
+
+ -
+
+
-
+
+
+ Solid
+
+
+
+ -
+
+
+ Face, Edge, Vertex
+
+
+ true
+
+
+
+ -
+
+
+ <html><head/><body><p>Selection</p></body></html>
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
diff --git a/src/Mod/Fem/TaskPanelShowResult.ui b/src/Mod/Fem/TaskPanelShowResult.ui
index af2b547d0..4b74bd91e 100644
--- a/src/Mod/Fem/TaskPanelShowResult.ui
+++ b/src/Mod/Fem/TaskPanelShowResult.ui
@@ -270,8 +270,38 @@
-
+
+
+ 0
+ 17
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ 1
+
- Available: Disp(x,y,z) Principal stresses (P1,P2,P3)
+ Available: Disp(x,y,z) Principal stresses(P1,P2,P3) Stress(sx,sy,sz) Strain (ex,ey,ez)
+
+
+ false
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+ -1
+
+
+ Qt::NoTextInteraction
diff --git a/src/Mod/Fem/_CommandMeshGroup.py b/src/Mod/Fem/_CommandMeshGroup.py
new file mode 100644
index 000000000..242718ea7
--- /dev/null
+++ b/src/Mod/Fem/_CommandMeshGroup.py
@@ -0,0 +1,57 @@
+# ***************************************************************************
+# * *
+# * Copyright (c) 2016 - Bernd Hahnebach *
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU Lesser General Public License (LGPL) *
+# * as published by the Free Software Foundation; either version 2 of *
+# * the License, or (at your option) any later version. *
+# * for detail see the LICENCE text file. *
+# * *
+# * This program is distributed in the hope that it will be useful, *
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# * GNU Library General Public License for more details. *
+# * *
+# * You should have received a copy of the GNU Library General Public *
+# * License along with this program; if not, write to the Free Software *
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+# * USA *
+# * *
+# ***************************************************************************
+
+__title__ = "_CommandMeshGroup"
+__author__ = "Bernd Hahnebach"
+__url__ = "http://www.freecadweb.org"
+
+## @package CommandMeshGroup
+# \ingroup FEM
+
+import FreeCAD
+from FemCommands import FemCommands
+import FreeCADGui
+from PySide import QtCore
+
+
+class _CommandMeshGroup(FemCommands):
+ "The Fem_MeshGroup command definition"
+ def __init__(self):
+ super(_CommandMeshGroup, self).__init__()
+ self.resources = {'Pixmap': 'fem-femmesh-from-shape',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_MeshGroup", "FEM mesh group"),
+ 'Accel': "M, G",
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_MeshGroup", "Creates a FEM mesh group")}
+ self.is_active = 'with_gmsh_femmesh'
+
+ def Activated(self):
+ FreeCAD.ActiveDocument.openTransaction("Create FemMeshGroup")
+ FreeCADGui.addModule("FemMeshGroup")
+ sel = FreeCADGui.Selection.getSelection()
+ if (len(sel) == 1):
+ sobj = sel[0]
+ if len(sel) == 1 and hasattr(sobj, "Proxy") and sobj.Proxy.Type == "FemMeshGmsh":
+ FreeCADGui.doCommand("FemMeshGroup.makeFemMeshGroup(App.ActiveDocument." + sobj.Name + ")")
+
+ FreeCADGui.Selection.clearSelection()
+
+FreeCADGui.addCommand('Fem_MeshGroup', _CommandMeshGroup())
diff --git a/src/Mod/Fem/_FemMeshGmsh.py b/src/Mod/Fem/_FemMeshGmsh.py
index ebbffe79c..0cf2ebbca 100644
--- a/src/Mod/Fem/_FemMeshGmsh.py
+++ b/src/Mod/Fem/_FemMeshGmsh.py
@@ -46,6 +46,9 @@ class _FemMeshGmsh():
obj.addProperty("App::PropertyLinkList", "MeshRegionList", "Base", "Mesh regions of the mesh")
obj.MeshRegionList = []
+ obj.addProperty("App::PropertyLinkList", "MeshGroupList", "Base", "Mesh groups of the mesh")
+ obj.MeshRegionList = []
+
obj.addProperty("App::PropertyLink", "Part", "FEM Mesh", "Part object to mesh")
obj.Part = None
diff --git a/src/Mod/Fem/_FemMeshGroup.py b/src/Mod/Fem/_FemMeshGroup.py
new file mode 100644
index 000000000..84380dac6
--- /dev/null
+++ b/src/Mod/Fem/_FemMeshGroup.py
@@ -0,0 +1,40 @@
+# ***************************************************************************
+# * *
+# * Copyright (c) 2016 - Bernd Hahnebach *
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU Lesser General Public License (LGPL) *
+# * as published by the Free Software Foundation; either version 2 of *
+# * the License, or (at your option) any later version. *
+# * for detail see the LICENCE text file. *
+# * *
+# * This program is distributed in the hope that it will be useful, *
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# * GNU Library General Public License for more details. *
+# * *
+# * You should have received a copy of the GNU Library General Public *
+# * License along with this program; if not, write to the Free Software *
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+# * USA *
+# * *
+# ***************************************************************************
+
+__title__ = "_FemMeshGroup"
+__author__ = "Bernd Hahnebach"
+__url__ = "http://www.freecadweb.org"
+
+## @package FemMeshGroup
+# \ingroup FEM
+
+
+class _FemMeshGroup:
+ "The FemMeshGroup object"
+ def __init__(self, obj):
+ obj.addProperty("App::PropertyBool", "UseLabel", "MeshGroupProperties", "The identifier used for export (True: Label, False: Name)")
+ obj.addProperty("App::PropertyLinkSubList", "References", "MeshGroupShapes", "List of FEM mesh group shapes")
+ obj.Proxy = self
+ self.Type = "FemMeshGroup"
+
+ def execute(self, obj):
+ return
diff --git a/src/Mod/Fem/_TaskPanelFemMeshGroup.py b/src/Mod/Fem/_TaskPanelFemMeshGroup.py
new file mode 100644
index 000000000..018d882a3
--- /dev/null
+++ b/src/Mod/Fem/_TaskPanelFemMeshGroup.py
@@ -0,0 +1,190 @@
+# ***************************************************************************
+# * *
+# * Copyright (c) 2016 - Bernd Hahnebach *
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU Lesser General Public License (LGPL) *
+# * as published by the Free Software Foundation; either version 2 of *
+# * the License, or (at your option) any later version. *
+# * for detail see the LICENCE text file. *
+# * *
+# * This program is distributed in the hope that it will be useful, *
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# * GNU Library General Public License for more details. *
+# * *
+# * You should have received a copy of the GNU Library General Public *
+# * License along with this program; if not, write to the Free Software *
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+# * USA *
+# * *
+# ***************************************************************************
+
+__title__ = "_TaskPanelFemMeshGroup"
+__author__ = "Bernd Hahnebach"
+__url__ = "http://www.freecadweb.org"
+
+## @package TaskPanelFemMeshGroup
+# \ingroup FEM
+
+import FreeCAD
+import FreeCADGui
+from PySide import QtGui
+from PySide import QtCore
+
+
+class _TaskPanelFemMeshGroup:
+ '''The TaskPanel for editing References property of FemMeshGroup objects'''
+ def __init__(self, obj):
+ FreeCADGui.Selection.clearSelection()
+ self.sel_server = None
+ self.obj = obj
+ self.selection_mode_solid = False
+ self.selection_mode_std_print_message = "Select Faces, Edges and Vertices by single click on them to add them to the list."
+ self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
+
+ self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/TaskPanelFemMeshGroup.ui")
+ QtCore.QObject.connect(self.form.rb_name, QtCore.SIGNAL("toggled(bool)"), self.choose_exportidentifier_name)
+ QtCore.QObject.connect(self.form.rb_label, QtCore.SIGNAL("toggled(bool)"), self.choose_exportidentifier_label)
+ QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
+ QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
+ QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
+ self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+ self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
+
+ self.get_meshgroup_props()
+ self.update()
+
+ def accept(self):
+ self.set_meshgroup_props()
+ if self.sel_server:
+ FreeCADGui.Selection.removeObserver(self.sel_server)
+ FreeCADGui.ActiveDocument.resetEdit()
+ FreeCAD.ActiveDocument.recompute()
+ return True
+
+ def reject(self):
+ if self.sel_server:
+ FreeCADGui.Selection.removeObserver(self.sel_server)
+ FreeCADGui.ActiveDocument.resetEdit()
+ return True
+
+ def get_meshgroup_props(self):
+ self.use_label = self.obj.UseLabel
+ self.references = []
+ if self.obj.References:
+ self.tuplereferences = self.obj.References
+ self.get_references()
+
+ def set_meshgroup_props(self):
+ self.obj.References = self.references
+ self.obj.UseLabel = self.use_label
+
+ def update(self):
+ 'fills the widgets'
+ self.form.rb_name.setChecked(not self.use_label)
+ self.form.rb_label.setChecked(self.use_label)
+ self.rebuild_list_References()
+
+ def choose_exportidentifier_name(self, state):
+ self.use_label = not state
+
+ def choose_exportidentifier_label(self, state):
+ self.use_label = state
+
+ def choose_selection_mode_standard(self, state):
+ self.selection_mode_solid = not state
+ if self.sel_server and not self.selection_mode_solid:
+ print(self.selection_mode_std_print_message)
+
+ def choose_selection_mode_solid(self, state):
+ self.selection_mode_solid = state
+ if self.sel_server and self.selection_mode_solid:
+ print(self.selection_mode_solid_print_message)
+
+ def get_references(self):
+ for ref in self.tuplereferences:
+ for elem in ref[1]:
+ self.references.append((ref[0], elem))
+
+ def references_list_right_clicked(self, QPos):
+ self.form.contextMenu = QtGui.QMenu()
+ menu_item = self.form.contextMenu.addAction("Remove Reference")
+ if not self.references:
+ menu_item.setDisabled(True)
+ self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
+ parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
+ self.form.contextMenu.move(parentPosition + QPos)
+ self.form.contextMenu.show()
+
+ def remove_reference(self):
+ if not self.references:
+ return
+ currentItemName = str(self.form.list_References.currentItem().text())
+ for ref in self.references:
+ refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
+ if refname_to_compare_listentry == currentItemName:
+ self.references.remove(ref)
+ self.rebuild_list_References()
+
+ def add_references(self):
+ '''Called if Button add_reference is triggered'''
+ # in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
+ # here the addReference button EditTaskPanel has to be triggered to start selection mode
+ FreeCADGui.Selection.clearSelection()
+ # start SelectionObserver and parse the function to add the References to the widget
+ if self.selection_mode_solid: # print message on button click
+ print_message = self.selection_mode_solid_print_message
+ else:
+ print_message = self.selection_mode_std_print_message
+ import FemSelectionObserver
+ self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
+
+ def selectionParser(self, selection):
+ print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
+ if hasattr(selection[0], "Shape") and selection[1]:
+ elt = selection[0].Shape.getElement(selection[1])
+ if self.selection_mode_solid:
+ # in solid selection mode use edges and faces for selection of a solid
+ solid_to_add = None
+ if elt.ShapeType == 'Edge':
+ found_edge = False
+ for i, s in enumerate(selection[0].Shape.Solids):
+ for e in s.Edges:
+ if elt.isSame(e):
+ if not found_edge:
+ solid_to_add = str(i + 1)
+ else:
+ FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
+ solid_to_add = None
+ found_edge = True
+ elif elt.ShapeType == 'Face':
+ found_face = False
+ for i, s in enumerate(selection[0].Shape.Solids):
+ for e in s.Faces:
+ if elt.isSame(e):
+ if not found_face:
+ solid_to_add = str(i + 1)
+ else:
+ FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
+ solid_to_add = None
+ found_edge = True
+ if solid_to_add:
+ selection = (selection[0], 'Solid' + solid_to_add)
+ print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
+ else:
+ return
+ if selection not in self.references:
+ self.references.append(selection)
+ self.rebuild_list_References()
+ else:
+ FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
+
+ def rebuild_list_References(self):
+ self.form.list_References.clear()
+ items = []
+ for ref in self.references:
+ item_name = ref[0].Name + ':' + ref[1]
+ items.append(item_name)
+ for listItemName in sorted(items):
+ self.form.list_References.addItem(listItemName)
diff --git a/src/Mod/Fem/_TaskPanelShowResult.py b/src/Mod/Fem/_TaskPanelShowResult.py
index 5c713eb97..8392df24d 100644
--- a/src/Mod/Fem/_TaskPanelShowResult.py
+++ b/src/Mod/Fem/_TaskPanelShowResult.py
@@ -21,7 +21,7 @@
# ***************************************************************************
__title__ = "Result Control Task Panel"
-__author__ = "Juergen Riegel"
+__author__ = "Juergen Riegel, Michael Hindley"
__url__ = "http://www.freecadweb.org"
## @package TaskPanelShowResult
@@ -231,7 +231,15 @@ class _TaskPanelShowResult:
x = np.array(dispvectors[:, 0])
y = np.array(dispvectors[:, 1])
z = np.array(dispvectors[:, 2])
- userdefined_eq = x + y + z + T + Von + P1 + P2 + P3 # Dummy equation to get around flake8, varibles not being used
+ stressvectors = np.array(self.result_object.StressVectors)
+ sx = np.array(stressvectors[:, 0])
+ sy = np.array(stressvectors[:, 1])
+ sz = np.array(stressvectors[:, 2])
+ strainvectors = np.array(self.result_object.StrainVectors)
+ ex = np.array(strainvectors[:, 0])
+ ey = np.array(strainvectors[:, 1])
+ ez = np.array(strainvectors[:, 2])
+ userdefined_eq = x + y + z + T + Von + P1 + P2 + P3 + sx + sy + sz + ex + ey + ez # Dummy equation to get around flake8, varibles not being used
userdefined_eq = self.form.user_def_eq.toPlainText() # Get equation to be used
UserDefinedFormula = eval(userdefined_eq).tolist()
self.result_object.UserDefined = UserDefinedFormula
diff --git a/src/Mod/Fem/_ViewProviderFemMeshGmsh.py b/src/Mod/Fem/_ViewProviderFemMeshGmsh.py
index 02f3a7880..7948933a8 100644
--- a/src/Mod/Fem/_ViewProviderFemMeshGmsh.py
+++ b/src/Mod/Fem/_ViewProviderFemMeshGmsh.py
@@ -112,7 +112,7 @@ class _ViewProviderFemMeshGmsh:
return None
def claimChildren(self):
- return self.Object.MeshRegionList
+ return (self.Object.MeshRegionList + self.Object.MeshGroupList)
def onDelete(self, feature, subelements):
try:
diff --git a/src/Mod/Fem/_ViewProviderFemMeshGroup.py b/src/Mod/Fem/_ViewProviderFemMeshGroup.py
new file mode 100644
index 000000000..c03377f0b
--- /dev/null
+++ b/src/Mod/Fem/_ViewProviderFemMeshGroup.py
@@ -0,0 +1,89 @@
+# ***************************************************************************
+# * *
+# * Copyright (c) 2016 - Bernd Hahnebach *
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU Lesser General Public License (LGPL) *
+# * as published by the Free Software Foundation; either version 2 of *
+# * the License, or (at your option) any later version. *
+# * for detail see the LICENCE text file. *
+# * *
+# * This program is distributed in the hope that it will be useful, *
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# * GNU Library General Public License for more details. *
+# * *
+# * You should have received a copy of the GNU Library General Public *
+# * License along with this program; if not, write to the Free Software *
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+# * USA *
+# * *
+# ***************************************************************************
+
+__title__ = "_ViewProviderFemMeshGroup"
+__author__ = "Bernd Hahnebach"
+__url__ = "http://www.freecadweb.org"
+
+## @package ViewProviderFemMeshGroup
+# \ingroup FEM
+
+import FreeCAD
+import FreeCADGui
+from pivy import coin
+
+
+class _ViewProviderFemMeshGroup:
+ "A View Provider for the FemMeshGroup object"
+ def __init__(self, vobj):
+ vobj.Proxy = self
+
+ def getIcon(self):
+ return ":/icons/fem-femmesh-from-shape.svg"
+
+ def attach(self, vobj):
+ self.ViewObject = vobj
+ self.Object = vobj.Object
+ self.standard = coin.SoGroup()
+ vobj.addDisplayMode(self.standard, "Standard")
+
+ def getDisplayModes(self, obj):
+ return ["Standard"]
+
+ def getDefaultDisplayMode(self):
+ return "Standard"
+
+ def updateData(self, obj, prop):
+ return
+
+ def onChanged(self, vobj, prop):
+ return
+
+ def setEdit(self, vobj, mode=0):
+ # hide all meshes
+ for o in FreeCAD.ActiveDocument.Objects:
+ if o.isDerivedFrom("Fem::FemMeshObject"):
+ o.ViewObject.hide()
+ # show task panel
+ import _TaskPanelFemMeshGroup
+ taskd = _TaskPanelFemMeshGroup._TaskPanelFemMeshGroup(self.Object)
+ taskd.obj = vobj.Object
+ FreeCADGui.Control.showDialog(taskd)
+ return True
+
+ def unsetEdit(self, vobj, mode=0):
+ FreeCADGui.Control.closeDialog()
+ return
+
+ def doubleClicked(self, vobj):
+ doc = FreeCADGui.getDocument(vobj.Object.Document)
+ if not doc.getInEdit():
+ doc.setEdit(vobj.Object.Name)
+ else:
+ FreeCAD.Console.PrintError('Active Task Dialog found! Please close this one first!\n')
+ return True
+
+ def __getstate__(self):
+ return None
+
+ def __setstate__(self, state):
+ return None
diff --git a/src/Mod/Fem/ccxFrdReader.py b/src/Mod/Fem/ccxFrdReader.py
index d312ebc81..060baeabb 100644
--- a/src/Mod/Fem/ccxFrdReader.py
+++ b/src/Mod/Fem/ccxFrdReader.py
@@ -54,15 +54,19 @@ def readResult(frd_input):
elements_quad4 = {}
elements_quad8 = {}
elements_seg2 = {}
+ elements_seg3 = {}
results = []
mode_results = {}
mode_disp = {}
mode_stress = {}
+ mode_stressv = {}
+ mode_strain = {}
mode_temp = {}
mode_disp_found = False
nodes_found = False
mode_stress_found = False
+ mode_strain_found = False
mode_temp_found = False
mode_time_found = False
elements_found = False
@@ -250,6 +254,14 @@ def readResult(frd_input):
nd1 = int(line[3:13])
nd2 = int(line[13:23])
elements_seg2[elem] = (nd1, nd2)
+ elif elemType == 12:
+ # B32 CalculiX --> seg3 FreeCAD
+ # Also D element element number
+ # N1, N3 ,N2 Order in outpufile is 1,3,2
+ nd1 = int(line[3:13])
+ nd3 = int(line[13:23])
+ nd2 = int(line[23:33])
+ elements_seg3[elem] = (nd1, nd2, nd3)
# Check if we found new eigenmode
if line[5:10] == "PMODE":
@@ -266,7 +278,7 @@ def readResult(frd_input):
mode_disp[elem] = FreeCAD.Vector(mode_disp_x, mode_disp_y, mode_disp_z)
if line[5:11] == "STRESS":
mode_stress_found = True
- # we found a displacement line in the frd file
+ # we found a stress line in the frd file
if mode_stress_found and (line[1:3] == "-1"):
elem = int(line[4:13])
stress_1 = float(line[13:25])
@@ -276,6 +288,19 @@ def readResult(frd_input):
stress_5 = float(line[61:73])
stress_6 = float(line[73:85])
mode_stress[elem] = (stress_1, stress_2, stress_3, stress_4, stress_5, stress_6)
+ mode_stressv[elem] = FreeCAD.Vector(stress_1, stress_2, stress_3)
+ if line[5:13] == "TOSTRAIN":
+ mode_strain_found = True
+ # we found a strain line in the frd file
+ if mode_strain_found and (line[1:3] == "-1"):
+ elem = int(line[4:13])
+ strain_1 = float(line[13:25])
+ strain_2 = float(line[25:37])
+ strain_3 = float(line[37:49])
+# strain_4 = float(line[49:61]) #Not used in vector
+# strain_5 = float(line[61:73])
+# strain_6 = float(line[73:85])
+ mode_strain[elem] = FreeCAD.Vector(strain_1, strain_2, strain_3)
# Check if we found a time step
if line[4:10] == "1PSTEP":
mode_time_found = True
@@ -309,6 +334,8 @@ def readResult(frd_input):
mode_results['number'] = eigenmode
mode_results['disp'] = mode_disp
mode_results['stress'] = mode_stress
+ mode_results['stressv'] = mode_stressv
+ mode_results['strainv'] = mode_strain
mode_results['temp'] = mode_temp
mode_results['time'] = timestep
results.append(mode_results)
@@ -322,6 +349,8 @@ def readResult(frd_input):
mode_results['number'] = eigenmode
mode_results['disp'] = mode_disp
mode_results['stress'] = mode_stress
+ mode_results['stressv'] = mode_stressv
+ mode_results['strainv'] = mode_strain
mode_results['time'] = 0 # Dont return time if static
results.append(mode_results)
mode_disp = {}
@@ -336,7 +365,7 @@ def readResult(frd_input):
return {'Nodes': nodes,
'Hexa8Elem': elements_hexa8, 'Penta6Elem': elements_penta6, 'Tetra4Elem': elements_tetra4, 'Tetra10Elem': elements_tetra10,
'Penta15Elem': elements_penta15, 'Hexa20Elem': elements_hexa20, 'Tria3Elem': elements_tria3, 'Tria6Elem': elements_tria6,
- 'Quad4Elem': elements_quad4, 'Quad8Elem': elements_quad8, 'Seg2Elem': elements_seg2,
+ 'Quad4Elem': elements_quad4, 'Quad8Elem': elements_quad8, 'Seg2Elem': elements_seg2, 'Seg3Elem': elements_seg3,
'Results': results}
@@ -421,6 +450,8 @@ def importFrd(filename, analysis=None, result_name_prefix=None):
break
disp = result_set['disp']
+ stressv = result_set['stressv']
+ strainv = result_set['strainv']
no_of_values = len(disp)
displacement = []
for k, v in disp.iteritems():
@@ -438,6 +469,8 @@ def importFrd(filename, analysis=None, result_name_prefix=None):
if len(disp) > 0:
results.DisplacementVectors = map((lambda x: x * scale), disp.values())
+ results.StressVectors = map((lambda x: x * scale), stressv.values())
+ results.StrainVectors = map((lambda x: x * scale), strainv.values())
results.NodeNumbers = disp.keys()
if(mesh_object):
results.Mesh = mesh_object
diff --git a/src/Mod/OpenSCAD/OpenSCADUtils.py b/src/Mod/OpenSCAD/OpenSCADUtils.py
index 26ab35327..1785d430d 100644
--- a/src/Mod/OpenSCAD/OpenSCADUtils.py
+++ b/src/Mod/OpenSCAD/OpenSCADUtils.py
@@ -30,10 +30,10 @@ the module
'''
try:
+ from PySide import QtGui
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text):
"convenience function for Qt translator"
- from PySide import QtGui
return QtGui.QApplication.translate(context, text, None, _encoding)
except AttributeError:
def translate(context, text):
diff --git a/src/Mod/Part/App/TopoShapePy.xml b/src/Mod/Part/App/TopoShapePy.xml
index ab11fe4eb..edc807ca9 100644
--- a/src/Mod/Part/App/TopoShapePy.xml
+++ b/src/Mod/Part/App/TopoShapePy.xml
@@ -186,7 +186,7 @@ Intersection of this and a given list of topo shapes.
Supports:
- Fuzzy Boolean operations (global tolerance for a Boolean operation)
-- Support of multiple arguments for a single Boolean operation (s1 AND (s2 OR s2))
+- Support of multiple arguments for a single Boolean operation (s1 AND (s2 OR s3))
- Parallelization of Boolean Operations algorithm
OCC 6.9.0 or later is required.
@@ -203,7 +203,7 @@ Section of this and a given list of topo shapes.
Supports:
- Fuzzy Boolean operations (global tolerance for a Boolean operation)
-- Support of multiple arguments for a single Boolean operation
+- Support of multiple arguments for a single Boolean operation (s1 AND (s2 OR s3))
- Parallelization of Boolean Operations algorithm
OCC 6.9.0 or later is required.
diff --git a/src/Mod/Part/BOPTools/SplitFeatures.py b/src/Mod/Part/BOPTools/SplitFeatures.py
index 5e9afcec9..1d639c72a 100644
--- a/src/Mod/Part/BOPTools/SplitFeatures.py
+++ b/src/Mod/Part/BOPTools/SplitFeatures.py
@@ -37,18 +37,18 @@ if FreeCAD.GuiUp:
#-------------------------- translation-related code ----------------------------------------
#(see forum thread "A new Part tool is being born... JoinFeatures!"
#http://forum.freecadweb.org/viewtopic.php?f=22&t=11112&start=30#p90239 )
-try:
- _fromUtf8 = QtCore.QString.fromUtf8
-except Exception:
- def _fromUtf8(s):
- return s
-try:
- _encoding = QtGui.QApplication.UnicodeUTF8
- def _translate(context, text, disambig):
- return QtGui.QApplication.translate(context, text, disambig, _encoding)
-except AttributeError:
- def _translate(context, text, disambig):
- return QtGui.QApplication.translate(context, text, disambig)
+ try:
+ _fromUtf8 = QtCore.QString.fromUtf8
+ except Exception:
+ def _fromUtf8(s):
+ return s
+ try:
+ _encoding = QtGui.QApplication.UnicodeUTF8
+ def _translate(context, text, disambig):
+ return QtGui.QApplication.translate(context, text, disambig, _encoding)
+ except AttributeError:
+ def _translate(context, text, disambig):
+ return QtGui.QApplication.translate(context, text, disambig)
#--------------------------/translation-related code ----------------------------------------
def getIconPath(icon_dot_svg):
diff --git a/src/Mod/Part/Gui/TaskCheckGeometry.h b/src/Mod/Part/Gui/TaskCheckGeometry.h
index 4910412b5..30822e608 100644
--- a/src/Mod/Part/Gui/TaskCheckGeometry.h
+++ b/src/Mod/Part/Gui/TaskCheckGeometry.h
@@ -99,7 +99,7 @@ public:
~TaskCheckGeometryResults();
QString getShapeContentString();
-private slots:
+private Q_SLOTS:
void currentRowChanged (const QModelIndex ¤t, const QModelIndex &previous);
private:
diff --git a/src/Mod/Part/Gui/TaskDimension.h b/src/Mod/Part/Gui/TaskDimension.h
index 15f766c0b..6e05179f5 100644
--- a/src/Mod/Part/Gui/TaskDimension.h
+++ b/src/Mod/Part/Gui/TaskDimension.h
@@ -198,7 +198,7 @@ protected:
QPixmap *stepActive;
QPixmap *stepDone;
-private slots:
+private Q_SLOTS:
void selectionSlot(bool checked);
void buildPixmaps();
@@ -229,7 +229,7 @@ class DimensionControl : public QWidget
public:
explicit DimensionControl(QWidget* parent);
QPushButton *resetButton;
-public slots:
+public Q_SLOTS:
void toggle3dSlot(bool);
void toggleDeltaSlot(bool);
void clearAllSlot(bool);
@@ -250,7 +250,7 @@ public:
protected:
virtual void onSelectionChanged(const Gui::SelectionChanges& msg);
-protected slots:
+protected Q_SLOTS:
void selection1Slot(bool checked);
void selection2Slot(bool checked);
void resetDialogSlot(bool);
@@ -326,7 +326,7 @@ public:
protected:
virtual void onSelectionChanged(const Gui::SelectionChanges& msg);
-protected slots:
+protected Q_SLOTS:
void selection1Slot(bool checked);
void selection2Slot(bool checked);
void resetDialogSlot(bool);
diff --git a/src/Mod/Path/App/TooltablePyImp.cpp b/src/Mod/Path/App/TooltablePyImp.cpp
index d339b6195..0b2ad6607 100644
--- a/src/Mod/Path/App/TooltablePyImp.cpp
+++ b/src/Mod/Path/App/TooltablePyImp.cpp
@@ -121,12 +121,12 @@ int ToolPy::PyInit(PyObject* args, PyObject* kwd)
else
getToolPtr()->Material = Tool::MATUNDEFINED;
- getToolPtr()->Diameter = PyFloat_AsDouble(dia);
- getToolPtr()->LengthOffset = PyFloat_AsDouble(len);
- getToolPtr()->FlatRadius = PyFloat_AsDouble(fla);
- getToolPtr()->CornerRadius = PyFloat_AsDouble(cor);
- getToolPtr()->CuttingEdgeAngle = PyFloat_AsDouble(ang);
- getToolPtr()->CuttingEdgeHeight = PyFloat_AsDouble(hei);
+ getToolPtr()->Diameter = dia ? PyFloat_AsDouble(dia) : 0.0;
+ getToolPtr()->LengthOffset = len ? PyFloat_AsDouble(len) : 0.0;
+ getToolPtr()->FlatRadius = fla ? PyFloat_AsDouble(fla) : 0.0;
+ getToolPtr()->CornerRadius = cor ? PyFloat_AsDouble(cor) : 0.0;
+ getToolPtr()->CuttingEdgeAngle = ang ? PyFloat_AsDouble(ang) : 0.0;
+ getToolPtr()->CuttingEdgeHeight = hei ? PyFloat_AsDouble(hei) : 0.0;
return 0;
}
diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt
index 701ba44b1..f01eb9b64 100644
--- a/src/Mod/Path/CMakeLists.txt
+++ b/src/Mod/Path/CMakeLists.txt
@@ -53,6 +53,7 @@ SET(PathScripts_SRCS
PathScripts/PathSimpleCopy.py
PathScripts/PathStock.py
PathScripts/PathStop.py
+ PathScripts/PathHelix.py
PathScripts/PathSurface.py
PathScripts/PathToolLenOffset.py
PathScripts/PathToolLibraryManager.py
diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc
index 5be33f8ea..5e701bc5c 100644
--- a/src/Mod/Path/Gui/Resources/Path.qrc
+++ b/src/Mod/Path/Gui/Resources/Path.qrc
@@ -18,6 +18,7 @@
icons/Path-FaceProfile.svg
icons/Path-Face.svg
icons/Path-Heights.svg
+ icons/Path-Helix.svg
icons/Path-Hop.svg
icons/Path-Inspect.svg
icons/Path-Job.svg
diff --git a/src/Mod/Path/Gui/Resources/icons/Path-Helix.svg b/src/Mod/Path/Gui/Resources/icons/Path-Helix.svg
new file mode 100644
index 000000000..48b2ed309
--- /dev/null
+++ b/src/Mod/Path/Gui/Resources/icons/Path-Helix.svg
@@ -0,0 +1,548 @@
+
+
+
+
diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py
index b5f020413..22b13882b 100644
--- a/src/Mod/Path/InitGui.py
+++ b/src/Mod/Path/InitGui.py
@@ -65,6 +65,7 @@ class PathWorkbench (Workbench):
from PathScripts import PathCustom
from PathScripts import PathInspect
from PathScripts import PathSimpleCopy
+ from PathScripts import PathHelix
from PathScripts import PathEngrave
from PathScripts import PathSurface
from PathScripts import PathSanity
@@ -80,7 +81,7 @@ class PathWorkbench (Workbench):
projcmdlist = ["Path_Job", "Path_Post", "Path_Inspect", "Path_Sanity"]
toolcmdlist = ["Path_ToolLibraryEdit", "Path_LoadTool"]
prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_ToolLenOffset", "Path_Comment", "Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_FromShape"]
- twodopcmdlist = ["Path_Contour", "Path_Profile", "Path_Profile_Edges", "Path_Pocket", "Path_Drilling", "Path_Engrave", "Path_MillFace"]
+ twodopcmdlist = ["Path_Contour", "Path_Profile", "Path_Profile_Edges", "Path_Pocket", "Path_Drilling", "Path_Engrave", "Path_MillFace", "Path_Helix"]
threedopcmdlist = ["Path_Surfacing"]
modcmdlist = ["Path_Copy", "Path_CompoundExtended", "Path_Array", "Path_SimpleCopy" ]
dressupcmdlist = ["PathDressup_Dogbone", "PathDressup_DragKnife", "PathDressup_HoldingTags"]
diff --git a/src/Mod/Path/PathScripts/PathDressupDogbone.py b/src/Mod/Path/PathScripts/PathDressupDogbone.py
index 23e56841b..9aa008b7b 100644
--- a/src/Mod/Path/PathScripts/PathDressupDogbone.py
+++ b/src/Mod/Path/PathScripts/PathDressupDogbone.py
@@ -275,7 +275,7 @@ class Chord (object):
return dir == 'Back' or dir == side
def connectsTo(self, chord):
- return PathGeom.isRoughly(self.End, chord.Start)
+ return PathGeom.pointsCoincide(self.End, chord.Start)
class Bone:
def __init__(self, boneId, obj, lastCommand, inChord, outChord, smooth):
diff --git a/src/Mod/Path/PathScripts/PathHelix.py b/src/Mod/Path/PathScripts/PathHelix.py
new file mode 100644
index 000000000..da2e63a72
--- /dev/null
+++ b/src/Mod/Path/PathScripts/PathHelix.py
@@ -0,0 +1,818 @@
+# -*- coding: utf-8 -*-
+
+#***************************************************************************
+#* *
+#* Copyright (c) 2016 Lorenz Hüdepohl *
+#* *
+#* This program is free software; you can redistribute it and/or modify *
+#* it under the terms of the GNU Lesser General Public License (LGPL) *
+#* as published by the Free Software Foundation; either version 2 of *
+#* the License, or (at your option) any later version. *
+#* for detail see the LICENCE text file. *
+#* *
+#* This program is distributed in the hope that it will be useful, *
+#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+#* GNU Library General Public License for more details. *
+#* *
+#* You should have received a copy of the GNU Library General Public *
+#* License along with this program; if not, write to the Free Software *
+#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+#* USA *
+#* *
+#***************************************************************************
+
+import FreeCAD, Path
+if FreeCAD.GuiUp:
+ import FreeCADGui
+ from PySide import QtCore, QtGui
+ from DraftTools import translate
+
+from . import PathUtils
+from .PathUtils import fmt
+
+"""Helix Drill object and FreeCAD command"""
+
+if FreeCAD.GuiUp:
+ try:
+ _encoding = QtGui.QApplication.UnicodeUTF8
+ def translate(context, text, disambig=None):
+ return QtGui.QApplication.translate(context, text, disambig, _encoding)
+ except AttributeError:
+ def translate(context, text, disambig=None):
+ return QtGui.QApplication.translate(context, text, disambig)
+else:
+ def translate(context, text, disambig=None):
+ return text
+
+def z_cylinder(cyl):
+ """ Test if cylinder is aligned to z-Axis"""
+ if cyl.Surface.Axis.x != 0.0:
+ return False
+ if cyl.Surface.Axis.y != 0.0:
+ return False
+ return True
+
+def connected(edge, face):
+ for otheredge in face.Edges:
+ if edge.isSame(otheredge):
+ return True
+ return False
+
+def cylinders_in_selection():
+ from Part import Cylinder
+ selections = FreeCADGui.Selection.getSelectionEx()
+
+ cylinders = []
+
+ for selection in selections:
+ base = selection.Object
+ cylinders.append((base, []))
+ for feature in selection.SubElementNames:
+ subobj = getattr(base.Shape, feature)
+ if subobj.ShapeType =='Face':
+ if isinstance(subobj.Surface, Cylinder):
+ if z_cylinder(subobj):
+ cylinders[-1][1].append(feature)
+
+ return cylinders
+
+
+def helix_cut(center, r_out, r_in, dr, zmax, zmin, dz, safe_z, tool_diameter, vfeed, hfeed, direction, startside):
+ """
+ center: 2-tuple
+ (x0,y0) coordinates of center
+ r_out, r_in: floats
+ radial range, cut from outer radius r_out in layers of dr to inner radius r_in
+ zmax, zmin: floats
+ z-range, cut from zmax in layers of dz down to zmin
+ safe_z: float
+ safety layer height
+ tool_diameter: float
+ Width of tool
+ """
+ from numpy import ceil, allclose, linspace
+
+ if (zmax <= zmin):
+ return
+
+ out = "(helix_cut <{0}, {1}>, {2})".format(center[0], center[1],
+ ", ".join(map(str, (r_out, r_in, dr, zmax, zmin, dz, safe_z, tool_diameter, vfeed, hfeed, direction, startside))))
+
+ x0, y0 = center
+ nz = max(int(ceil((zmax - zmin)/dz)), 2)
+ zi = linspace(zmax, zmin, 2 * nz + 1)
+
+ if dr > tool_diameter:
+ FreeCAD.Console.PrintWarning("PathHelix: Warning, shortening dr to tool diameter!\n")
+ dr = tool_diameter
+
+ def xyz(x=None, y=None, z=None):
+ out = ""
+ if x is not None:
+ out += " X" + fmt(x)
+ if y is not None:
+ out += " Y" + fmt(y)
+ if z is not None:
+ out += " Z" + fmt(z)
+ return out
+
+ def rapid(x=None, y=None, z=None):
+ return "G0" + xyz(x,y,z) + "\n"
+
+ def F(f=None):
+ return (" F" + fmt(f) if f else "")
+
+ def feed(x=None, y=None, z=None, f=None):
+ return "G1" + xyz(x,y,z) + F(f) + "\n"
+
+ def arc(x,y,i,j,z,f):
+ if direction == "CW":
+ code = "G2"
+ elif direction == "CCW":
+ code = "G3"
+ return code + " I" + fmt(i) + " J" + fmt(j) + " X" + fmt(x) + " Y" + fmt(y) + " Z" + fmt(z) + F(f) + "\n"
+
+ def helix_cut_r(r):
+ out = ""
+ out += rapid(x=x0+r,y=y0)
+ out += rapid(z=zmax + tool_diameter)
+ out += feed(z=zmax,f=vfeed)
+ z=zmin
+ for i in range(1,nz+1):
+ out += arc(x0-r, y0, i=-r, j=0.0, z = zi[2*i-1], f=hfeed)
+ out += arc(x0+r, y0, i= r, j=0.0, z = zi[2*i], f=hfeed)
+ out += arc(x0-r, y0, i=-r, j=0.0, z = zmin, f=hfeed)
+ out += arc(x0+r, y0, i=r, j=0.0, z = zmin, f=hfeed)
+ out += feed(z=zmax + tool_diameter, f=vfeed)
+ out += rapid(z=safe_z)
+ return out
+
+ assert(r_out > 0.0)
+ assert(r_in >= 0.0)
+
+ msg = None
+ if r_out < 0.0:
+ msg = "r_out < 0"
+ elif r_in > 0 and r_out - r_in < tool_diameter:
+ msg = "r_out - r_in = {0} is < tool diameter of {1}".format(r_out - r_in, tool_diamater)
+ elif r_in == 0.0 and not r_out > tool_diameter/2.:
+ msg = "Cannot drill a hole of diameter {0} with a tool of diameter {1}".format(2 * r_out, tool_diameter)
+ elif not startside in ["inside", "outside"]:
+ msg = "Invalid value for parameter 'startside'"
+
+ if msg:
+ out += "(ERROR: Hole at {0}:".format((x0, y0, zmax)) + msg + ")\n"
+ FreeCAD.Console.PrintError("PathHelix: Hole at {0}:".format((x0, y0, zmax)) + msg + "\n")
+ return out
+
+ if r_in > 0:
+ out += "(annulus mode)\n"
+ r_out = r_out - tool_diameter/2
+ r_in = r_in + tool_diameter/2
+ if abs((r_out - r_in) / dr) < 1e-5:
+ radii = [(r_out + r_in)/2]
+ else:
+ nr = max(int(ceil((r_out - r_in)/dr)), 2)
+ radii = linspace(r_out, r_in, nr)
+ elif r_out <= 2 * dr:
+ out += "(single helix mode)\n"
+ radii = [r_out - tool_diameter/2]
+ assert(radii[0] > 0)
+ else:
+ out += "(full hole mode)\n"
+ r_out = r_out - tool_diameter/2
+ r_in = dr/2
+
+ nr = max(1 + int(ceil((r_out - r_in)/dr)), 2)
+ radii = linspace(r_out, r_in, nr)
+ assert(all(radii > 0))
+
+ if startside == "inside":
+ radii = radii[::-1]
+
+ for r in radii:
+ out += "(radius {0})\n".format(r)
+ out += helix_cut_r(r)
+
+ return out
+
+def features_by_centers(base, features):
+ import scipy.spatial
+ features = sorted(features,
+ key = lambda feature : getattr(base.Shape, feature).Surface.Radius,
+ reverse = True)
+
+ coordinates = [(cylinder.Surface.Center.x, cylinder.Surface.Center.y) for cylinder in
+ [getattr(base.Shape, feature) for feature in features]]
+
+ tree = scipy.spatial.KDTree(coordinates)
+ seen = {}
+
+ by_centers = {}
+ for n, feature in enumerate(features):
+ if n in seen:
+ continue
+ seen[n] = True
+
+ cylinder = getattr(base.Shape, feature)
+ xc, yc, _ = cylinder.Surface.Center
+ by_centers[xc, yc] = {cylinder.Surface.Radius : feature}
+
+ for coord in tree.query_ball_point((xc, yc), cylinder.Surface.Radius):
+ seen[coord] = True
+ cylinder = getattr(base.Shape, features[coord])
+ by_centers[xc, yc][cylinder.Surface.Radius] = features[coord]
+
+ return by_centers
+
+class ObjectPathHelix(object):
+
+ def __init__(self,obj):
+ # Basic
+ obj.addProperty("App::PropertyLinkSubList","Features","Path",translate("Features","Selected features for the drill operation"))
+ obj.addProperty("App::PropertyBool","Active","Path",translate("Active","Set to False to disable code generation"))
+ obj.addProperty("App::PropertyString","Comment","Path",translate("Comment","An optional comment for this profile, will appear in G-Code"))
+
+ # Helix specific
+ obj.addProperty("App::PropertyEnumeration", "Direction", "Helix Drill",
+ translate("Direction", "The direction of the circular cuts, clockwise (CW), or counter clockwise (CCW)"))
+ obj.Direction = ['CW','CCW']
+
+ obj.addProperty("App::PropertyEnumeration", "StartSide", "Helix Drill",
+ translate("Direction", "Start cutting from the inside or outside"))
+ obj.StartSide = ['inside','outside']
+
+ obj.addProperty("App::PropertyLength", "DeltaR", "Helix Drill",
+ translate("DeltaR", "Radius increment (must be smaller than tool diameter)"))
+
+ # Depth Properties
+ obj.addProperty("App::PropertyDistance", "Clearance", "Depths",
+ translate("Clearance","Safe distance above the top of the hole to which to retract the tool"))
+ obj.addProperty("App::PropertyLength", "StepDown", "Depths",
+ translate("StepDown","Incremental Step Down of Tool"))
+ obj.addProperty("App::PropertyBool","UseStartDepth","Depths",
+ translate("Use Start Depth","Set to True to manually specify a start depth"))
+ obj.addProperty("App::PropertyDistance", "StartDepth", "Depths",
+ translate("Start Depth","Starting Depth of Tool - first cut depth in Z"))
+ obj.addProperty("App::PropertyBool","UseFinalDepth","Depths",
+ translate("Use Final Depth","Set to True to manually specify a final depth"))
+ obj.addProperty("App::PropertyDistance", "FinalDepth", "Depths",
+ translate("Final Depth","Final Depth of Tool - lowest value in Z"))
+ obj.addProperty("App::PropertyDistance", "ThroughDepth", "Depths",
+ translate("Through Depth","Add this amount of additional cutting depth to open-ended holes. Only used if UseFinalDepth is False"))
+
+ # The current tool number, read-only
+ # this is apparently used internally, to keep track of tool chagnes
+ obj.addProperty("App::PropertyIntegerConstraint","ToolNumber","Tool",translate("PathProfile","The current tool in use"))
+ obj.ToolNumber = (0,0,1000,1)
+ obj.setEditorMode('ToolNumber',1) #make this read only
+
+ obj.Proxy = self
+
+ def __getstate__(self):
+ return None
+
+ def __setstate__(self,state):
+ return None
+
+ def execute(self,obj):
+ from Part import Circle, Cylinder, Plane
+ from math import sqrt
+
+ output = '(helix cut operation'
+ if obj.Comment:
+ output += ', '+ str(obj.Comment)+')\n'
+ else:
+ output += ')\n'
+
+ if obj.Features:
+ if not obj.Active:
+ obj.Path = Path.Path("(helix cut operation inactive)")
+ if obj.ViewObject:
+ obj.ViewObject.Visibility = False
+ return
+
+ toolload = PathUtils.getLastToolLoad(obj)
+
+ if toolload is None or toolload.ToolNumber == 0:
+ FreeCAD.Console.PrintError("PathHelix: No tool selected for helix cut operation, insert a tool change operation first\n")
+ obj.Path = Path.Path("(ERROR: no tool selected for helix cut operation)")
+ return
+
+ tool = PathUtils.getTool(obj, toolload.ToolNumber)
+
+ zsafe = max(baseobj.Shape.BoundBox.ZMax for baseobj, features in obj.Features) + obj.Clearance.Value
+ output += "G0 Z" + fmt(zsafe)
+
+ drill_jobs = []
+
+ for base, features in obj.Features:
+ for center, by_radius in features_by_centers(base, features).items():
+ radii = sorted(by_radius.keys(), reverse=True)
+ cylinders = map(lambda radius: getattr(base.Shape, by_radius[radius]), radii)
+ zsafe = max(cyl.BoundBox.ZMax for cyl in cylinders) + obj.Clearance.Value
+ cur_z = cylinders[0].BoundBox.ZMax
+ jobs = []
+
+ for cylinder in cylinders:
+ # Find other edge of current cylinder
+ other_edge = None
+ for edge in cylinder.Edges:
+ if isinstance(edge.Curve, Circle) and edge.Curve.Center.z != cur_z:
+ other_edge = edge
+ break
+
+ next_z = other_edge.Curve.Center.z
+ dz = next_z - cur_z
+ r = cylinder.Surface.Radius
+
+ if dz < 0:
+ # This is a closed hole if the face connected to the current cylinder at next_z has
+ # the cylinder's edge as its OuterWire
+ closed = None
+ for face in base.Shape.Faces:
+ if connected(other_edge, face) and not face.isSame(cylinder.Faces[0]):
+ wire = face.OuterWire
+ if len(wire.Edges) == 1 and wire.Edges[0].isSame(other_edge):
+ closed = True
+ else:
+ closed = False
+
+ if closed is None:
+ raise Exception("Cannot determine if this cylinder is closed on the z = {0} side".format(next_z))
+
+ xc, yc, _ = cylinder.Surface.Center
+ jobs.append(dict(xc=xc, yc=yc, zmin=next_z, zmax=cur_z, r_out=r, r_in=0.0, closed=closed, zsafe=zsafe))
+
+ elif dz > 0:
+ new_jobs = []
+ for job in jobs:
+ if job["zmin"] < next_z < job["zmax"]:
+ # split this job
+ job1 = dict(job)
+ job2 = dict(job)
+ job1["zmin"] = next_z
+ job2["zmax"] = next_z
+ job2["r_in"] = r
+ new_jobs.append(job1)
+ new_jobs.append(job2)
+ else:
+ new_jobs.append(job)
+ jobs = new_jobs
+ else:
+ FreeCAD.Console.PrintError("PathHelix: Encountered cylinder with zero height\n")
+ break
+
+ cur_z = next_z
+
+ if obj.UseStartDepth:
+ jobs = [job for job in jobs if job["zmin"] < obj.StartDepth.Value]
+ if jobs:
+ jobs[0]["zmax"] = obj.StartDepth.Value
+ if obj.UseFinalDepth:
+ jobs = [job for job in jobs if job["zmax"] > obj.FinalDepth.Value]
+ if jobs:
+ jobs[-1]["zmin"] = obj.FinalDepth.Value
+ else:
+ if not jobs[-1]["closed"]:
+ jobs[-1]["zmin"] -= obj.ThroughDepth.Value
+
+ drill_jobs.extend(jobs)
+
+ for job in drill_jobs:
+ output += helix_cut((job["xc"], job["yc"]), job["r_out"], job["r_in"], obj.DeltaR.Value,
+ job["zmax"], job["zmin"], obj.StepDown.Value,
+ job["zsafe"], tool.Diameter,
+ toolload.VertFeed.Value, toolload.HorizFeed.Value, obj.Direction, obj.StartSide)
+ output += '\n'
+
+ obj.Path = Path.Path(output)
+ if obj.ViewObject:
+ obj.ViewObject.Visibility = True
+
+taskpanels = {}
+
+class ViewProviderPathHelix(object):
+ def __init__(self,vobj):
+ vobj.Proxy = self
+
+ def attach(self,vobj):
+ self.Object = vobj.Object
+ return
+
+ def getIcon(self):
+ return ":/icons/Path-Helix.svg"
+
+ def setEdit(self, vobj, mode=0):
+ FreeCADGui.Control.closeDialog()
+ taskpanel = TaskPanel(vobj.Object)
+ FreeCADGui.Control.showDialog(taskpanel)
+ taskpanels[0] = taskpanel
+ return True
+
+ def __getstate__(self):
+ return None
+
+ def __setstate__(self, state):
+ return None
+
+class CommandPathHelix(object):
+ def GetResources(self):
+ return {'Pixmap' : 'Path-Helix',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathHelix","PathHelix"),
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathHelix","Creates a helix cut from selected circles")}
+
+ def IsActive(self):
+ if FreeCAD.ActiveDocument is not None:
+ for o in FreeCAD.ActiveDocument.Objects:
+ if o.Name[:3] == "Job":
+ return True
+ return False
+
+ def Activated(self):
+ import FreeCADGui
+ import Path
+ from PathScripts import PathUtils
+
+ FreeCAD.ActiveDocument.openTransaction(translate("PathHelix","Create a helix cut"))
+ FreeCADGui.addModule("PathScripts.PathHelix")
+
+ obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","PathHelix")
+ ObjectPathHelix(obj)
+ ViewProviderPathHelix(obj.ViewObject)
+
+ obj.Features = cylinders_in_selection()
+ obj.DeltaR = 1.0
+
+ toolLoad = PathUtils.getLastToolLoad(obj)
+ if toolLoad is not None:
+ obj.ToolNumber = toolLoad.ToolNumber
+ tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
+ if tool:
+ # start with 25% overlap
+ obj.DeltaR = tool.Diameter * 0.75
+
+ obj.Active = True
+ obj.Comment = ""
+
+ obj.Direction = "CW"
+ obj.StartSide = "inside"
+
+ obj.Clearance = 10.0
+ obj.StepDown = 1.0
+ obj.UseStartDepth = False
+ obj.StartDepth = 1.0
+ obj.UseFinalDepth = False
+ obj.FinalDepth = 0.0
+ obj.ThroughDepth = 0.0
+
+ PathUtils.addToJob(obj)
+
+ obj.ViewObject.startEditing()
+
+ FreeCAD.ActiveDocument.recompute()
+
+def print_exceptions(func):
+ from functools import wraps
+ import traceback
+ import sys
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except:
+ ex_type, ex, tb = sys.exc_info()
+ FreeCAD.Console.PrintError("".join(traceback.format_exception(ex_type, ex, tb)) + "\n")
+ raise
+ return wrapper
+
+def print_all_exceptions(cls):
+ for entry in dir(cls):
+ obj = getattr(cls, entry)
+ if not entry.startswith("__") and hasattr(obj, "__call__"):
+ setattr(cls, entry, print_exceptions(obj))
+ return cls
+
+@print_all_exceptions
+class TaskPanel(object):
+
+ def __init__(self, obj):
+ from Units import Quantity
+ self.obj = obj
+
+ ui = FreeCADGui.UiLoader()
+ layout = QtGui.QGridLayout()
+
+ headerStyle = "QLabel { font-weight: bold; font-size: large; }"
+ grayed_out = "background-color: #d0d0d0;"
+
+ self.previous_value = {}
+
+ def addWidget(widget):
+ row = layout.rowCount()
+ layout.addWidget(widget, row, 0, 1, 2)
+
+ def addWidgets(widget1, widget2):
+ row = layout.rowCount()
+ layout.addWidget(widget1, row, 0)
+ layout.addWidget(widget2, row, 1)
+
+ def heading(label):
+ heading = QtGui.QLabel(label)
+ heading.setStyleSheet(headerStyle)
+ addWidget(heading)
+
+ def addQuantity(property, labelstring, activator=None, max=None):
+ self.previous_value[property] = getattr(self.obj, property)
+ widget = ui.createWidget("Gui::InputField")
+
+ if activator:
+ self.previous_value[activator] = getattr(self.obj, activator)
+ currently_active = getattr(self.obj, activator)
+ label = QtGui.QCheckBox(labelstring)
+
+ def change(state):
+ setattr(self.obj, activator, label.isChecked())
+ if label.isChecked():
+ widget.setStyleSheet("")
+ else:
+ widget.setStyleSheet(grayed_out)
+ self.obj.Proxy.execute(self.obj)
+ FreeCAD.ActiveDocument.recompute()
+
+ label.stateChanged.connect(change)
+ label.setChecked(currently_active)
+ if not currently_active:
+ widget.setStyleSheet(grayed_out)
+ label.setToolTip(self.obj.getDocumentationOfProperty(activator))
+ else:
+ label = QtGui.QLabel(labelstring)
+ label.setToolTip(self.obj.getDocumentationOfProperty(property))
+
+ widget.setText(str(getattr(self.obj, property)))
+ widget.setToolTip(self.obj.getDocumentationOfProperty(property))
+
+ if max:
+ # cannot use widget.setMaximum() as apparently ui.createWidget()
+ # returns the object up-casted to QWidget.
+ widget.setProperty("maximum", max)
+
+ def change(quantity):
+ setattr(self.obj, property, quantity)
+ self.obj.Proxy.execute(self.obj)
+ FreeCAD.ActiveDocument.recompute()
+
+ QtCore.QObject.connect(widget, QtCore.SIGNAL("valueChanged(const Base::Quantity &)"), change)
+
+ addWidgets(label, widget)
+ return label, widget
+
+ def addCheckBox(property, label):
+ self.previous_value[property] = getattr(self.obj, property)
+ widget = QtGui.QCheckBox(label)
+ widget.setToolTip(self.obj.getDocumentationOfProperty(property))
+
+ def change(state):
+ setattr(self.obj, property, widget.isChecked())
+ self.obj.Proxy.execute(self.obj)
+ FreeCAD.ActiveDocument.recompute()
+ widget.stateChanged.connect(change)
+
+ widget.setChecked(getattr(self.obj, property))
+ addWidget(widget)
+
+ def addEnumeration(property, label, options):
+ self.previous_value[property] = getattr(self.obj, property)
+ label = QtGui.QLabel(label)
+ label.setToolTip(self.obj.getDocumentationOfProperty(property))
+ widget = QtGui.QComboBox()
+ widget.setToolTip(self.obj.getDocumentationOfProperty(property))
+ for option_label, option_value in options:
+ widget.addItem(option_label)
+ def change(index):
+ setattr(self.obj, property, options[index][1])
+ self.obj.Proxy.execute(self.obj)
+ FreeCAD.ActiveDocument.recompute()
+ widget.currentIndexChanged.connect(change)
+ addWidgets(label, widget)
+
+ self.featureTree = QtGui.QTreeWidget()
+ self.featureTree.setMinimumHeight(200)
+ self.featureTree.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
+ #self.featureTree.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
+ #self.featureTree.setDefaultDropAction(QtCore.Qt.MoveAction)
+ self.fillFeatureTree()
+ sm = self.featureTree.selectionModel()
+ sm.selectionChanged.connect(self.selectFeatures)
+ addWidget(self.featureTree)
+ self.featureTree.expandAll()
+
+ self.addButton = QtGui.QPushButton("Add holes")
+ self.addButton.clicked.connect(self.addCylinders)
+
+ self.delButton = QtGui.QPushButton("Delete")
+ self.delButton.clicked.connect(self.delCylinders)
+
+ addWidgets(self.addButton, self.delButton)
+
+ heading("Drill parameters")
+ addCheckBox("Active", "Operation is active")
+ tool = PathUtils.getTool(self.obj,self.obj.ToolNumber)
+ if not tool:
+ drmax = None
+ else:
+ drmax = tool.Diameter
+ addQuantity("DeltaR", "Step in Radius", max=drmax)
+ addQuantity("StepDown", "Step in Z")
+ addEnumeration("Direction", "Cut direction", [("Clockwise", "CW"), ("Counter-Clockwise", "CCW")])
+ addEnumeration("StartSide", "Start Side", [("Start from inside", "inside"), ("Start from outside", "outside")])
+
+ heading("Cutting Depths")
+ addQuantity("Clearance", "Clearance Distance")
+ addQuantity("StartDepth", "Absolute start height", "UseStartDepth")
+
+ fdcheckbox, fdinput = addQuantity("FinalDepth", "Absolute final height", "UseFinalDepth")
+ tdlabel, tdinput = addQuantity("ThroughDepth", "Extra drill depth\nfor open holes")
+
+ # make ThroughDepth and FinalDepth mutually exclusive
+ def fd_change(state):
+ if fdcheckbox.isChecked():
+ tdinput.setStyleSheet(grayed_out)
+ else:
+ tdinput.setStyleSheet("")
+ fdcheckbox.stateChanged.connect(fd_change)
+
+ def td_change(quantity):
+ fdcheckbox.setChecked(False)
+ QtCore.QObject.connect(tdinput, QtCore.SIGNAL("valueChanged(const Base::Quantity &)"), td_change)
+
+ if obj.UseFinalDepth:
+ tdinput.setStyleSheet(grayed_out)
+
+ # add
+ widget = QtGui.QWidget()
+ widget.setLayout(layout)
+ self.form = widget
+
+ def addCylinders(self):
+ features_per_base = {}
+ for base, features in self.obj.Features:
+ features_per_base[base] = list(set(features))
+
+ for base, features in cylinders_in_selection():
+ for feature in features:
+ if base in features_per_base:
+ if not feature in features_per_base[base]:
+ features_per_base[base].append(feature)
+ else:
+ features_per_base[base] = [feature]
+
+ self.obj.Features = list(features_per_base.items())
+ self.featureTree.clear()
+ self.fillFeatureTree()
+ self.featureTree.expandAll()
+ self.obj.Proxy.execute(self.obj)
+ FreeCAD.ActiveDocument.recompute()
+
+ def delCylinders(self):
+ del_features = []
+
+ def delete_feature(item, base=None):
+ kind, feature = item.data(0, QtCore.Qt.UserRole)
+ assert(kind == "feature")
+
+ if base is None:
+ base_item = item.parent().parent()
+ _, base = base_item.data(0, QtCore.Qt.UserRole)
+
+ del_features.append((base, feature))
+ item.parent().takeChild(item.parent().indexOfChild(item))
+
+ def delete_hole(item, base=None):
+ kind, center = item.data(0, QtCore.Qt.UserRole)
+ assert(kind == "hole")
+
+ if base is None:
+ base_item = item.parent()
+ _, base = base_item.data(0, QtCore.Qt.UserRole)
+
+ for i in reversed(range(item.childCount())):
+ delete_feature(item.child(i), base=base)
+ item.parent().takeChild(item.parent().indexOfChild(item))
+
+ def delete_base(item):
+ kind, base = item.data(0, QtCore.Qt.UserRole)
+ assert(kind == "base")
+ for i in reversed(range(item.childCount())):
+ delete_hole(item.child(i), base=base)
+ self.featureTree.takeTopLevelItem(self.featureTree.indexOfTopLevelItem(item))
+
+ for item in self.featureTree.selectedItems():
+ kind, info = item.data(0, QtCore.Qt.UserRole)
+ if kind == "base":
+ delete_base(item)
+ elif kind == "hole":
+ parent = item.parent()
+ delete_hole(item)
+ if parent.childCount() == 0:
+ self.featureTree.takeTopLevelItem(self.featureTree.indexOfTopLevelItem(parent))
+ elif kind =="feature":
+ parent = item.parent()
+ delete_feature(item)
+ if parent.childCount() == 0:
+ parent.parent().takeChild(parent.parent().indexOfChild(parent))
+ else:
+ raise Exception("No such item kind: {0}".format(kind))
+
+ for base, features in cylinders_in_selection():
+ for feature in features:
+ del_features.append((base, feature))
+
+ new_features = []
+ for obj, features in self.obj.Features:
+ for feature in features:
+ if (obj, feature) not in del_features:
+ new_features.append((obj, feature))
+
+ self.obj.Features = new_features
+ self.obj.Proxy.execute(self.obj)
+ FreeCAD.ActiveDocument.recompute()
+
+ def fillFeatureTree(self):
+ for base, features in self.obj.Features:
+ base_item = QtGui.QTreeWidgetItem()
+ base_item.setText(0, base.Name)
+ base_item.setData(0, QtCore.Qt.UserRole, ("base", base))
+ self.featureTree.addTopLevelItem(base_item)
+ for center, by_radius in features_by_centers(base, features).items():
+ hole_item = QtGui.QTreeWidgetItem()
+ hole_item.setText(0, "Hole at ({0[0]:.2f}, {0[1]:.2f})".format(center))
+ hole_item.setData(0, QtCore.Qt.UserRole, ("hole", center))
+ base_item.addChild(hole_item)
+ for radius in sorted(by_radius.keys(), reverse=True):
+ feature = by_radius[radius]
+ cylinder = getattr(base.Shape, feature)
+ cyl_item = QtGui.QTreeWidgetItem()
+ cyl_item.setText(0, "Diameter {0:.2f}, {1}".format(2 * cylinder.Surface.Radius, feature))
+ cyl_item.setData(0, QtCore.Qt.UserRole, ("feature", feature))
+ hole_item.addChild(cyl_item)
+
+ def selectFeatures(self, selected, deselected):
+ FreeCADGui.Selection.clearSelection()
+ def select_feature(item, base=None):
+ kind, feature = item.data(0, QtCore.Qt.UserRole)
+ assert(kind == "feature")
+
+ if base is None:
+ base_item = item.parent().parent()
+ _, base = base_item.data(0, QtCore.Qt.UserRole)
+
+ FreeCADGui.Selection.addSelection(base, feature)
+
+ def select_hole(item, base=None):
+ kind, center = item.data(0, QtCore.Qt.UserRole)
+ assert(kind == "hole")
+
+ if base is None:
+ base_item = item.parent()
+ _, base = base_item.data(0, QtCore.Qt.UserRole)
+
+ for i in range(item.childCount()):
+ select_feature(item.child(i), base=base)
+
+ def select_base(item):
+ kind, base = item.data(0, QtCore.Qt.UserRole)
+ assert(kind == "base")
+
+ for i in range(item.childCount()):
+ select_hole(item.child(i), base=base)
+
+ for item in self.featureTree.selectedItems():
+ kind, info = item.data(0, QtCore.Qt.UserRole)
+
+ if kind == "base":
+ select_base(item)
+ elif kind == "hole":
+ select_hole(item)
+ elif kind == "feature":
+ select_feature(item)
+
+ def needsFullSpace(self):
+ return True
+
+ def accept(self):
+ FreeCADGui.ActiveDocument.resetEdit()
+ FreeCADGui.Control.closeDialog()
+
+ def reject(self):
+ for property in self.previous_value:
+ setattr(self.obj, property, self.previous_value[property])
+ self.obj.Proxy.execute(self.obj)
+ FreeCAD.ActiveDocument.recompute()
+ FreeCADGui.ActiveDocument.resetEdit()
+ FreeCADGui.Control.closeDialog()
+
+if FreeCAD.GuiUp:
+ import FreeCADGui
+ FreeCADGui.addCommand('Path_Helix',CommandPathHelix())
diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp
index d610f64e4..b2a1336c7 100644
--- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp
+++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp
@@ -29,6 +29,7 @@
#endif
#include
+#include
#include
#include
#include
@@ -3252,14 +3253,34 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
Base::Vector3d p1b = lineSeg1->getEndPoint();
Base::Vector3d p2a = lineSeg2->getStartPoint();
Base::Vector3d p2b = lineSeg2->getEndPoint();
- double length = DBL_MAX;
- for (int i=0; i <= 1; i++) {
- for (int j=0; j <= 1; j++) {
- double tmp = ((j?p2a:p2b)-(i?p1a:p1b)).Length();
- if (tmp < length) {
- length = tmp;
- PosId1 = i ? Sketcher::start : Sketcher::end;
- PosId2 = j ? Sketcher::start : Sketcher::end;
+
+ // Get the intersection point in 2d of the two lines if possible
+ Base::Line2d line1(Base::Vector2d(p1a.x, p1a.y), Base::Vector2d(p1b.x, p1b.y));
+ Base::Line2d line2(Base::Vector2d(p2a.x, p2a.y), Base::Vector2d(p2b.x, p2b.y));
+ Base::Vector2d s;
+ if (line1.Intersect(line2, s)) {
+ // get the end points of the line segments that are closest to the intersection point
+ Base::Vector3d s3d(s.x, s.y, p1a.z);
+ if (Base::DistanceP2(s3d, p1a) < Base::DistanceP2(s3d, p1b))
+ PosId1 = Sketcher::start;
+ else
+ PosId1 = Sketcher::end;
+ if (Base::DistanceP2(s3d, p2a) < Base::DistanceP2(s3d, p2b))
+ PosId2 = Sketcher::start;
+ else
+ PosId2 = Sketcher::end;
+ }
+ else {
+ // if all points are collinear
+ double length = DBL_MAX;
+ for (int i=0; i <= 1; i++) {
+ for (int j=0; j <= 1; j++) {
+ double tmp = Base::DistanceP2((j?p2a:p2b), (i?p1a:p1b));
+ if (tmp < length) {
+ length = tmp;
+ PosId1 = i ? Sketcher::start : Sketcher::end;
+ PosId2 = j ? Sketcher::start : Sketcher::end;
+ }
}
}
}
@@ -3280,8 +3301,8 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
}
}
- double ActAngle = atan2(-dir1.y*dir2.x+dir1.x*dir2.y,
- dir1.x*dir2.x+dir1.y*dir2.y);
+ double ActAngle = atan2(dir1.x*dir2.y-dir1.y*dir2.x,
+ dir1.y*dir2.y+dir1.x*dir2.x);
if (ActAngle < 0) {
ActAngle *= -1;
std::swap(GeoId1,GeoId2);
diff --git a/src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp b/src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp
index ea222095c..d40584f9e 100644
--- a/src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp
+++ b/src/Mod/Spreadsheet/Gui/qtcolorpicker.cpp
@@ -1,17 +1,17 @@
/****************************************************************************
**
** This file is part of a Qt Solutions component.
-**
+**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-**
+**
** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** Commercial Usage
+**
+** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Solutions Commercial License Agreement provided
** with the Software or, alternatively, in accordance with the terms
** contained in a written agreement between you and Nokia.
-**
+**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
@@ -19,29 +19,29 @@
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
+**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
-**
-** GNU General Public License Usage
+**
+** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
-**
+**
** Please note Third Party Software included with Qt Solutions may impose
** additional restrictions and it is the user's responsibility to ensure
** that they have met the licensing requirements of the GPL, LGPL, or Qt
** Solutions Commercial license and the relevant license of the Third
** Party Software they are using.
-**
+**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
-**
+**
****************************************************************************/
#include
@@ -169,7 +169,7 @@ class ColorPickerItem : public QFrame
public:
ColorPickerItem(const QColor &color = Qt::white, const QString &text = QString::null,
- QWidget *parent = 0);
+ QWidget *parent = 0);
~ColorPickerItem();
QColor color() const;
@@ -181,7 +181,7 @@ signals:
void clicked();
void selected();
-public slots:
+public Q_SLOTS:
void setColor(const QColor &color, const QString &text = QString());
protected:
@@ -205,7 +205,7 @@ class ColorPickerPopup : public QFrame
public:
ColorPickerPopup(int width, bool withColorDialog,
- QWidget *parent = 0);
+ QWidget *parent = 0);
~ColorPickerPopup();
void insertColor(const QColor &col, const QString &text, int index);
@@ -217,17 +217,17 @@ public:
ColorPickerItem *find(const QColor &col) const;
QColor color(int index) const;
-
+
void setLastSel(const QColor & col);
signals:
void selected(const QColor &);
void hid();
-public slots:
+public Q_SLOTS:
void getColorFromDialog();
-protected slots:
+protected Q_SLOTS:
void updateSelected();
protected:
@@ -268,7 +268,7 @@ private:
\sa QFrame
*/
QtColorPicker::QtColorPicker(QWidget *parent,
- int cols, bool enableColorDialog)
+ int cols, bool enableColorDialog)
: QPushButton(parent), popup(0), withColorDialog(enableColorDialog)
{
setFocusPolicy(Qt::StrongFocus);
@@ -288,7 +288,7 @@ QtColorPicker::QtColorPicker(QWidget *parent,
// Create color grid popup and connect to it.
popup = new ColorPickerPopup(cols, withColorDialog, this);
connect(popup, SIGNAL(selected(const QColor &)),
- SLOT(setCurrentColor(const QColor &)));
+ SLOT(setCurrentColor(const QColor &)));
connect(popup, SIGNAL(hid()), SLOT(popupClosed()));
// Connect this push button's pressed() signal.
@@ -434,18 +434,18 @@ void QtColorPicker::setStandardColors()
void QtColorPicker::setCurrentColor(const QColor &color)
{
if (color.isValid() && col == color) {
- emit colorSet(color);
+ Q_EMIT colorSet(color);
return;
}
if (col == color || !color.isValid())
- return;
+ return;
ColorPickerItem *item = popup->find(color);
if (!item) {
- insertColor(color, tr("Custom"));
- item = popup->find(color);
+ insertColor(color, tr("Custom"));
+ item = popup->find(color);
}
-
+
popup->setLastSel(color);
col = color;
@@ -457,8 +457,8 @@ void QtColorPicker::setCurrentColor(const QColor &color)
repaint();
item->setSelected(true);
- emit colorChanged(color);
- emit colorSet(color);
+ Q_EMIT colorChanged(color);
+ Q_EMIT colorSet(color);
}
/*!
@@ -471,9 +471,9 @@ void QtColorPicker::insertColor(const QColor &color, const QString &text, int in
{
popup->insertColor(color, text, index);
if (!firstInserted) {
- col = color;
- setText(text);
- firstInserted = true;
+ col = color;
+ setText(text);
+ firstInserted = true;
}
}
@@ -504,7 +504,7 @@ bool QtColorPicker::colorDialogEnabled() const
\code
void Drawer::mouseReleaseEvent(QMouseEvent *e)
{
- if (e->button() & RightButton) {
+ if (e->button() & RightButton) {
QColor color = QtColorPicker::getColor(mapToGlobal(e->pos()));
}
}
@@ -542,7 +542,7 @@ QColor QtColorPicker::getColor(const QPoint &point, bool allowCustomColors)
Constructs the popup widget.
*/
ColorPickerPopup::ColorPickerPopup(int width, bool withColorDialog,
- QWidget *parent)
+ QWidget *parent)
: QFrame(parent, Qt::Popup)
{
setFrameStyle(QFrame::StyledPanel);
@@ -553,13 +553,13 @@ ColorPickerPopup::ColorPickerPopup(int width, bool withColorDialog,
cols = width;
if (withColorDialog) {
- moreButton = new ColorPickerButton(this);
- moreButton->setFixedWidth(24);
- moreButton->setFixedHeight(21);
- moreButton->setFrameRect(QRect(2, 2, 20, 17));
- connect(moreButton, SIGNAL(clicked()), SLOT(getColorFromDialog()));
+ moreButton = new ColorPickerButton(this);
+ moreButton->setFixedWidth(24);
+ moreButton->setFixedHeight(21);
+ moreButton->setFrameRect(QRect(2, 2, 20, 17));
+ connect(moreButton, SIGNAL(clicked()), SLOT(getColorFromDialog()));
} else {
- moreButton = 0;
+ moreButton = 0;
}
eventLoop = 0;
@@ -586,8 +586,8 @@ ColorPickerPopup::~ColorPickerPopup()
ColorPickerItem *ColorPickerPopup::find(const QColor &col) const
{
for (int i = 0; i < items.size(); ++i) {
- if (items.at(i) && items.at(i)->color() == col)
- return items.at(i);
+ if (items.at(i) && items.at(i)->color() == col)
+ return items.at(i);
}
return 0;
@@ -626,7 +626,7 @@ void ColorPickerPopup::insertColor(const QColor &col, const QString &text, int i
connect(item, SIGNAL(selected()), SLOT(updateSelected()));
if (index == -1)
- index = items.count();
+ index = items.count();
items.insert((unsigned int)index, item);
regenerateGrid();
@@ -667,19 +667,19 @@ void ColorPickerPopup::updateSelected()
QLayoutItem *layoutItem;
int i = 0;
while ((layoutItem = grid->itemAt(i)) != 0) {
- QWidget *w = layoutItem->widget();
- if (w && w->inherits("ColorPickerItem")) {
- ColorPickerItem *litem = reinterpret_cast(layoutItem->widget());
- if (litem != sender())
- litem->setSelected(false);
- }
- ++i;
+ QWidget *w = layoutItem->widget();
+ if (w && w->inherits("ColorPickerItem")) {
+ ColorPickerItem *litem = reinterpret_cast(layoutItem->widget());
+ if (litem != sender())
+ litem->setSelected(false);
+ }
+ ++i;
}
if (sender() && sender()->inherits("ColorPickerItem")) {
- ColorPickerItem *item = (ColorPickerItem *)sender();
- lastSel = item->color();
- emit selected(item->color());
+ ColorPickerItem *item = (ColorPickerItem *)sender();
+ lastSel = item->color();
+ Q_EMIT selected(item->color());
}
hide();
@@ -691,7 +691,7 @@ void ColorPickerPopup::updateSelected()
void ColorPickerPopup::mouseReleaseEvent(QMouseEvent *e)
{
if (!rect().contains(e->pos()))
- hide();
+ hide();
}
/*! \internal
@@ -705,96 +705,96 @@ void ColorPickerPopup::keyPressEvent(QKeyEvent *e)
bool foundFocus = false;
for (int j = 0; !foundFocus && j < grid->rowCount(); ++j) {
- for (int i = 0; !foundFocus && i < grid->columnCount(); ++i) {
- if (widgetAt[j][i] && widgetAt[j][i]->hasFocus()) {
- curRow = j;
- curCol = i;
- foundFocus = true;
- break;
- }
- }
+ for (int i = 0; !foundFocus && i < grid->columnCount(); ++i) {
+ if (widgetAt[j][i] && widgetAt[j][i]->hasFocus()) {
+ curRow = j;
+ curCol = i;
+ foundFocus = true;
+ break;
+ }
+ }
}
switch (e->key()) {
- case Qt::Key_Left:
- if (curCol > 0) --curCol;
- else if (curRow > 0) { --curRow; curCol = grid->columnCount() - 1; }
- break;
- case Qt::Key_Right:
- if (curCol < grid->columnCount() - 1 && widgetAt[curRow][curCol + 1]) ++curCol;
- else if (curRow < grid->rowCount() - 1) { ++curRow; curCol = 0; }
- break;
- case Qt::Key_Up:
- if (curRow > 0) --curRow;
- else curCol = 0;
- break;
- case Qt::Key_Down:
- if (curRow < grid->rowCount() - 1) {
- QWidget *w = widgetAt[curRow + 1][curCol];
- if (w) {
- ++curRow;
- } else for (int i = 1; i < grid->columnCount(); ++i) {
- if (!widgetAt[curRow + 1][i]) {
- curCol = i - 1;
- ++curRow;
- break;
- }
- }
- }
- break;
- case Qt::Key_Space:
- case Qt::Key_Return:
- case Qt::Key_Enter: {
- QWidget *w = widgetAt[curRow][curCol];
- if (w && w->inherits("ColorPickerItem")) {
- ColorPickerItem *wi = reinterpret_cast(w);
- wi->setSelected(true);
+ case Qt::Key_Left:
+ if (curCol > 0) --curCol;
+ else if (curRow > 0) { --curRow; curCol = grid->columnCount() - 1; }
+ break;
+ case Qt::Key_Right:
+ if (curCol < grid->columnCount() - 1 && widgetAt[curRow][curCol + 1]) ++curCol;
+ else if (curRow < grid->rowCount() - 1) { ++curRow; curCol = 0; }
+ break;
+ case Qt::Key_Up:
+ if (curRow > 0) --curRow;
+ else curCol = 0;
+ break;
+ case Qt::Key_Down:
+ if (curRow < grid->rowCount() - 1) {
+ QWidget *w = widgetAt[curRow + 1][curCol];
+ if (w) {
+ ++curRow;
+ } else for (int i = 1; i < grid->columnCount(); ++i) {
+ if (!widgetAt[curRow + 1][i]) {
+ curCol = i - 1;
+ ++curRow;
+ break;
+ }
+ }
+ }
+ break;
+ case Qt::Key_Space:
+ case Qt::Key_Return:
+ case Qt::Key_Enter: {
+ QWidget *w = widgetAt[curRow][curCol];
+ if (w && w->inherits("ColorPickerItem")) {
+ ColorPickerItem *wi = reinterpret_cast(w);
+ wi->setSelected(true);
- QLayoutItem *layoutItem;
+ QLayoutItem *layoutItem;
int i = 0;
- while ((layoutItem = grid->itemAt(i)) != 0) {
- QWidget *w = layoutItem->widget();
- if (w && w->inherits("ColorPickerItem")) {
- ColorPickerItem *litem
- = reinterpret_cast(layoutItem->widget());
- if (litem != wi)
- litem->setSelected(false);
- }
- ++i;
- }
+ while ((layoutItem = grid->itemAt(i)) != 0) {
+ QWidget *w = layoutItem->widget();
+ if (w && w->inherits("ColorPickerItem")) {
+ ColorPickerItem *litem
+ = reinterpret_cast(layoutItem->widget());
+ if (litem != wi)
+ litem->setSelected(false);
+ }
+ ++i;
+ }
- lastSel = wi->color();
- emit selected(wi->color());
- hide();
- } else if (w && w->inherits("QPushButton")) {
- ColorPickerItem *wi = reinterpret_cast(w);
- wi->setSelected(true);
+ lastSel = wi->color();
+ Q_EMIT selected(wi->color());
+ hide();
+ } else if (w && w->inherits("QPushButton")) {
+ ColorPickerItem *wi = reinterpret_cast(w);
+ wi->setSelected(true);
- QLayoutItem *layoutItem;
+ QLayoutItem *layoutItem;
int i = 0;
- while ((layoutItem = grid->itemAt(i)) != 0) {
- QWidget *w = layoutItem->widget();
- if (w && w->inherits("ColorPickerItem")) {
- ColorPickerItem *litem
- = reinterpret_cast(layoutItem->widget());
- if (litem != wi)
- litem->setSelected(false);
- }
- ++i;
- }
+ while ((layoutItem = grid->itemAt(i)) != 0) {
+ QWidget *w = layoutItem->widget();
+ if (w && w->inherits("ColorPickerItem")) {
+ ColorPickerItem *litem
+ = reinterpret_cast(layoutItem->widget());
+ if (litem != wi)
+ litem->setSelected(false);
+ }
+ ++i;
+ }
- lastSel = wi->color();
- emit selected(wi->color());
- hide();
- }
- }
- break;
+ lastSel = wi->color();
+ Q_EMIT selected(wi->color());
+ hide();
+ }
+ }
+ break;
case Qt::Key_Escape:
hide();
break;
- default:
- e->ignore();
- break;
+ default:
+ e->ignore();
+ break;
}
widgetAt[curRow][curCol]->setFocus();
@@ -806,12 +806,12 @@ void ColorPickerPopup::keyPressEvent(QKeyEvent *e)
void ColorPickerPopup::hideEvent(QHideEvent *e)
{
if (eventLoop) {
- eventLoop->exit();
+ eventLoop->exit();
}
setFocus();
- emit hid();
+ Q_EMIT hid();
QFrame::hideEvent(e);
}
@@ -832,23 +832,23 @@ void ColorPickerPopup::showEvent(QShowEvent *)
{
bool foundSelected = false;
for (int i = 0; i < grid->columnCount(); ++i) {
- for (int j = 0; j < grid->rowCount(); ++j) {
- QWidget *w = widgetAt[j][i];
- if (w && w->inherits("ColorPickerItem")) {
- if (((ColorPickerItem *)w)->isSelected()) {
- w->setFocus();
- foundSelected = true;
- break;
- }
- }
- }
+ for (int j = 0; j < grid->rowCount(); ++j) {
+ QWidget *w = widgetAt[j][i];
+ if (w && w->inherits("ColorPickerItem")) {
+ if (((ColorPickerItem *)w)->isSelected()) {
+ w->setFocus();
+ foundSelected = true;
+ break;
+ }
+ }
+ }
}
if (!foundSelected) {
- if (items.count() == 0)
- setFocus();
- else
- widgetAt[0][0]->setFocus();
+ if (items.count() == 0)
+ setFocus();
+ else
+ widgetAt[0][0]->setFocus();
}
}
@@ -861,7 +861,7 @@ void ColorPickerPopup::regenerateGrid()
int columns = cols;
if (columns == -1)
- columns = (int) ceil(sqrt((float) items.count()));
+ columns = (int) ceil(sqrt((float) items.count()));
// When the number of columns grows, the number of rows will
// fall. There's no way to shrink a grid, so we create a new
@@ -884,8 +884,8 @@ void ColorPickerPopup::regenerateGrid()
}
if (moreButton) {
- grid->addWidget(moreButton, crow, ccol);
- widgetAt[crow][ccol] = moreButton;
+ grid->addWidget(moreButton, crow, ccol);
+ widgetAt[crow][ccol] = moreButton;
}
updateGeometry();
}
@@ -901,12 +901,12 @@ void ColorPickerPopup::getColorFromDialog()
//QRgb rgb = QColorDialog::getRgba(lastSel.rgba(), &ok, parentWidget());
QColor col = QColorDialog::getColor(lastSel,parentWidget(),0,QColorDialog::ShowAlphaChannel);
if (!col.isValid())
- return;
+ return;
//QColor col = QColor::fromRgba(rgb);
insertColor(col, tr("Custom"), -1);
lastSel = col;
- emit selected(col);
+ Q_EMIT selected(col);
}
void ColorPickerPopup::setLastSel(const QColor & col) { lastSel = col; }
@@ -916,7 +916,7 @@ void ColorPickerPopup::setLastSel(const QColor & col) { lastSel = col; }
whose name is set to \a text.
*/
ColorPickerItem::ColorPickerItem(const QColor &color, const QString &text,
- QWidget *parent)
+ QWidget *parent)
: QFrame(parent), c(color), t(text), sel(false)
{
setToolTip(t);
@@ -994,7 +994,7 @@ void ColorPickerItem::mouseMoveEvent(QMouseEvent *)
void ColorPickerItem::mouseReleaseEvent(QMouseEvent *)
{
sel = true;
- emit selected();
+ Q_EMIT selected();
}
/*!
@@ -1018,14 +1018,14 @@ void ColorPickerItem::paintEvent(QPaintEvent *)
p.setPen( QPen( Qt::gray, 0, Qt::SolidLine ) );
if (sel)
- p.drawRect(1, 1, w - 3, h - 3);
+ p.drawRect(1, 1, w - 3, h - 3);
p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) );
p.drawRect(3, 3, w - 7, h - 7);
p.fillRect(QRect(4, 4, w - 8, h - 8), QBrush(c));
if (hasFocus())
- p.drawRect(0, 0, w - 1, h - 1);
+ p.drawRect(0, 0, w - 1, h - 1);
}
/*!
@@ -1062,7 +1062,7 @@ void ColorPickerButton::mouseReleaseEvent(QMouseEvent *)
{
setFrameShadow(Raised);
repaint();
- emit clicked();
+ Q_EMIT clicked();
}
/*!
@@ -1071,15 +1071,15 @@ void ColorPickerButton::mouseReleaseEvent(QMouseEvent *)
void ColorPickerButton::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Up
- || e->key() == Qt::Key_Down
- || e->key() == Qt::Key_Left
- || e->key() == Qt::Key_Right) {
- qApp->sendEvent(parent(), e);
+ || e->key() == Qt::Key_Down
+ || e->key() == Qt::Key_Left
+ || e->key() == Qt::Key_Right) {
+ qApp->sendEvent(parent(), e);
} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) {
- setFrameShadow(Sunken);
- update();
+ setFrameShadow(Sunken);
+ update();
} else {
- QFrame::keyPressEvent(e);
+ QFrame::keyPressEvent(e);
}
}
@@ -1089,16 +1089,16 @@ void ColorPickerButton::keyPressEvent(QKeyEvent *e)
void ColorPickerButton::keyReleaseEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Up
- || e->key() == Qt::Key_Down
- || e->key() == Qt::Key_Left
- || e->key() == Qt::Key_Right) {
- qApp->sendEvent(parent(), e);
+ || e->key() == Qt::Key_Down
+ || e->key() == Qt::Key_Left
+ || e->key() == Qt::Key_Right) {
+ qApp->sendEvent(parent(), e);
} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) {
- setFrameShadow(Raised);
- repaint();
- emit clicked();
+ setFrameShadow(Raised);
+ repaint();
+ Q_EMIT clicked();
} else {
- QFrame::keyReleaseEvent(e);
+ QFrame::keyReleaseEvent(e);
}
}
@@ -1144,8 +1144,8 @@ void ColorPickerButton::paintEvent(QPaintEvent *e)
p.drawRect(r.center().x() + offset , r.center().y() + offset, 1, 1);
p.drawRect(r.center().x() + offset + 4, r.center().y() + offset, 1, 1);
if (hasFocus()) {
- p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) );
- p.drawRect(0, 0, width() - 1, height() - 1);
+ p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) );
+ p.drawRect(0, 0, width() - 1, height() - 1);
}
p.end();
diff --git a/src/Tools/plugins/widget/customwidgets.cpp b/src/Tools/plugins/widget/customwidgets.cpp
index d96b9fb9c..51f70a6df 100644
--- a/src/Tools/plugins/widget/customwidgets.cpp
+++ b/src/Tools/plugins/widget/customwidgets.cpp
@@ -182,7 +182,7 @@ void FileChooser::chooseFile()
if (!fn.isEmpty()) {
lineEdit->setText(fn);
- emit fileNameSelected(fn);
+ Q_EMIT fileNameSelected(fn);
}
}
@@ -595,9 +595,9 @@ QAbstractSpinBox::StepEnabled QuantitySpinBox::stepEnabled() const
}
return ret;
}
-
-void QuantitySpinBox::stepBy(int steps)
-{
+
+void QuantitySpinBox::stepBy(int steps)
+{
double step = StepSize * steps;
double val = Value + step;
if (val > Maximum)
@@ -607,7 +607,7 @@ void QuantitySpinBox::stepBy(int steps)
lineEdit()->setText(QString::fromUtf8("%L1 %2").arg(val).arg(UnitStr));
update();
-}
+}
void QuantitySpinBox::setUnitText(QString str)
{
@@ -792,9 +792,9 @@ public:
UIntSpinBox::UIntSpinBox (QWidget* parent)
: QSpinBox (parent)
{
- d = new UIntSpinBoxPrivate;
+ d = new UIntSpinBoxPrivate;
d->mValidator = new UnsignedValidator(this->minimum(), this->maximum(), this);
- connect(this, SIGNAL(valueChanged(int)),
+ connect(this, SIGNAL(valueChanged(int)),
this, SLOT(valueChange(int)));
setRange(0, 99);
setValue(0);
@@ -802,7 +802,7 @@ UIntSpinBox::UIntSpinBox (QWidget* parent)
}
UIntSpinBox::~UIntSpinBox()
-{
+{
delete d->mValidator;
delete d; d = 0;
}
@@ -1032,7 +1032,7 @@ void ColorButton::onChooseColor()
if ( c.isValid() )
{
setColor( c );
- emit changed();
+ Q_EMIT changed();
}
}
diff --git a/src/Tools/plugins/widget/wizard.cpp b/src/Tools/plugins/widget/wizard.cpp
index 7d788baf6..6aae3ac0a 100644
--- a/src/Tools/plugins/widget/wizard.cpp
+++ b/src/Tools/plugins/widget/wizard.cpp
@@ -153,7 +153,7 @@ void Wizard::setCurrentIndex(int index)
textLabel->setText(stackWidget->currentWidget()->windowTitle());
_backButton->setEnabled(index > 0);
_nextButton->setEnabled(index < count()-1);
- emit currentIndexChanged(index);
+ Q_EMIT currentIndexChanged(index);
}
}
@@ -171,7 +171,7 @@ void Wizard::setPageTitle(QString const &newTitle)
{
stackWidget->currentWidget()->setWindowTitle(newTitle);
textLabel->setText(newTitle);
- emit pageTitleChanged(newTitle);
+ Q_EMIT pageTitleChanged(newTitle);
}
WizardExtension::WizardExtension(Wizard *widget, QObject *parent)