Merge branch 'master' into logari81/PartDesign
This commit is contained in:
commit
9f452bd6ca
|
@ -1056,6 +1056,7 @@ src/Mod/Sandbox/App/Makefile
|
||||||
src/Mod/Sandbox/Gui/Makefile
|
src/Mod/Sandbox/Gui/Makefile
|
||||||
src/Mod/Surfaces/Makefile
|
src/Mod/Surfaces/Makefile
|
||||||
src/Mod/Ship/Makefile
|
src/Mod/Ship/Makefile
|
||||||
|
src/Mod/OpenSCAD/Makefile
|
||||||
src/Tools/Makefile
|
src/Tools/Makefile
|
||||||
src/Tools/_TEMPLATE_/Makefile
|
src/Tools/_TEMPLATE_/Makefile
|
||||||
src/Tools/_TEMPLATE_/App/Makefile
|
src/Tools/_TEMPLATE_/App/Makefile
|
||||||
|
|
|
@ -16,14 +16,11 @@ if(FREECAD_BUILD_TEMPLATE)
|
||||||
add_subdirectory(Tools/_TEMPLATE_)
|
add_subdirectory(Tools/_TEMPLATE_)
|
||||||
endif(FREECAD_BUILD_TEMPLATE)
|
endif(FREECAD_BUILD_TEMPLATE)
|
||||||
|
|
||||||
if(FREECAD_MAINTAINERS_BUILD)
|
add_subdirectory(Doc)
|
||||||
add_subdirectory(Doc)
|
|
||||||
endif(FREECAD_MAINTAINERS_BUILD)
|
|
||||||
|
|
||||||
if(FREECAD_MAINTAINERS_BUILD AND WIN32)
|
if(FREECAD_MAINTAINERS_BUILD AND WIN32)
|
||||||
#add_subdirectory(WindowsInstaller)
|
#add_subdirectory(WindowsInstaller)
|
||||||
endif(FREECAD_MAINTAINERS_BUILD AND WIN32)
|
endif(FREECAD_MAINTAINERS_BUILD AND WIN32)
|
||||||
|
|
||||||
INSTALL(FILES Doc/Start_Page.html Doc/freecad.qhc Doc/freecad.qch
|
INSTALL(FILES Doc/Start_Page.html Doc/freecad.qhc Doc/freecad.qch
|
||||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,7 +49,7 @@ if(DOXYGEN_FOUND)
|
||||||
|
|
||||||
STRING(REGEX REPLACE ";" " " DOXYGEN_EXCLUDE_LIST "${DOXYGEN_EXCLUDE_DIR}")
|
STRING(REGEX REPLACE ";" " " DOXYGEN_EXCLUDE_LIST "${DOXYGEN_EXCLUDE_DIR}")
|
||||||
|
|
||||||
SET(DOXYGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/Doc/SourceDocu)
|
SET(DOXYGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/doc/SourceDocu)
|
||||||
SET(DOXYGEN_IMAGE_PATH ${CMAKE_SOURCE_DIR}/src/Gui/Icons)
|
SET(DOXYGEN_IMAGE_PATH ${CMAKE_SOURCE_DIR}/src/Gui/Icons)
|
||||||
SET(DOXYGEN_LAYOUT_FILE ${CMAKE_SOURCE_DIR}/src/Doc/FreecadDoxygenLayout.xml)
|
SET(DOXYGEN_LAYOUT_FILE ${CMAKE_SOURCE_DIR}/src/Doc/FreecadDoxygenLayout.xml)
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ if(DOXYGEN_FOUND)
|
||||||
if( FREECAD_MAINTAINERS_BUILD )
|
if( FREECAD_MAINTAINERS_BUILD )
|
||||||
ADD_CUSTOM_TARGET(SourceDocu
|
ADD_CUSTOM_TARGET(SourceDocu
|
||||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/BuildDevDoc.cfg
|
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/BuildDevDoc.cfg
|
||||||
COMMAND ${QT_HELPCOMPILER_EXECUTABLE} "\"${CMAKE_BINARY_DIR}/Doc/SourceDocu/html/index.qhp\""
|
COMMAND ${QT_HELPCOMPILER_EXECUTABLE} "\"${CMAKE_BINARY_DIR}/doc/SourceDocu/html/index.qhp\""
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/Doc/SourceDocu/html/index.qch ${CMAKE_BINARY_DIR}/Doc/FreeCADSource.qch
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/doc/SourceDocu/html/index.qch ${CMAKE_BINARY_DIR}/doc/FreeCADSource.qch
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/BuildDevDoc.cfg
|
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/BuildDevDoc.cfg
|
||||||
)
|
)
|
||||||
|
@ -77,7 +77,7 @@ if(DOXYGEN_FOUND)
|
||||||
${CMAKE_SOURCE_DIR}/src/Tools/wiki2qhelp.py
|
${CMAKE_SOURCE_DIR}/src/Tools/wiki2qhelp.py
|
||||||
-c ${QT_HELPCOMPILER_EXECUTABLE}
|
-c ${QT_HELPCOMPILER_EXECUTABLE}
|
||||||
-g ${QT_COLLECTIOMGENERATOR_EXECUTABLE}
|
-g ${QT_COLLECTIOMGENERATOR_EXECUTABLE}
|
||||||
-o ${CMAKE_BINARY_DIR}/Doc
|
-o ${CMAKE_BINARY_DIR}/doc
|
||||||
)
|
)
|
||||||
|
|
||||||
else( FREECAD_MAINTAINERS_BUILD )
|
else( FREECAD_MAINTAINERS_BUILD )
|
||||||
|
|
|
@ -69,6 +69,12 @@ EXTRA_DIST = \
|
||||||
accessories-text-editor.svg \
|
accessories-text-editor.svg \
|
||||||
help-browser.svg \
|
help-browser.svg \
|
||||||
spaceball_button.svg \
|
spaceball_button.svg \
|
||||||
|
SpNav-PanLR.png \
|
||||||
|
SpNav-PanUD.png \
|
||||||
|
SpNav-Roll.png \
|
||||||
|
SpNav-Spin.png \
|
||||||
|
SpNav-Tilt.png \
|
||||||
|
SpNav-Zoom.png \
|
||||||
view-unselectable.svg \
|
view-unselectable.svg \
|
||||||
view-refresh.svg \
|
view-refresh.svg \
|
||||||
view-measurement.svg \
|
view-measurement.svg \
|
||||||
|
|
|
@ -13,6 +13,7 @@ BUILT_SOURCES=\
|
||||||
moc_DlgCommandsImp.cpp \
|
moc_DlgCommandsImp.cpp \
|
||||||
moc_DlgCustomizeImp.cpp \
|
moc_DlgCustomizeImp.cpp \
|
||||||
moc_DlgCustomizeSpaceball.cpp \
|
moc_DlgCustomizeSpaceball.cpp \
|
||||||
|
moc_DlgCustomizeSpNavSettings.cpp \
|
||||||
moc_DlgDisplayPropertiesImp.cpp \
|
moc_DlgDisplayPropertiesImp.cpp \
|
||||||
moc_DlgEditorImp.cpp \
|
moc_DlgEditorImp.cpp \
|
||||||
moc_DlgGeneralImp.cpp \
|
moc_DlgGeneralImp.cpp \
|
||||||
|
@ -84,6 +85,7 @@ BUILT_SOURCES=\
|
||||||
ui_DlgAuthorization.h \
|
ui_DlgAuthorization.h \
|
||||||
ui_DlgChooseIcon.h \
|
ui_DlgChooseIcon.h \
|
||||||
ui_DlgCommands.h \
|
ui_DlgCommands.h \
|
||||||
|
ui_DlgCustomizeSpNavSettings.h \
|
||||||
ui_DlgDisplayProperties.h \
|
ui_DlgDisplayProperties.h \
|
||||||
ui_DlgEditor.h \
|
ui_DlgEditor.h \
|
||||||
ui_DlgInputDialog.h \
|
ui_DlgInputDialog.h \
|
||||||
|
@ -133,6 +135,7 @@ libFreeCADGui_la_UI=\
|
||||||
DlgAuthorization.ui \
|
DlgAuthorization.ui \
|
||||||
DlgChooseIcon.ui \
|
DlgChooseIcon.ui \
|
||||||
DlgCommands.ui \
|
DlgCommands.ui \
|
||||||
|
DlgCustomizeSpNavSettings.ui \
|
||||||
DlgDisplayProperties.ui \
|
DlgDisplayProperties.ui \
|
||||||
DlgEditor.ui \
|
DlgEditor.ui \
|
||||||
DlgGeneral.ui \
|
DlgGeneral.ui \
|
||||||
|
@ -208,6 +211,8 @@ libFreeCADGui_la_SOURCES=\
|
||||||
DlgCustomizeImp.h \
|
DlgCustomizeImp.h \
|
||||||
DlgCustomizeSpaceball.cpp \
|
DlgCustomizeSpaceball.cpp \
|
||||||
DlgCustomizeSpaceball.h \
|
DlgCustomizeSpaceball.h \
|
||||||
|
DlgCustomizeSpNavSettings.cpp \
|
||||||
|
DlgCustomizeSpNavSettings.h \
|
||||||
DlgDisplayPropertiesImp.cpp \
|
DlgDisplayPropertiesImp.cpp \
|
||||||
DlgDisplayPropertiesImp.h \
|
DlgDisplayPropertiesImp.h \
|
||||||
DlgEditorImp.cpp \
|
DlgEditorImp.cpp \
|
||||||
|
|
|
@ -59,7 +59,29 @@ using namespace Gui;
|
||||||
namespace Gui
|
namespace Gui
|
||||||
{
|
{
|
||||||
|
|
||||||
static size_t promptLength = 4; //< length of prompt string: ">>> " or "... ", in either case 4 characters
|
static const QChar promptEnd( QLatin1Char(' ') ); //< char for detecting prompt end
|
||||||
|
|
||||||
|
inline int promptLength( const QString &lineStr )
|
||||||
|
{ return lineStr.indexOf( promptEnd ) + 1; }
|
||||||
|
|
||||||
|
inline QString stripPromptFrom( const QString &lineStr )
|
||||||
|
{ return lineStr.mid( promptLength(lineStr) ); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cursorBeyond checks if cursor is at a valid position to accept keyEvents.
|
||||||
|
* @param cursor - cursor to check
|
||||||
|
* @param limit - cursor that marks the begin of the input region
|
||||||
|
* @param shift - offset for shifting the limit for non-selection cursors [default: 0]
|
||||||
|
* @return true if a keyEvent is ok at cursor's position, false otherwise
|
||||||
|
*/
|
||||||
|
inline bool cursorBeyond( const QTextCursor &cursor, const QTextCursor &limit, int shift = 0 )
|
||||||
|
{
|
||||||
|
int pos = limit.position();
|
||||||
|
if (cursor.hasSelection())
|
||||||
|
return (cursor.selectionStart() >= pos && cursor.selectionEnd() >= pos);
|
||||||
|
else
|
||||||
|
return cursor.position() >= (pos + shift);
|
||||||
|
}
|
||||||
|
|
||||||
struct PythonConsoleP
|
struct PythonConsoleP
|
||||||
{
|
{
|
||||||
|
@ -341,7 +363,7 @@ void InteractiveInterpreter::clearBuffer()
|
||||||
* Constructs a PythonConsole which is a child of 'parent'.
|
* Constructs a PythonConsole which is a child of 'parent'.
|
||||||
*/
|
*/
|
||||||
PythonConsole::PythonConsole(QWidget *parent)
|
PythonConsole::PythonConsole(QWidget *parent)
|
||||||
: TextEdit(parent), WindowParameter( "Editor" )
|
: TextEdit(parent), WindowParameter( "Editor" ), _sourceDrain(NULL)
|
||||||
{
|
{
|
||||||
d = new PythonConsoleP();
|
d = new PythonConsoleP();
|
||||||
d->interactive = false;
|
d->interactive = false;
|
||||||
|
@ -445,7 +467,7 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
|
||||||
QTextCursor cursor = this->textCursor();
|
QTextCursor cursor = this->textCursor();
|
||||||
QTextCursor inputLineBegin = this->inputBegin();
|
QTextCursor inputLineBegin = this->inputBegin();
|
||||||
|
|
||||||
if (cursor < inputLineBegin)
|
if (!cursorBeyond( cursor, inputLineBegin ))
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The cursor is placed not on the input line (or within the prompt string)
|
* The cursor is placed not on the input line (or within the prompt string)
|
||||||
|
@ -460,6 +482,7 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
|
||||||
case Qt::Key_Return:
|
case Qt::Key_Return:
|
||||||
case Qt::Key_Enter:
|
case Qt::Key_Enter:
|
||||||
case Qt::Key_Escape:
|
case Qt::Key_Escape:
|
||||||
|
case Qt::Key_Backspace:
|
||||||
this->moveCursor( QTextCursor::End );
|
this->moveCursor( QTextCursor::End );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -488,19 +511,20 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
|
||||||
* - show call tips on period
|
* - show call tips on period
|
||||||
*/
|
*/
|
||||||
QTextBlock inputBlock = inputLineBegin.block(); //< get the last paragraph's text
|
QTextBlock inputBlock = inputLineBegin.block(); //< get the last paragraph's text
|
||||||
QString inputLine = inputBlock.text().mid(promptLength); //< and skip prompt characters
|
QString inputLine = inputBlock.text();
|
||||||
|
QString inputStrg = stripPromptFrom( inputLine );
|
||||||
|
|
||||||
switch (e->key())
|
switch (e->key())
|
||||||
{
|
{
|
||||||
case Qt::Key_Escape:
|
case Qt::Key_Escape:
|
||||||
{
|
{
|
||||||
// disable current input line - i.e. put it to history but don't execute it.
|
// disable current input string - i.e. put it to history but don't execute it.
|
||||||
if (!inputLine.isEmpty())
|
if (!inputStrg.isEmpty())
|
||||||
{
|
{
|
||||||
d->history.append( QLatin1String("# ") + inputLine ); //< put line to history ...
|
d->history.append( QLatin1String("# ") + inputStrg ); //< put commented string to history ...
|
||||||
inputLineBegin.insertText( QString::fromAscii("# ") ); //< but comment it on console
|
inputLineBegin.insertText( QString::fromAscii("# ") ); //< and comment it on console
|
||||||
setTextCursor( inputLineBegin );
|
setTextCursor( inputLineBegin );
|
||||||
printPrompt(d->interpreter->hasPendingInput() //< print adequate prompt
|
printPrompt(d->interpreter->hasPendingInput() //< print adequate prompt
|
||||||
? PythonConsole::Incomplete
|
? PythonConsole::Incomplete
|
||||||
: PythonConsole::Complete);
|
: PythonConsole::Complete);
|
||||||
}
|
}
|
||||||
|
@ -509,8 +533,8 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
|
||||||
case Qt::Key_Return:
|
case Qt::Key_Return:
|
||||||
case Qt::Key_Enter:
|
case Qt::Key_Enter:
|
||||||
{
|
{
|
||||||
runSource( inputLine ); //< commit input line
|
d->history.append( inputStrg ); //< put statement to history
|
||||||
d->history.append( inputLine ); //< put statement to history
|
runSource( inputStrg ); //< commit input string
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Qt::Key_Period:
|
case Qt::Key_Period:
|
||||||
|
@ -518,14 +542,14 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
|
||||||
// analyse context and show available call tips
|
// analyse context and show available call tips
|
||||||
int contextLength = cursor.position() - inputLineBegin.position();
|
int contextLength = cursor.position() - inputLineBegin.position();
|
||||||
TextEdit::keyPressEvent(e);
|
TextEdit::keyPressEvent(e);
|
||||||
d->callTipsList->showTips( inputLine.left( contextLength ) );
|
d->callTipsList->showTips( inputStrg.left( contextLength ) );
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Qt::Key_Home:
|
case Qt::Key_Home:
|
||||||
{
|
{
|
||||||
QTextCursor::MoveMode mode = (e->modifiers() & Qt::ShiftModifier)? QTextCursor::KeepAnchor
|
QTextCursor::MoveMode mode = (e->modifiers() & Qt::ShiftModifier)? QTextCursor::KeepAnchor
|
||||||
/* else */ : QTextCursor::MoveAnchor;
|
/* else */ : QTextCursor::MoveAnchor;
|
||||||
cursor.setPosition( inputBlock.position() + promptLength, mode );
|
cursor.setPosition( inputLineBegin.position(), mode );
|
||||||
setTextCursor( cursor );
|
setTextCursor( cursor );
|
||||||
ensureCursorVisible();
|
ensureCursorVisible();
|
||||||
} break;
|
} break;
|
||||||
|
@ -533,7 +557,7 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
|
||||||
case Qt::Key_Up:
|
case Qt::Key_Up:
|
||||||
{
|
{
|
||||||
// if possible, move back in history
|
// if possible, move back in history
|
||||||
if (d->history.prev( inputLine ))
|
if (d->history.prev( inputStrg ))
|
||||||
{ overrideCursor( d->history.value() ); }
|
{ overrideCursor( d->history.value() ); }
|
||||||
restartHistory = false;
|
restartHistory = false;
|
||||||
} break;
|
} break;
|
||||||
|
@ -561,7 +585,7 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
|
||||||
|
|
||||||
case Qt::Key_Backspace:
|
case Qt::Key_Backspace:
|
||||||
{
|
{
|
||||||
if (cursor > inputLineBegin)
|
if (cursorBeyond( cursor, inputLineBegin, +1 ))
|
||||||
{ TextEdit::keyPressEvent(e); }
|
{ TextEdit::keyPressEvent(e); }
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -576,7 +600,7 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
|
||||||
{ d->callTipsList->validateCursor(); }
|
{ d->callTipsList->validateCursor(); }
|
||||||
|
|
||||||
// disable history restart if input line changed
|
// disable history restart if input line changed
|
||||||
restartHistory &= (inputLine != inputBlock.text().mid(promptLength));
|
restartHistory &= (inputLine != inputBlock.text());
|
||||||
}
|
}
|
||||||
// any cursor move resets the history to its latest item.
|
// any cursor move resets the history to its latest item.
|
||||||
if (restartHistory)
|
if (restartHistory)
|
||||||
|
@ -623,37 +647,40 @@ void PythonConsole::printPrompt(PythonConsole::Prompt mode)
|
||||||
d->error = QString::null;
|
d->error = QString::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the prompt string
|
if (mode != PythonConsole::Special)
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
cursor.beginEditBlock();
|
|
||||||
cursor.movePosition(QTextCursor::End);
|
|
||||||
QTextBlock block = cursor.block();
|
|
||||||
|
|
||||||
// Python's print command appends a trailing '\n' to the system output.
|
|
||||||
// In this case, however, we should not add a new text block. We force
|
|
||||||
// the current block to be normal text (user state = 0) to be highlighted
|
|
||||||
// correctly and append the '>>> ' or '... ' to this block.
|
|
||||||
if (block.length() > 1)
|
|
||||||
cursor.insertBlock(cursor.blockFormat(), cursor.charFormat());
|
|
||||||
else
|
|
||||||
block.setUserState(0);
|
|
||||||
|
|
||||||
switch (mode)
|
|
||||||
{
|
{
|
||||||
case PythonConsole::Incomplete:
|
// Append the prompt string
|
||||||
cursor.insertText(QString::fromAscii("... "));
|
QTextCursor cursor = textCursor();
|
||||||
break;
|
cursor.beginEditBlock();
|
||||||
case PythonConsole::Complete:
|
cursor.movePosition(QTextCursor::End);
|
||||||
cursor.insertText(QString::fromAscii(">>> "));
|
QTextBlock block = cursor.block();
|
||||||
break;
|
|
||||||
default:
|
// Python's print command appends a trailing '\n' to the system output.
|
||||||
break;
|
// In this case, however, we should not add a new text block. We force
|
||||||
}
|
// the current block to be normal text (user state = 0) to be highlighted
|
||||||
cursor.endEditBlock();
|
// correctly and append the '>>> ' or '... ' to this block.
|
||||||
|
if (block.length() > 1)
|
||||||
|
cursor.insertBlock(cursor.blockFormat(), cursor.charFormat());
|
||||||
|
else
|
||||||
|
block.setUserState(0);
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case PythonConsole::Incomplete:
|
||||||
|
cursor.insertText(QString::fromAscii("... "));
|
||||||
|
break;
|
||||||
|
case PythonConsole::Complete:
|
||||||
|
cursor.insertText(QString::fromAscii(">>> "));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cursor.endEditBlock();
|
||||||
|
|
||||||
// move cursor to the end
|
// move cursor to the end
|
||||||
cursor.movePosition(QTextCursor::End);
|
cursor.movePosition(QTextCursor::End);
|
||||||
setTextCursor(cursor);
|
setTextCursor(cursor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -683,6 +710,17 @@ void PythonConsole::appendOutput(const QString& output, int state)
|
||||||
*/
|
*/
|
||||||
void PythonConsole::runSource(const QString& line)
|
void PythonConsole::runSource(const QString& line)
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Check if there's a "source drain", which want's to consume the source in another way then just executing it.
|
||||||
|
* If so, put the source to the drain and emit a signal to notify the consumer, whoever this may be.
|
||||||
|
*/
|
||||||
|
if (this->_sourceDrain)
|
||||||
|
{
|
||||||
|
*this->_sourceDrain = line;
|
||||||
|
Q_EMIT pendingSource();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool incomplete = false;
|
bool incomplete = false;
|
||||||
Base::PyGILStateLocker lock;
|
Base::PyGILStateLocker lock;
|
||||||
PyObject* default_stdout = PySys_GetObject("stdout");
|
PyObject* default_stdout = PySys_GetObject("stdout");
|
||||||
|
@ -692,8 +730,11 @@ void PythonConsole::runSource(const QString& line)
|
||||||
d->interactive = true;
|
d->interactive = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
d->history.markScratch(); //< mark current history position ...
|
||||||
// launch the command now
|
// launch the command now
|
||||||
incomplete = d->interpreter->push(line.toUtf8());
|
incomplete = d->interpreter->push(line.toUtf8());
|
||||||
|
if (!incomplete)
|
||||||
|
{ d->history.doScratch(); } //< ... and scratch history entries that might have been added by executing the line.
|
||||||
setFocus(); // if focus was lost
|
setFocus(); // if focus was lost
|
||||||
}
|
}
|
||||||
catch (const Base::SystemExitException&) {
|
catch (const Base::SystemExitException&) {
|
||||||
|
@ -923,7 +964,8 @@ QTextCursor PythonConsole::inputBegin( void ) const
|
||||||
QTextCursor inputLineBegin( this->textCursor() );
|
QTextCursor inputLineBegin( this->textCursor() );
|
||||||
inputLineBegin.movePosition( QTextCursor::End );
|
inputLineBegin.movePosition( QTextCursor::End );
|
||||||
inputLineBegin.movePosition( QTextCursor::StartOfLine );
|
inputLineBegin.movePosition( QTextCursor::StartOfLine );
|
||||||
inputLineBegin.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptLength );
|
// ... and move cursor right beyond the prompt.
|
||||||
|
inputLineBegin.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptLength( inputLineBegin.block().text() ) );
|
||||||
return inputLineBegin;
|
return inputLineBegin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,10 +990,7 @@ QMimeData * PythonConsole::createMimeDataFromSelection () const
|
||||||
int pos = b.position();
|
int pos = b.position();
|
||||||
if ( pos >= s && pos <= e ) {
|
if ( pos >= s && pos <= e ) {
|
||||||
if (b.userState() > -1 && b.userState() < pythonSyntax->maximumUserState()) {
|
if (b.userState() > -1 && b.userState() < pythonSyntax->maximumUserState()) {
|
||||||
QString line = b.text();
|
lines << stripPromptFrom( b.text() );
|
||||||
// and skip the prompt characters consisting of either ">>> " or "... "
|
|
||||||
line = line.mid(promptLength);
|
|
||||||
lines << line;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1020,8 +1059,7 @@ void PythonConsole::runSourceFromMimeData(const QString& source)
|
||||||
QString select = cursor.selectedText();
|
QString select = cursor.selectedText();
|
||||||
cursor.removeSelectedText();
|
cursor.removeSelectedText();
|
||||||
last = last + select;
|
last = last + select;
|
||||||
line = cursor.block().text();
|
line = stripPromptFrom( cursor.block().text() );
|
||||||
line = line.mid(promptLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// put statement to the history
|
// put statement to the history
|
||||||
|
@ -1073,12 +1111,10 @@ void PythonConsole::runSourceFromMimeData(const QString& source)
|
||||||
void PythonConsole::overrideCursor(const QString& txt)
|
void PythonConsole::overrideCursor(const QString& txt)
|
||||||
{
|
{
|
||||||
// Go to the last line and the fourth position, right after the prompt
|
// Go to the last line and the fourth position, right after the prompt
|
||||||
QTextCursor cursor = textCursor();
|
QTextCursor cursor = this->inputBegin();
|
||||||
QTextBlock block = cursor.block();
|
int blockLength = this->textCursor().block().text().length();
|
||||||
cursor.movePosition(QTextCursor::End);
|
|
||||||
cursor.movePosition(QTextCursor::StartOfLine);
|
cursor.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, blockLength ); //<< select text to override
|
||||||
cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, promptLength);
|
|
||||||
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, block.text().length());
|
|
||||||
cursor.removeSelectedText();
|
cursor.removeSelectedText();
|
||||||
cursor.insertText(txt);
|
cursor.insertText(txt);
|
||||||
// move cursor to the end
|
// move cursor to the end
|
||||||
|
@ -1090,12 +1126,7 @@ void PythonConsole::contextMenuEvent ( QContextMenuEvent * e )
|
||||||
{
|
{
|
||||||
QMenu menu(this);
|
QMenu menu(this);
|
||||||
QAction *a;
|
QAction *a;
|
||||||
// construct reference cursor at begin of input line ...
|
bool mayPasteHere = cursorBeyond( this->textCursor(), this->inputBegin() );
|
||||||
QTextCursor cursor = this->textCursor();
|
|
||||||
QTextCursor inputLineBegin = cursor;
|
|
||||||
inputLineBegin.movePosition(QTextCursor::End);
|
|
||||||
inputLineBegin.movePosition(QTextCursor::StartOfLine);
|
|
||||||
inputLineBegin.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, promptLength);
|
|
||||||
|
|
||||||
a = menu.addAction(tr("&Copy"), this, SLOT(copy()), Qt::CTRL+Qt::Key_C);
|
a = menu.addAction(tr("&Copy"), this, SLOT(copy()), Qt::CTRL+Qt::Key_C);
|
||||||
a->setEnabled(textCursor().hasSelection());
|
a->setEnabled(textCursor().hasSelection());
|
||||||
|
@ -1113,7 +1144,7 @@ void PythonConsole::contextMenuEvent ( QContextMenuEvent * e )
|
||||||
|
|
||||||
a = menu.addAction(tr("&Paste"), this, SLOT(paste()), Qt::CTRL+Qt::Key_V);
|
a = menu.addAction(tr("&Paste"), this, SLOT(paste()), Qt::CTRL+Qt::Key_V);
|
||||||
const QMimeData *md = QApplication::clipboard()->mimeData();
|
const QMimeData *md = QApplication::clipboard()->mimeData();
|
||||||
a->setEnabled(cursor >= inputLineBegin && md && canInsertFromMimeData(md));
|
a->setEnabled( mayPasteHere && md && canInsertFromMimeData(md));
|
||||||
|
|
||||||
a = menu.addAction(tr("Select All"), this, SLOT(selectAll()), Qt::CTRL+Qt::Key_A);
|
a = menu.addAction(tr("Select All"), this, SLOT(selectAll()), Qt::CTRL+Qt::Key_A);
|
||||||
a->setEnabled(!document()->isEmpty());
|
a->setEnabled(!document()->isEmpty());
|
||||||
|
@ -1195,6 +1226,20 @@ void PythonConsole::onCopyCommand()
|
||||||
d->type = PythonConsoleP::Normal;
|
d->type = PythonConsoleP::Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PythonConsole::readline( void )
|
||||||
|
{
|
||||||
|
QEventLoop loop;
|
||||||
|
QString inputBuffer;
|
||||||
|
|
||||||
|
printPrompt( PythonConsole::Special );
|
||||||
|
this->_sourceDrain = &inputBuffer; //< enable source drain ...
|
||||||
|
// ... and wait until we get notified about pendingSource
|
||||||
|
QObject::connect( this, SIGNAL(pendingSource()), &loop, SLOT(quit()) );
|
||||||
|
loop.exec();
|
||||||
|
this->_sourceDrain = NULL; //< disable source drain
|
||||||
|
return inputBuffer.append(QChar::fromAscii('\n')); //< pass a newline here, since the readline-caller may need it!
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
PythonConsoleHighlighter::PythonConsoleHighlighter(QObject* parent)
|
PythonConsoleHighlighter::PythonConsoleHighlighter(QObject* parent)
|
||||||
|
@ -1245,6 +1290,7 @@ void PythonConsoleHighlighter::colorChanged(const QString& type, const QColor& c
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
ConsoleHistory::ConsoleHistory()
|
ConsoleHistory::ConsoleHistory()
|
||||||
|
: _scratchBegin(0)
|
||||||
{
|
{
|
||||||
_it = _history.end();
|
_it = _history.end();
|
||||||
}
|
}
|
||||||
|
@ -1345,6 +1391,28 @@ void ConsoleHistory::restart( void )
|
||||||
_it = _history.end();
|
_it = _history.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* markScratch stores the current end index of the history list.
|
||||||
|
* Note: with simply remembering a start index, it does not work to nest scratch regions.
|
||||||
|
* However, just replace the index keeping by a stack - in case this is be a concern.
|
||||||
|
*/
|
||||||
|
void ConsoleHistory::markScratch( void )
|
||||||
|
{
|
||||||
|
_scratchBegin = _history.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* doScratch removes the tail of the history list, starting from the index marked lately.
|
||||||
|
*/
|
||||||
|
void ConsoleHistory::doScratch( void )
|
||||||
|
{
|
||||||
|
if (_scratchBegin < _history.length())
|
||||||
|
{
|
||||||
|
_history.erase( _history.begin() + _scratchBegin, _history.end() );
|
||||||
|
this->restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
|
|
||||||
/* TRANSLATOR Gui::PythonInputField */
|
/* TRANSLATOR Gui::PythonInputField */
|
||||||
|
|
|
@ -79,10 +79,13 @@ public:
|
||||||
void append(const QString &inputLine);
|
void append(const QString &inputLine);
|
||||||
const QStringList& values() const;
|
const QStringList& values() const;
|
||||||
void restart();
|
void restart();
|
||||||
|
void markScratch( void );
|
||||||
|
void doScratch( void );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList _history;
|
QStringList _history;
|
||||||
QStringList::ConstIterator _it;
|
QStringList::ConstIterator _it;
|
||||||
|
int _scratchBegin;
|
||||||
QString _prefix;
|
QString _prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -99,7 +102,8 @@ public:
|
||||||
enum Prompt {
|
enum Prompt {
|
||||||
Complete = 0,
|
Complete = 0,
|
||||||
Incomplete = 1,
|
Incomplete = 1,
|
||||||
Flush = 2
|
Flush = 2,
|
||||||
|
Special = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
PythonConsole(QWidget *parent = 0);
|
PythonConsole(QWidget *parent = 0);
|
||||||
|
@ -107,6 +111,7 @@ public:
|
||||||
|
|
||||||
void OnChange( Base::Subject<const char*> &rCaller,const char* rcReason );
|
void OnChange( Base::Subject<const char*> &rCaller,const char* rcReason );
|
||||||
void printStatement( const QString& cmd );
|
void printStatement( const QString& cmd );
|
||||||
|
QString readline( void );
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void onSaveHistoryAs();
|
void onSaveHistoryAs();
|
||||||
|
@ -126,7 +131,7 @@ protected:
|
||||||
void dragEnterEvent ( QDragEnterEvent * e );
|
void dragEnterEvent ( QDragEnterEvent * e );
|
||||||
void dragMoveEvent ( QDragMoveEvent * e );
|
void dragMoveEvent ( QDragMoveEvent * e );
|
||||||
void changeEvent ( QEvent * e );
|
void changeEvent ( QEvent * e );
|
||||||
void mouseReleaseEvent( QMouseEvent * e );
|
void mouseReleaseEvent( QMouseEvent * e );
|
||||||
|
|
||||||
void overrideCursor(const QString& txt);
|
void overrideCursor(const QString& txt);
|
||||||
|
|
||||||
|
@ -146,6 +151,9 @@ private:
|
||||||
void runSourceFromMimeData(const QString&);
|
void runSourceFromMimeData(const QString&);
|
||||||
void appendOutput(const QString&, int);
|
void appendOutput(const QString&, int);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void pendingSource( void );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PythonConsoleP* d;
|
struct PythonConsoleP* d;
|
||||||
|
|
||||||
|
@ -154,6 +162,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PythonConsoleHighlighter* pythonSyntax;
|
PythonConsoleHighlighter* pythonSyntax;
|
||||||
|
QString *_sourceDrain;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -317,16 +317,5 @@ Py::Object PythonStdin::repr()
|
||||||
|
|
||||||
Py::Object PythonStdin::readline(const Py::Tuple& args)
|
Py::Object PythonStdin::readline(const Py::Tuple& args)
|
||||||
{
|
{
|
||||||
if (console)
|
return Py::String( (const char *)console->readline().toAscii() );
|
||||||
console->onFlush();
|
|
||||||
timer->stop();
|
|
||||||
QEventLoop loop;
|
|
||||||
QObject::connect(editField, SIGNAL(textEntered()), &loop, SLOT(quit()));
|
|
||||||
editField->clear();
|
|
||||||
editField->show();
|
|
||||||
editField->setFocus();
|
|
||||||
loop.exec();
|
|
||||||
QString txt = editField->getText();
|
|
||||||
timer->start();
|
|
||||||
return Py::String((const char*)txt.toAscii());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#SUBDIRS=Part Mesh Points Raytracing Image Drawing Complete Draft Test TemplatePyMod
|
#SUBDIRS=Part Mesh Points Raytracing Image Drawing Complete Draft Test TemplatePyMod
|
||||||
SUBDIRS=Points Complete Draft Test TemplatePyMod Web Start Idf Arch Surfaces Ship OpenSCAD
|
SUBDIRS=Points Complete Draft Test TemplatePyMod Web Start Idf
|
||||||
|
|
||||||
#if HAVE_OPENCV
|
#if HAVE_OPENCV
|
||||||
SUBDIRS += Image
|
SUBDIRS += Image
|
||||||
|
@ -10,7 +10,7 @@ SUBDIRS += Mesh
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if HAVE_OPENCASCADE
|
if HAVE_OPENCASCADE
|
||||||
SUBDIRS += Part Import PartDesign Raytracing Drawing
|
SUBDIRS += Part Import PartDesign Raytracing Drawing Arch Surfaces Ship OpenSCAD
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_EIGEN3
|
if HAVE_EIGEN3
|
||||||
|
|
|
@ -52,11 +52,9 @@ Chamfer::Chamfer()
|
||||||
|
|
||||||
short Chamfer::mustExecute() const
|
short Chamfer::mustExecute() const
|
||||||
{
|
{
|
||||||
if (Placement.isTouched() || Base.isTouched() || Size.isTouched())
|
if (Placement.isTouched() || Size.isTouched())
|
||||||
return 1;
|
return 1;
|
||||||
if (Base.getValue() && Base.getValue()->isTouched())
|
return DressUp::mustExecute();
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
App::DocumentObjectExecReturn *Chamfer::execute(void)
|
App::DocumentObjectExecReturn *Chamfer::execute(void)
|
||||||
|
|
|
@ -41,6 +41,14 @@ DressUp::DressUp()
|
||||||
ADD_PROPERTY(Base,(0));
|
ADD_PROPERTY(Base,(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
short DressUp::mustExecute() const
|
||||||
|
{
|
||||||
|
if (Base.getValue() && Base.getValue()->isTouched())
|
||||||
|
return 1;
|
||||||
|
return PartDesign::Feature::mustExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DressUp::positionByBase(void)
|
void DressUp::positionByBase(void)
|
||||||
{
|
{
|
||||||
Part::Feature *base = static_cast<Part::Feature*>(Base.getValue());
|
Part::Feature *base = static_cast<Part::Feature*>(Base.getValue());
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
|
|
||||||
App::PropertyLinkSub Base;
|
App::PropertyLinkSub Base;
|
||||||
|
|
||||||
|
short mustExecute() const;
|
||||||
/// updates the Placement property from the Placement of Base
|
/// updates the Placement property from the Placement of Base
|
||||||
void positionByBase(void);
|
void positionByBase(void);
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ short Face::mustExecute() const
|
||||||
{
|
{
|
||||||
if (Sources.isTouched())
|
if (Sources.isTouched())
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return Part::Part2DObject::mustExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
App::DocumentObjectExecReturn *Face::execute(void)
|
App::DocumentObjectExecReturn *Face::execute(void)
|
||||||
|
|
|
@ -49,11 +49,9 @@ Fillet::Fillet()
|
||||||
|
|
||||||
short Fillet::mustExecute() const
|
short Fillet::mustExecute() const
|
||||||
{
|
{
|
||||||
if (Placement.isTouched() || Base.isTouched() || Radius.isTouched())
|
if (Placement.isTouched() || Radius.isTouched())
|
||||||
return 1;
|
return 1;
|
||||||
if (Base.getValue() && Base.getValue()->isTouched())
|
return DressUp::mustExecute();
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
App::DocumentObjectExecReturn *Fillet::execute(void)
|
App::DocumentObjectExecReturn *Fillet::execute(void)
|
||||||
|
|
|
@ -48,7 +48,7 @@ using namespace PartDesign;
|
||||||
namespace PartDesign {
|
namespace PartDesign {
|
||||||
|
|
||||||
|
|
||||||
PROPERTY_SOURCE(PartDesign::Groove, PartDesign::SketchBased)
|
PROPERTY_SOURCE(PartDesign::Groove, PartDesign::Subtractive)
|
||||||
|
|
||||||
Groove::Groove()
|
Groove::Groove()
|
||||||
{
|
{
|
||||||
|
@ -63,7 +63,6 @@ Groove::Groove()
|
||||||
short Groove::mustExecute() const
|
short Groove::mustExecute() const
|
||||||
{
|
{
|
||||||
if (Placement.isTouched() ||
|
if (Placement.isTouched() ||
|
||||||
Sketch.isTouched() ||
|
|
||||||
ReferenceAxis.isTouched() ||
|
ReferenceAxis.isTouched() ||
|
||||||
Axis.isTouched() ||
|
Axis.isTouched() ||
|
||||||
Base.isTouched() ||
|
Base.isTouched() ||
|
||||||
|
@ -71,7 +70,7 @@ short Groove::mustExecute() const
|
||||||
Midplane.isTouched() ||
|
Midplane.isTouched() ||
|
||||||
Reversed.isTouched())
|
Reversed.isTouched())
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return Subtractive::mustExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
App::DocumentObjectExecReturn *Groove::execute(void)
|
App::DocumentObjectExecReturn *Groove::execute(void)
|
||||||
|
|
|
@ -25,12 +25,12 @@
|
||||||
#define PARTDESIGN_Groove_H
|
#define PARTDESIGN_Groove_H
|
||||||
|
|
||||||
#include <App/PropertyUnits.h>
|
#include <App/PropertyUnits.h>
|
||||||
#include "FeatureSketchBased.h"
|
#include "FeatureSubtractive.h"
|
||||||
|
|
||||||
namespace PartDesign
|
namespace PartDesign
|
||||||
{
|
{
|
||||||
|
|
||||||
class PartDesignExport Groove : public SketchBased
|
class PartDesignExport Groove : public Subtractive
|
||||||
{
|
{
|
||||||
PROPERTY_HEADER(PartDesign::Groove);
|
PROPERTY_HEADER(PartDesign::Groove);
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ const char* Hole::TypeEnums[] = {"Dimension","UpToLast","UpToFirst",NULL};
|
||||||
const char* Hole::HoleTypeEnums[]= {"Simple","Counterbore","Countersunk",NULL};
|
const char* Hole::HoleTypeEnums[]= {"Simple","Counterbore","Countersunk",NULL};
|
||||||
const char* Hole::ThreadEnums[] = {"None","Metric","MetricFine",NULL};
|
const char* Hole::ThreadEnums[] = {"None","Metric","MetricFine",NULL};
|
||||||
|
|
||||||
PROPERTY_SOURCE(PartDesign::Hole, PartDesign::SketchBased)
|
PROPERTY_SOURCE(PartDesign::Hole, PartDesign::Subtractive)
|
||||||
|
|
||||||
Hole::Hole()
|
Hole::Hole()
|
||||||
{
|
{
|
||||||
|
@ -72,7 +72,7 @@ Hole::Hole()
|
||||||
// if (Sketch.isTouched() ||
|
// if (Sketch.isTouched() ||
|
||||||
// Length.isTouched())
|
// Length.isTouched())
|
||||||
// return 1;
|
// return 1;
|
||||||
// return 0;
|
// return Subtractive::mustExecute();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
App::DocumentObjectExecReturn *Hole::execute(void)
|
App::DocumentObjectExecReturn *Hole::execute(void)
|
||||||
|
@ -134,6 +134,8 @@ App::DocumentObjectExecReturn *Hole::execute(void)
|
||||||
//if (PrismMaker.IsDone()) {
|
//if (PrismMaker.IsDone()) {
|
||||||
// // if the sketch has a support fuse them to get one result object (PAD!)
|
// // if the sketch has a support fuse them to get one result object (PAD!)
|
||||||
// if (SupportObject) {
|
// if (SupportObject) {
|
||||||
|
// // Set the subtractive shape property for later usage in e.g. pattern
|
||||||
|
// this->SubShape.setValue(PrismMaker.Shape());
|
||||||
// const TopoDS_Shape& support = SupportObject->Shape.getValue();
|
// const TopoDS_Shape& support = SupportObject->Shape.getValue();
|
||||||
// if (support.IsNull())
|
// if (support.IsNull())
|
||||||
// return new App::DocumentObjectExecReturn("Support shape is invalid");
|
// return new App::DocumentObjectExecReturn("Support shape is invalid");
|
||||||
|
|
|
@ -68,14 +68,13 @@ Pad::Pad()
|
||||||
short Pad::mustExecute() const
|
short Pad::mustExecute() const
|
||||||
{
|
{
|
||||||
if (Placement.isTouched() ||
|
if (Placement.isTouched() ||
|
||||||
Sketch.isTouched() ||
|
|
||||||
Length.isTouched() ||
|
Length.isTouched() ||
|
||||||
Midplane.isTouched() ||
|
Midplane.isTouched() ||
|
||||||
Reversed.isTouched() ||
|
Reversed.isTouched() ||
|
||||||
Length2.isTouched() ||
|
Length2.isTouched() ||
|
||||||
FaceName.isTouched())
|
FaceName.isTouched())
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return Additive::mustExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
App::DocumentObjectExecReturn *Pad::execute(void)
|
App::DocumentObjectExecReturn *Pad::execute(void)
|
||||||
|
|
|
@ -56,7 +56,7 @@ using namespace PartDesign;
|
||||||
|
|
||||||
const char* Pocket::TypeEnums[]= {"Length","UpToLast","UpToFirst","ThroughAll","UpToFace",NULL};
|
const char* Pocket::TypeEnums[]= {"Length","UpToLast","UpToFirst","ThroughAll","UpToFace",NULL};
|
||||||
|
|
||||||
PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::SketchBased)
|
PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::Subtractive)
|
||||||
|
|
||||||
Pocket::Pocket()
|
Pocket::Pocket()
|
||||||
{
|
{
|
||||||
|
@ -69,11 +69,10 @@ Pocket::Pocket()
|
||||||
short Pocket::mustExecute() const
|
short Pocket::mustExecute() const
|
||||||
{
|
{
|
||||||
if (Placement.isTouched() ||
|
if (Placement.isTouched() ||
|
||||||
Sketch.isTouched() ||
|
|
||||||
Length.isTouched() ||
|
Length.isTouched() ||
|
||||||
FaceName.isTouched())
|
FaceName.isTouched())
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return Subtractive::mustExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
App::DocumentObjectExecReturn *Pocket::execute(void)
|
App::DocumentObjectExecReturn *Pocket::execute(void)
|
||||||
|
@ -255,8 +254,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
|
||||||
return new App::DocumentObjectExecReturn("Internal error: Unknown type for Pocket feature");
|
return new App::DocumentObjectExecReturn("Internal error: Unknown type for Pocket feature");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Set the subtractive shape property for later usage in e.g. pattern
|
this->SubShape.setValue(prism);
|
||||||
//this->SubShape.setValue(prism); // This crashes with "Illegal storage access". Why?
|
|
||||||
|
|
||||||
// Cut out the pocket
|
// Cut out the pocket
|
||||||
BRepAlgoAPI_Cut mkCut(support.Moved(invObjLoc), prism);
|
BRepAlgoAPI_Cut mkCut(support.Moved(invObjLoc), prism);
|
||||||
|
|
|
@ -48,7 +48,7 @@ using namespace PartDesign;
|
||||||
namespace PartDesign {
|
namespace PartDesign {
|
||||||
|
|
||||||
|
|
||||||
PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::SketchBased)
|
PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::Additive)
|
||||||
|
|
||||||
Revolution::Revolution()
|
Revolution::Revolution()
|
||||||
{
|
{
|
||||||
|
@ -63,7 +63,6 @@ Revolution::Revolution()
|
||||||
short Revolution::mustExecute() const
|
short Revolution::mustExecute() const
|
||||||
{
|
{
|
||||||
if (Placement.isTouched() ||
|
if (Placement.isTouched() ||
|
||||||
Sketch.isTouched() ||
|
|
||||||
ReferenceAxis.isTouched() ||
|
ReferenceAxis.isTouched() ||
|
||||||
Axis.isTouched() ||
|
Axis.isTouched() ||
|
||||||
Base.isTouched() ||
|
Base.isTouched() ||
|
||||||
|
@ -71,7 +70,7 @@ short Revolution::mustExecute() const
|
||||||
Midplane.isTouched() ||
|
Midplane.isTouched() ||
|
||||||
Reversed.isTouched())
|
Reversed.isTouched())
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return Additive::mustExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
App::DocumentObjectExecReturn *Revolution::execute(void)
|
App::DocumentObjectExecReturn *Revolution::execute(void)
|
||||||
|
@ -183,6 +182,8 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
|
||||||
if (SupportObject) {
|
if (SupportObject) {
|
||||||
const TopoDS_Shape& support = SupportObject->Shape.getValue();
|
const TopoDS_Shape& support = SupportObject->Shape.getValue();
|
||||||
if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) {
|
if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) {
|
||||||
|
// set the additive shape property for later usage in e.g. pattern
|
||||||
|
this->AddShape.setValue(result);
|
||||||
// Let's call algorithm computing a fuse operation:
|
// Let's call algorithm computing a fuse operation:
|
||||||
BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result);
|
BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result);
|
||||||
// Let's check if the fusion has been successful
|
// Let's check if the fusion has been successful
|
||||||
|
|
|
@ -25,12 +25,12 @@
|
||||||
#define PARTDESIGN_Revolution_H
|
#define PARTDESIGN_Revolution_H
|
||||||
|
|
||||||
#include <App/PropertyUnits.h>
|
#include <App/PropertyUnits.h>
|
||||||
#include "FeatureSketchBased.h"
|
#include "FeatureAdditive.h"
|
||||||
|
|
||||||
namespace PartDesign
|
namespace PartDesign
|
||||||
{
|
{
|
||||||
|
|
||||||
class PartDesignExport Revolution : public SketchBased
|
class PartDesignExport Revolution : public Additive
|
||||||
{
|
{
|
||||||
PROPERTY_HEADER(PartDesign::Revolution);
|
PROPERTY_HEADER(PartDesign::Revolution);
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,13 @@ SketchBased::SketchBased()
|
||||||
ADD_PROPERTY(Sketch,(0));
|
ADD_PROPERTY(Sketch,(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
short SketchBased::mustExecute() const
|
||||||
|
{
|
||||||
|
if (Sketch.isTouched())
|
||||||
|
return 1;
|
||||||
|
return 0; // PartDesign::Feature::mustExecute();
|
||||||
|
}
|
||||||
|
|
||||||
void SketchBased::positionBySketch(void)
|
void SketchBased::positionBySketch(void)
|
||||||
{
|
{
|
||||||
Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Sketch.getValue());
|
Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Sketch.getValue());
|
||||||
|
|
|
@ -42,6 +42,8 @@ public:
|
||||||
|
|
||||||
App::PropertyLink Sketch;
|
App::PropertyLink Sketch;
|
||||||
|
|
||||||
|
short mustExecute() const;
|
||||||
|
|
||||||
/** calculates and updates the Placement property based on the Sketch
|
/** calculates and updates the Placement property based on the Sketch
|
||||||
* or its support if it has one
|
* or its support if it has one
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
import os
|
import os
|
||||||
# FreeCAD modules
|
# FreeCAD modules
|
||||||
import FreeCAD,FreeCADGui
|
import FreeCAD,FreeCADGui
|
||||||
from FreeCAD import Base, Image, ImageGui
|
from FreeCAD import Base
|
||||||
|
import Image, ImageGui
|
||||||
# FreeCADShip modules
|
# FreeCADShip modules
|
||||||
from shipUtils import Paths, Translator
|
from shipUtils import Paths, Translator
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,7 @@ import math
|
||||||
# FreeCAD modules
|
# FreeCAD modules
|
||||||
import FreeCAD,FreeCADGui
|
import FreeCAD,FreeCADGui
|
||||||
from FreeCAD import Base, Vector
|
from FreeCAD import Base, Vector
|
||||||
from FreeCAD import Image, ImageGui
|
import Part, Image, ImageGui
|
||||||
import Part
|
|
||||||
# FreeCADShip modules
|
# FreeCADShip modules
|
||||||
from shipUtils import Paths, Translator
|
from shipUtils import Paths, Translator
|
||||||
import Tools
|
import Tools
|
||||||
|
|
|
@ -1,229 +1,229 @@
|
||||||
#***************************************************************************
|
#***************************************************************************
|
||||||
#* *
|
#* *
|
||||||
#* Copyright (c) 2011, 2012 *
|
#* Copyright (c) 2011, 2012 *
|
||||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||||
#* *
|
#* *
|
||||||
#* This program is free software; you can redistribute it and/or modify *
|
#* This program is free software; you can redistribute it and/or modify *
|
||||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||||
#* as published by the Free Software Foundation; either version 2 of *
|
#* as published by the Free Software Foundation; either version 2 of *
|
||||||
#* the License, or (at your option) any later version. *
|
#* the License, or (at your option) any later version. *
|
||||||
#* for detail see the LICENCE text file. *
|
#* for detail see the LICENCE text file. *
|
||||||
#* *
|
#* *
|
||||||
#* This program is distributed in the hope that it will be useful, *
|
#* This program is distributed in the hope that it will be useful, *
|
||||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
#* GNU Library General Public License for more details. *
|
#* GNU Library General Public License for more details. *
|
||||||
#* *
|
#* *
|
||||||
#* You should have received a copy of the GNU Library General Public *
|
#* You should have received a copy of the GNU Library General Public *
|
||||||
#* License along with this program; if not, write to the Free Software *
|
#* License along with this program; if not, write to the Free Software *
|
||||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
#* USA *
|
#* USA *
|
||||||
#* *
|
#* *
|
||||||
#***************************************************************************
|
#***************************************************************************
|
||||||
|
|
||||||
import math
|
import math
|
||||||
# FreeCAD modules
|
# FreeCAD modules
|
||||||
import FreeCAD as App
|
import FreeCAD as App
|
||||||
import FreeCADGui as Gui
|
import FreeCADGui as Gui
|
||||||
# Qt library
|
# Qt library
|
||||||
from PyQt4 import QtGui,QtCore
|
from PyQt4 import QtGui,QtCore
|
||||||
# Module
|
# Module
|
||||||
import Plot
|
import Plot
|
||||||
import Instance
|
import Instance
|
||||||
from shipUtils import Paths, Translator
|
from shipUtils import Paths, Translator
|
||||||
import Tools
|
import Tools
|
||||||
|
|
||||||
class TaskPanel:
|
class TaskPanel:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.ui = Paths.modulePath() + "/shipHydrostatics/TaskPanel.ui"
|
self.ui = Paths.modulePath() + "/shipHydrostatics/TaskPanel.ui"
|
||||||
self.ship = None
|
self.ship = None
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
if not self.ship:
|
if not self.ship:
|
||||||
return False
|
return False
|
||||||
self.save()
|
self.save()
|
||||||
draft = self.form.minDraft.value()
|
draft = self.form.minDraft.value()
|
||||||
drafts = [draft]
|
drafts = [draft]
|
||||||
dDraft = (self.form.maxDraft.value() - self.form.minDraft.value())/(self.form.nDraft.value()-1)
|
dDraft = (self.form.maxDraft.value() - self.form.minDraft.value())/(self.form.nDraft.value()-1)
|
||||||
for i in range(1,self.form.nDraft.value()):
|
for i in range(1,self.form.nDraft.value()):
|
||||||
draft = draft + dDraft
|
draft = draft + dDraft
|
||||||
drafts.append(draft)
|
drafts.append(draft)
|
||||||
Plot.Plot(self.ship, self.form.trim.value(), drafts)
|
Plot.Plot(self.ship, self.form.trim.value(), drafts)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def clicked(self, index):
|
def clicked(self, index):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def needsFullSpace(self):
|
def needsFullSpace(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isAllowedAlterSelection(self):
|
def isAllowedAlterSelection(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def isAllowedAlterView(self):
|
def isAllowedAlterView(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isAllowedAlterDocument(self):
|
def isAllowedAlterDocument(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def helpRequested(self):
|
def helpRequested(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
mw = self.getMainWindow()
|
mw = self.getMainWindow()
|
||||||
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
||||||
form.trim = form.findChild(QtGui.QDoubleSpinBox, "Trim")
|
form.trim = form.findChild(QtGui.QDoubleSpinBox, "Trim")
|
||||||
form.minDraft = form.findChild(QtGui.QDoubleSpinBox, "MinDraft")
|
form.minDraft = form.findChild(QtGui.QDoubleSpinBox, "MinDraft")
|
||||||
form.maxDraft = form.findChild(QtGui.QDoubleSpinBox, "MaxDraft")
|
form.maxDraft = form.findChild(QtGui.QDoubleSpinBox, "MaxDraft")
|
||||||
form.nDraft = form.findChild(QtGui.QSpinBox, "NDraft")
|
form.nDraft = form.findChild(QtGui.QSpinBox, "NDraft")
|
||||||
self.form = form
|
self.form = form
|
||||||
# Initial values
|
# Initial values
|
||||||
if self.initValues():
|
if self.initValues():
|
||||||
return True
|
return True
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
# Connect Signals and Slots
|
# Connect Signals and Slots
|
||||||
QtCore.QObject.connect(form.trim, QtCore.SIGNAL("valueChanged(double)"), self.onData)
|
QtCore.QObject.connect(form.trim, QtCore.SIGNAL("valueChanged(double)"), self.onData)
|
||||||
QtCore.QObject.connect(form.minDraft, QtCore.SIGNAL("valueChanged(double)"), self.onData)
|
QtCore.QObject.connect(form.minDraft, QtCore.SIGNAL("valueChanged(double)"), self.onData)
|
||||||
QtCore.QObject.connect(form.maxDraft, QtCore.SIGNAL("valueChanged(double)"), self.onData)
|
QtCore.QObject.connect(form.maxDraft, QtCore.SIGNAL("valueChanged(double)"), self.onData)
|
||||||
|
|
||||||
def getMainWindow(self):
|
def getMainWindow(self):
|
||||||
"returns the main window"
|
"returns the main window"
|
||||||
# using QtGui.qApp.activeWindow() isn't very reliable because if another
|
# using QtGui.qApp.activeWindow() isn't very reliable because if another
|
||||||
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
|
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
|
||||||
# returned
|
# returned
|
||||||
toplevel = QtGui.qApp.topLevelWidgets()
|
toplevel = QtGui.qApp.topLevelWidgets()
|
||||||
for i in toplevel:
|
for i in toplevel:
|
||||||
if i.metaObject().className() == "Gui::MainWindow":
|
if i.metaObject().className() == "Gui::MainWindow":
|
||||||
return i
|
return i
|
||||||
raise Exception("No main window found")
|
raise Exception("No main window found")
|
||||||
|
|
||||||
def initValues(self):
|
def initValues(self):
|
||||||
""" Set initial values for fields
|
""" Set initial values for fields
|
||||||
"""
|
"""
|
||||||
# Get objects
|
# Get objects
|
||||||
selObjs = Gui.Selection.getSelection()
|
selObjs = Gui.Selection.getSelection()
|
||||||
if not selObjs:
|
if not selObjs:
|
||||||
msg = Translator.translate("Ship instance must be selected (no object selected)\n")
|
msg = Translator.translate("Ship instance must be selected (no object selected)\n")
|
||||||
App.Console.PrintError(msg)
|
App.Console.PrintError(msg)
|
||||||
return True
|
return True
|
||||||
for i in range(0,len(selObjs)):
|
for i in range(0,len(selObjs)):
|
||||||
obj = selObjs[i]
|
obj = selObjs[i]
|
||||||
# Test if is a ship instance
|
# Test if is a ship instance
|
||||||
props = obj.PropertiesList
|
props = obj.PropertiesList
|
||||||
try:
|
try:
|
||||||
props.index("IsShip")
|
props.index("IsShip")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
if obj.IsShip:
|
if obj.IsShip:
|
||||||
# Test if another ship already selected
|
# Test if another ship already selected
|
||||||
if self.ship:
|
if self.ship:
|
||||||
msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n")
|
msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n")
|
||||||
App.Console.PrintWarning(msg)
|
App.Console.PrintWarning(msg)
|
||||||
break
|
break
|
||||||
self.ship = obj
|
self.ship = obj
|
||||||
# Test if any valid ship was selected
|
# Test if any valid ship was selected
|
||||||
if not self.ship:
|
if not self.ship:
|
||||||
msg = Translator.translate("Ship instance must be selected (no valid ship found at selected objects)\n")
|
msg = Translator.translate("Ship instance must be selected (no valid ship found at selected objects)\n")
|
||||||
App.Console.PrintError(msg)
|
App.Console.PrintError(msg)
|
||||||
return True
|
return True
|
||||||
# Get bounds
|
# Get bounds
|
||||||
bbox = self.ship.Shape.BoundBox
|
bbox = self.ship.Shape.BoundBox
|
||||||
# Set trim
|
# Set trim
|
||||||
flag = True
|
flag = True
|
||||||
try:
|
try:
|
||||||
props.index("HydrostaticsTrim")
|
props.index("HydrostaticsTrim")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
flag = False
|
flag = False
|
||||||
if flag:
|
if flag:
|
||||||
self.form.trim.setValue(self.ship.HydrostaticsTrim)
|
self.form.trim.setValue(self.ship.HydrostaticsTrim)
|
||||||
# Set drafts
|
# Set drafts
|
||||||
self.form.maxDraft.setValue(1.1*self.ship.Draft)
|
self.form.maxDraft.setValue(1.1*self.ship.Draft)
|
||||||
self.form.minDraft.setValue(0.9*self.ship.Draft)
|
self.form.minDraft.setValue(0.9*self.ship.Draft)
|
||||||
# Try to use saved values
|
# Try to use saved values
|
||||||
props = self.ship.PropertiesList
|
props = self.ship.PropertiesList
|
||||||
flag = True
|
flag = True
|
||||||
try:
|
try:
|
||||||
props.index("HydrostaticsMinDraft")
|
props.index("HydrostaticsMinDraft")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
flag = False
|
flag = False
|
||||||
if flag:
|
if flag:
|
||||||
self.form.minDraft.setValue(self.ship.HydrostaticsMinDraft)
|
self.form.minDraft.setValue(self.ship.HydrostaticsMinDraft)
|
||||||
flag = True
|
flag = True
|
||||||
try:
|
try:
|
||||||
props.index("HydrostaticsMaxDraft")
|
props.index("HydrostaticsMaxDraft")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
flag = False
|
flag = False
|
||||||
if flag:
|
if flag:
|
||||||
self.form.maxDraft.setValue(self.ship.HydrostaticsMaxDraft)
|
self.form.maxDraft.setValue(self.ship.HydrostaticsMaxDraft)
|
||||||
self.form.maxDraft.setMaximum(bbox.ZMax)
|
self.form.maxDraft.setMaximum(bbox.ZMax)
|
||||||
self.form.minDraft.setMinimum(bbox.ZMin)
|
self.form.minDraft.setMinimum(bbox.ZMin)
|
||||||
self.form.maxDraft.setMinimum(self.form.minDraft.value())
|
self.form.maxDraft.setMinimum(self.form.minDraft.value())
|
||||||
self.form.minDraft.setMaximum(self.form.maxDraft.value())
|
self.form.minDraft.setMaximum(self.form.maxDraft.value())
|
||||||
flag = True
|
flag = True
|
||||||
try:
|
try:
|
||||||
props.index("HydrostaticsNDraft")
|
props.index("HydrostaticsNDraft")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
flag = False
|
flag = False
|
||||||
if flag:
|
if flag:
|
||||||
self.form.nDraft.setValue(self.ship.HydrostaticsNDraft)
|
self.form.nDraft.setValue(self.ship.HydrostaticsNDraft)
|
||||||
# Update GUI
|
# Update GUI
|
||||||
msg = Translator.translate("Ready to work\n")
|
msg = Translator.translate("Ready to work\n")
|
||||||
App.Console.PrintMessage(msg)
|
App.Console.PrintMessage(msg)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
""" Set user interface locale strings.
|
""" Set user interface locale strings.
|
||||||
"""
|
"""
|
||||||
self.form.setWindowTitle(Translator.translate("Plot hydrostatics"))
|
self.form.setWindowTitle(Translator.translate("Plot hydrostatics"))
|
||||||
self.form.findChild(QtGui.QLabel, "TrimLabel").setText(Translator.translate("Trim"))
|
self.form.findChild(QtGui.QLabel, "TrimLabel").setText(Translator.translate("Trim"))
|
||||||
self.form.findChild(QtGui.QLabel, "MinDraftLabel").setText(Translator.translate("Minimum draft"))
|
self.form.findChild(QtGui.QLabel, "MinDraftLabel").setText(Translator.translate("Minimum draft"))
|
||||||
self.form.findChild(QtGui.QLabel, "MaxDraftLabel").setText(Translator.translate("Maximum draft"))
|
self.form.findChild(QtGui.QLabel, "MaxDraftLabel").setText(Translator.translate("Maximum draft"))
|
||||||
self.form.findChild(QtGui.QLabel, "NDraftLabel").setText(Translator.translate("Number of points"))
|
self.form.findChild(QtGui.QLabel, "NDraftLabel").setText(Translator.translate("Number of points"))
|
||||||
|
|
||||||
def onData(self, value):
|
def onData(self, value):
|
||||||
""" Method called when input data is changed.
|
""" Method called when input data is changed.
|
||||||
@param value Changed value.
|
@param value Changed value.
|
||||||
"""
|
"""
|
||||||
if not self.ship:
|
if not self.ship:
|
||||||
return
|
return
|
||||||
self.form.maxDraft.setMinimum(self.form.minDraft.value())
|
self.form.maxDraft.setMinimum(self.form.minDraft.value())
|
||||||
self.form.minDraft.setMaximum(self.form.maxDraft.value())
|
self.form.minDraft.setMaximum(self.form.maxDraft.value())
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
""" Saves data into ship instance.
|
""" Saves data into ship instance.
|
||||||
"""
|
"""
|
||||||
props = self.ship.PropertiesList
|
props = self.ship.PropertiesList
|
||||||
try:
|
try:
|
||||||
props.index("HydrostaticsTrim")
|
props.index("HydrostaticsTrim")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.ship.addProperty("App::PropertyFloat","HydrostaticsTrim","Ship", str(Translator.translate("Hydrostatics trim selected [m]")))
|
self.ship.addProperty("App::PropertyFloat","HydrostaticsTrim","Ship", str(Translator.translate("Hydrostatics trim selected [m]")))
|
||||||
self.ship.HydrostaticsTrim = self.form.trim.value()
|
self.ship.HydrostaticsTrim = self.form.trim.value()
|
||||||
try:
|
try:
|
||||||
props.index("HydrostaticsMinDraft")
|
props.index("HydrostaticsMinDraft")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.ship.addProperty("App::PropertyFloat","HydrostaticsMinDraft","Ship", str(Translator.translate("Hydrostatics minimum draft selected [m]")))
|
self.ship.addProperty("App::PropertyFloat","HydrostaticsMinDraft","Ship", str(Translator.translate("Hydrostatics minimum draft selected [m]")))
|
||||||
self.ship.HydrostaticsMinDraft = self.form.minDraft.value()
|
self.ship.HydrostaticsMinDraft = self.form.minDraft.value()
|
||||||
try:
|
try:
|
||||||
props.index("HydrostaticsMaxDraft")
|
props.index("HydrostaticsMaxDraft")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.ship.addProperty("App::PropertyFloat","HydrostaticsMaxDraft","Ship", str(Translator.translate("Hydrostatics maximum draft selected [m]")))
|
self.ship.addProperty("App::PropertyFloat","HydrostaticsMaxDraft","Ship", str(Translator.translate("Hydrostatics maximum draft selected [m]")))
|
||||||
self.ship.HydrostaticsMaxDraft = self.form.maxDraft.value()
|
self.ship.HydrostaticsMaxDraft = self.form.maxDraft.value()
|
||||||
try:
|
try:
|
||||||
props.index("HydrostaticsNDraft")
|
props.index("HydrostaticsNDraft")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.ship.addProperty("App::PropertyInteger","HydrostaticsNDraft","Ship", str(Translator.translate("Hydrostatics number of points selected [m]")))
|
self.ship.addProperty("App::PropertyInteger","HydrostaticsNDraft","Ship", str(Translator.translate("Hydrostatics number of points selected [m]")))
|
||||||
self.ship.HydrostaticsNDraft = self.form.nDraft.value()
|
self.ship.HydrostaticsNDraft = self.form.nDraft.value()
|
||||||
|
|
||||||
def createTask():
|
def createTask():
|
||||||
panel = TaskPanel()
|
panel = TaskPanel()
|
||||||
Gui.Control.showDialog(panel)
|
Gui.Control.showDialog(panel)
|
||||||
if panel.setupUi():
|
if panel.setupUi():
|
||||||
Gui.Control.closeDialog(panel)
|
Gui.Control.closeDialog(panel)
|
||||||
return None
|
return None
|
||||||
return panel
|
return panel
|
||||||
|
|
|
@ -51,7 +51,7 @@ def Plot(scale, sections, shape):
|
||||||
x0 = xMid - 0.5*xTot
|
x0 = xMid - 0.5*xTot
|
||||||
y0 = 297.0 - yMid - 0.5*yTot # 297 = A3_width
|
y0 = 297.0 - yMid - 0.5*yTot # 297 = A3_width
|
||||||
# Get border
|
# Get border
|
||||||
edges = self.getEdges([shape])
|
edges = getEdges([shape])
|
||||||
border = edges[0]
|
border = edges[0]
|
||||||
for i in range(0,len(edges)):
|
for i in range(0,len(edges)):
|
||||||
border = border.oldFuse(edges[i]) # Only group objects, don't try to build more complex entities
|
border = border.oldFuse(edges[i]) # Only group objects, don't try to build more complex entities
|
||||||
|
@ -95,7 +95,7 @@ def Plot(scale, sections, shape):
|
||||||
FreeCAD.ActiveDocument.recompute()
|
FreeCAD.ActiveDocument.recompute()
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def getEdges(self, objs=None):
|
def getEdges(objs=None):
|
||||||
""" Returns object edges (list of them)
|
""" Returns object edges (list of them)
|
||||||
@param objs Object to get the faces, none if selected
|
@param objs Object to get the faces, none if selected
|
||||||
object may used.
|
object may used.
|
||||||
|
|
|
@ -1,348 +1,348 @@
|
||||||
#***************************************************************************
|
#***************************************************************************
|
||||||
#* *
|
#* *
|
||||||
#* Copyright (c) 2011, 2012 *
|
#* Copyright (c) 2011, 2012 *
|
||||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||||
#* *
|
#* *
|
||||||
#* This program is free software; you can redistribute it and/or modify *
|
#* This program is free software; you can redistribute it and/or modify *
|
||||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||||
#* as published by the Free Software Foundation; either version 2 of *
|
#* as published by the Free Software Foundation; either version 2 of *
|
||||||
#* the License, or (at your option) any later version. *
|
#* the License, or (at your option) any later version. *
|
||||||
#* for detail see the LICENCE text file. *
|
#* for detail see the LICENCE text file. *
|
||||||
#* *
|
#* *
|
||||||
#* This program is distributed in the hope that it will be useful, *
|
#* This program is distributed in the hope that it will be useful, *
|
||||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
#* GNU Library General Public License for more details. *
|
#* GNU Library General Public License for more details. *
|
||||||
#* *
|
#* *
|
||||||
#* You should have received a copy of the GNU Library General Public *
|
#* You should have received a copy of the GNU Library General Public *
|
||||||
#* License along with this program; if not, write to the Free Software *
|
#* License along with this program; if not, write to the Free Software *
|
||||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
#* USA *
|
#* USA *
|
||||||
#* *
|
#* *
|
||||||
#***************************************************************************
|
#***************************************************************************
|
||||||
|
|
||||||
# FreeCAD modules
|
# FreeCAD modules
|
||||||
import FreeCAD as App
|
import FreeCAD as App
|
||||||
import FreeCADGui as Gui
|
import FreeCADGui as Gui
|
||||||
# Qt library
|
# Qt library
|
||||||
from PyQt4 import QtGui,QtCore
|
from PyQt4 import QtGui,QtCore
|
||||||
# Module
|
# Module
|
||||||
import Preview, Plot
|
import Preview, Plot
|
||||||
import Instance
|
import Instance
|
||||||
from shipUtils import Paths, Translator
|
from shipUtils import Paths, Translator
|
||||||
|
|
||||||
class TaskPanel:
|
class TaskPanel:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.ui = Paths.modulePath() + "/shipOutlineDraw/TaskPanel.ui"
|
self.ui = Paths.modulePath() + "/shipOutlineDraw/TaskPanel.ui"
|
||||||
self.ship = None
|
self.ship = None
|
||||||
self.skip = False
|
self.skip = False
|
||||||
self.LSections = []
|
self.LSections = []
|
||||||
self.BSections = []
|
self.BSections = []
|
||||||
self.TSections = []
|
self.TSections = []
|
||||||
self.obj = None
|
self.obj = None
|
||||||
self.preview = Preview.Preview()
|
self.preview = Preview.Preview()
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
self.saveSections()
|
self.saveSections()
|
||||||
self.obj = Plot.Plot(self.form.scale.value(), self.obj.Shape, self.ship.Shape)
|
self.obj = Plot.Plot(self.form.scale.value(), self.obj.Shape, self.ship.Shape)
|
||||||
self.preview.clean()
|
self.preview.clean()
|
||||||
self.obj.Label = 'OutlineDraw'
|
self.obj.Label = 'OutlineDraw'
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
self.preview.clean()
|
self.preview.clean()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def clicked(self, index):
|
def clicked(self, index):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def needsFullSpace(self):
|
def needsFullSpace(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isAllowedAlterSelection(self):
|
def isAllowedAlterSelection(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def isAllowedAlterView(self):
|
def isAllowedAlterView(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isAllowedAlterDocument(self):
|
def isAllowedAlterDocument(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def helpRequested(self):
|
def helpRequested(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
mw = self.getMainWindow()
|
mw = self.getMainWindow()
|
||||||
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
||||||
form.sections = form.findChild(QtGui.QTableWidget, "Sections")
|
form.sections = form.findChild(QtGui.QTableWidget, "Sections")
|
||||||
try:
|
try:
|
||||||
form.sections.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly)
|
form.sections.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly)
|
||||||
except:
|
except:
|
||||||
msg = Translator.translate("QtCore.Qt.ImhFormattedNumbersOnly not supported, will not used.\n")
|
msg = Translator.translate("QtCore.Qt.ImhFormattedNumbersOnly not supported, will not used.\n")
|
||||||
App.Console.PrintWarning(msg)
|
App.Console.PrintWarning(msg)
|
||||||
form.sectionType = form.findChild(QtGui.QComboBox, "SectionType")
|
form.sectionType = form.findChild(QtGui.QComboBox, "SectionType")
|
||||||
form.deleteButton = form.findChild(QtGui.QPushButton, "DeleteButton")
|
form.deleteButton = form.findChild(QtGui.QPushButton, "DeleteButton")
|
||||||
form.nSections = form.findChild(QtGui.QSpinBox, "NSections")
|
form.nSections = form.findChild(QtGui.QSpinBox, "NSections")
|
||||||
form.createButton = form.findChild(QtGui.QPushButton, "CreateButton")
|
form.createButton = form.findChild(QtGui.QPushButton, "CreateButton")
|
||||||
form.scale = form.findChild(QtGui.QSpinBox, "Scale")
|
form.scale = form.findChild(QtGui.QSpinBox, "Scale")
|
||||||
self.form = form
|
self.form = form
|
||||||
# Initial values
|
# Initial values
|
||||||
if self.initValues():
|
if self.initValues():
|
||||||
return True
|
return True
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
|
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
|
||||||
# Connect Signals and Slots
|
# Connect Signals and Slots
|
||||||
QtCore.QObject.connect(form.sectionType,QtCore.SIGNAL("activated(QString)"),self.onSectionType)
|
QtCore.QObject.connect(form.sectionType,QtCore.SIGNAL("activated(QString)"),self.onSectionType)
|
||||||
QtCore.QObject.connect(form.sections,QtCore.SIGNAL("cellChanged(int,int)"),self.onTableItem);
|
QtCore.QObject.connect(form.sections,QtCore.SIGNAL("cellChanged(int,int)"),self.onTableItem);
|
||||||
QtCore.QObject.connect(form.deleteButton,QtCore.SIGNAL("pressed()"),self.onDeleteButton)
|
QtCore.QObject.connect(form.deleteButton,QtCore.SIGNAL("pressed()"),self.onDeleteButton)
|
||||||
QtCore.QObject.connect(form.createButton,QtCore.SIGNAL("pressed()"),self.onCreateButton)
|
QtCore.QObject.connect(form.createButton,QtCore.SIGNAL("pressed()"),self.onCreateButton)
|
||||||
|
|
||||||
def getMainWindow(self):
|
def getMainWindow(self):
|
||||||
"returns the main window"
|
"returns the main window"
|
||||||
# using QtGui.qApp.activeWindow() isn't very reliable because if another
|
# using QtGui.qApp.activeWindow() isn't very reliable because if another
|
||||||
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
|
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
|
||||||
# returned
|
# returned
|
||||||
toplevel = QtGui.qApp.topLevelWidgets()
|
toplevel = QtGui.qApp.topLevelWidgets()
|
||||||
for i in toplevel:
|
for i in toplevel:
|
||||||
if i.metaObject().className() == "Gui::MainWindow":
|
if i.metaObject().className() == "Gui::MainWindow":
|
||||||
return i
|
return i
|
||||||
raise Exception("No main window found")
|
raise Exception("No main window found")
|
||||||
|
|
||||||
def initValues(self):
|
def initValues(self):
|
||||||
""" Set initial values for fields
|
""" Set initial values for fields
|
||||||
"""
|
"""
|
||||||
# Get selected objects
|
# Get selected objects
|
||||||
selObjs = Gui.Selection.getSelection()
|
selObjs = Gui.Selection.getSelection()
|
||||||
if not selObjs:
|
if not selObjs:
|
||||||
msg = Translator.translate("Ship instance must be selected (no object selected)\n")
|
msg = Translator.translate("Ship instance must be selected (no object selected)\n")
|
||||||
App.Console.PrintError(msg)
|
App.Console.PrintError(msg)
|
||||||
return True
|
return True
|
||||||
for i in range(0,len(selObjs)):
|
for i in range(0,len(selObjs)):
|
||||||
obj = selObjs[i]
|
obj = selObjs[i]
|
||||||
# Test if is a ship instance
|
# Test if is a ship instance
|
||||||
props = obj.PropertiesList
|
props = obj.PropertiesList
|
||||||
try:
|
try:
|
||||||
props.index("IsShip")
|
props.index("IsShip")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
if obj.IsShip:
|
if obj.IsShip:
|
||||||
# Test if another ship already selected
|
# Test if another ship already selected
|
||||||
if self.ship:
|
if self.ship:
|
||||||
msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n")
|
msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n")
|
||||||
App.Console.PrintWarning(msg)
|
App.Console.PrintWarning(msg)
|
||||||
break
|
break
|
||||||
self.ship = obj
|
self.ship = obj
|
||||||
# Test if any valid ship was selected
|
# Test if any valid ship was selected
|
||||||
if not self.ship:
|
if not self.ship:
|
||||||
msg = Translator.translate("Ship instance must be selected (no valid ship found at selected objects)\n")
|
msg = Translator.translate("Ship instance must be selected (no valid ship found at selected objects)\n")
|
||||||
App.Console.PrintError(msg)
|
App.Console.PrintError(msg)
|
||||||
return True
|
return True
|
||||||
# Load sections (if exist)
|
# Load sections (if exist)
|
||||||
self.loadSections()
|
self.loadSections()
|
||||||
msg = Translator.translate("Ready to work\n")
|
msg = Translator.translate("Ready to work\n")
|
||||||
App.Console.PrintMessage(msg)
|
App.Console.PrintMessage(msg)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
""" Set user interface locale strings.
|
""" Set user interface locale strings.
|
||||||
"""
|
"""
|
||||||
self.form.setWindowTitle(Translator.translate("Outline draw"))
|
self.form.setWindowTitle(Translator.translate("Outline draw"))
|
||||||
self.form.findChild(QtGui.QGroupBox, "AutoCreateBox").setTitle(Translator.translate("Auto create"))
|
self.form.findChild(QtGui.QGroupBox, "AutoCreateBox").setTitle(Translator.translate("Auto create"))
|
||||||
self.form.findChild(QtGui.QGroupBox, "ScaleBox").setTitle(Translator.translate("Scale"))
|
self.form.findChild(QtGui.QGroupBox, "ScaleBox").setTitle(Translator.translate("Scale"))
|
||||||
self.form.findChild(QtGui.QPushButton, "DeleteButton").setText(Translator.translate("Delete all sections"))
|
self.form.findChild(QtGui.QPushButton, "DeleteButton").setText(Translator.translate("Delete all sections"))
|
||||||
self.form.findChild(QtGui.QPushButton, "CreateButton").setText(Translator.translate("Create sections"))
|
self.form.findChild(QtGui.QPushButton, "CreateButton").setText(Translator.translate("Create sections"))
|
||||||
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(0, Translator.translate("Transversal"))
|
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(0, Translator.translate("Transversal"))
|
||||||
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(1, Translator.translate("Longitudinal"))
|
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(1, Translator.translate("Longitudinal"))
|
||||||
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(2, Translator.translate("Water lines"))
|
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(2, Translator.translate("Water lines"))
|
||||||
|
|
||||||
def onSectionType(self):
|
def onSectionType(self):
|
||||||
""" Function called when the section type is changed.
|
""" Function called when the section type is changed.
|
||||||
"""
|
"""
|
||||||
# Search section type
|
# Search section type
|
||||||
ID = self.form.sectionType.currentIndex()
|
ID = self.form.sectionType.currentIndex()
|
||||||
self.setSectionType(ID)
|
self.setSectionType(ID)
|
||||||
|
|
||||||
def setSectionType(self, ID):
|
def setSectionType(self, ID):
|
||||||
""" Function that set the type section related table.
|
""" Function that set the type section related table.
|
||||||
@param ID Id of the section to set: \n
|
@param ID Id of the section to set: \n
|
||||||
0 = Transversal sections \n
|
0 = Transversal sections \n
|
||||||
1 = Longitudinal sections \n
|
1 = Longitudinal sections \n
|
||||||
2 = Water lines
|
2 = Water lines
|
||||||
"""
|
"""
|
||||||
SectionList = []
|
SectionList = []
|
||||||
if ID == 0:
|
if ID == 0:
|
||||||
SectionList = self.LSections[:]
|
SectionList = self.LSections[:]
|
||||||
elif ID == 1:
|
elif ID == 1:
|
||||||
SectionList = self.BSections[:]
|
SectionList = self.BSections[:]
|
||||||
elif ID == 2:
|
elif ID == 2:
|
||||||
SectionList = self.TSections[:]
|
SectionList = self.TSections[:]
|
||||||
nRow = len(SectionList)
|
nRow = len(SectionList)
|
||||||
self.form.sections.clearContents()
|
self.form.sections.clearContents()
|
||||||
self.form.sections.setRowCount(nRow+1)
|
self.form.sections.setRowCount(nRow+1)
|
||||||
if not nRow:
|
if not nRow:
|
||||||
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
|
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
|
||||||
return
|
return
|
||||||
self.skip = True # Avoid recursive call to OnItem
|
self.skip = True # Avoid recursive call to OnItem
|
||||||
for i in range(0,nRow):
|
for i in range(0,nRow):
|
||||||
if i == nRow-1:
|
if i == nRow-1:
|
||||||
self.skip = False
|
self.skip = False
|
||||||
string = '%f' % (SectionList[i])
|
string = '%f' % (SectionList[i])
|
||||||
item = QtGui.QTableWidgetItem(string)
|
item = QtGui.QTableWidgetItem(string)
|
||||||
self.form.sections.setItem(i,0,item)
|
self.form.sections.setItem(i,0,item)
|
||||||
|
|
||||||
def onTableItem(self, row, column):
|
def onTableItem(self, row, column):
|
||||||
""" Function called when an item of table is changed.
|
""" Function called when an item of table is changed.
|
||||||
@param row Changed item row
|
@param row Changed item row
|
||||||
@param column Changed item column
|
@param column Changed item column
|
||||||
"""
|
"""
|
||||||
if self.skip:
|
if self.skip:
|
||||||
return
|
return
|
||||||
# Ensure that exist one empty item at least
|
# Ensure that exist one empty item at least
|
||||||
nRow = self.form.sections.rowCount()
|
nRow = self.form.sections.rowCount()
|
||||||
item = self.form.sections.item(nRow-1,0)
|
item = self.form.sections.item(nRow-1,0)
|
||||||
if item :
|
if item :
|
||||||
if(item.text() != ''):
|
if(item.text() != ''):
|
||||||
self.form.sections.setRowCount(nRow+1)
|
self.form.sections.setRowCount(nRow+1)
|
||||||
# Ensure that new item is a number
|
# Ensure that new item is a number
|
||||||
ID = self.form.sectionType.currentIndex()
|
ID = self.form.sectionType.currentIndex()
|
||||||
if ID == 0:
|
if ID == 0:
|
||||||
SectionList = self.LSections[:]
|
SectionList = self.LSections[:]
|
||||||
elif ID == 1:
|
elif ID == 1:
|
||||||
SectionList = self.BSections[:]
|
SectionList = self.BSections[:]
|
||||||
elif ID == 2:
|
elif ID == 2:
|
||||||
SectionList = self.TSections[:]
|
SectionList = self.TSections[:]
|
||||||
item = self.form.sections.item(row,column)
|
item = self.form.sections.item(row,column)
|
||||||
(number,flag) = item.text().toFloat()
|
(number,flag) = item.text().toFloat()
|
||||||
if not flag:
|
if not flag:
|
||||||
if len(SectionList) > nRow-1:
|
if len(SectionList) > nRow-1:
|
||||||
number = SectionList[nRow-1]
|
number = SectionList[nRow-1]
|
||||||
else:
|
else:
|
||||||
number = 0.0
|
number = 0.0
|
||||||
string = '%f' % (number)
|
string = '%f' % (number)
|
||||||
item.setText(string)
|
item.setText(string)
|
||||||
# Regenerate the list
|
# Regenerate the list
|
||||||
SectionList = []
|
SectionList = []
|
||||||
for i in range(0,nRow):
|
for i in range(0,nRow):
|
||||||
item = self.form.sections.item(i,0)
|
item = self.form.sections.item(i,0)
|
||||||
if item:
|
if item:
|
||||||
(number,flag) = item.text().toFloat()
|
(number,flag) = item.text().toFloat()
|
||||||
SectionList.append(number)
|
SectionList.append(number)
|
||||||
# Paste it into the class list
|
# Paste it into the class list
|
||||||
ID = self.form.sectionType.currentIndex()
|
ID = self.form.sectionType.currentIndex()
|
||||||
if ID == 0:
|
if ID == 0:
|
||||||
self.LSections = SectionList[:]
|
self.LSections = SectionList[:]
|
||||||
elif ID == 1:
|
elif ID == 1:
|
||||||
self.BSections = SectionList[:]
|
self.BSections = SectionList[:]
|
||||||
elif ID == 2:
|
elif ID == 2:
|
||||||
self.TSections = SectionList[:]
|
self.TSections = SectionList[:]
|
||||||
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
|
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
|
||||||
|
|
||||||
def onDeleteButton(self):
|
def onDeleteButton(self):
|
||||||
""" Function called when the delete button is pressed.
|
""" Function called when the delete button is pressed.
|
||||||
All sections mustt be erased
|
All sections mustt be erased
|
||||||
"""
|
"""
|
||||||
self.form.sections.clearContents()
|
self.form.sections.clearContents()
|
||||||
self.form.sections.setRowCount(1)
|
self.form.sections.setRowCount(1)
|
||||||
# Clear active list
|
# Clear active list
|
||||||
ID = self.form.sectionType.currentIndex()
|
ID = self.form.sectionType.currentIndex()
|
||||||
if ID == 0:
|
if ID == 0:
|
||||||
self.LSections = []
|
self.LSections = []
|
||||||
elif ID == 1:
|
elif ID == 1:
|
||||||
self.BSections = []
|
self.BSections = []
|
||||||
elif ID == 2:
|
elif ID == 2:
|
||||||
self.TSections = []
|
self.TSections = []
|
||||||
self.setSectionType(ID)
|
self.setSectionType(ID)
|
||||||
|
|
||||||
def onCreateButton(self):
|
def onCreateButton(self):
|
||||||
""" Function called when create button is pressed.
|
""" Function called when create button is pressed.
|
||||||
Several sections must be added to list
|
Several sections must be added to list
|
||||||
"""
|
"""
|
||||||
# Recolect data
|
# Recolect data
|
||||||
nSections = self.form.nSections.value()
|
nSections = self.form.nSections.value()
|
||||||
SectionList = []
|
SectionList = []
|
||||||
L = 0.0
|
L = 0.0
|
||||||
ID = self.form.sectionType.currentIndex()
|
ID = self.form.sectionType.currentIndex()
|
||||||
if ID == 0:
|
if ID == 0:
|
||||||
L = self.ship.Length
|
L = self.ship.Length
|
||||||
d = L / (nSections-1) # Distance between sections
|
d = L / (nSections-1) # Distance between sections
|
||||||
start = - L/2.0 # Ship must have 0.0 at coordinates origin
|
start = - L/2.0 # Ship must have 0.0 at coordinates origin
|
||||||
elif ID == 1:
|
elif ID == 1:
|
||||||
L = -0.5*self.ship.Beam # Ship must be in y<0.0
|
L = -0.5*self.ship.Beam # Ship must be in y<0.0
|
||||||
d = L / (nSections+1.0) # Distance between sections
|
d = L / (nSections+1.0) # Distance between sections
|
||||||
start = d
|
start = d
|
||||||
elif ID == 2:
|
elif ID == 2:
|
||||||
L = self.ship.Draft
|
L = self.ship.Draft
|
||||||
d = L / (nSections) # Distance between sections
|
d = L / (nSections) # Distance between sections
|
||||||
start = d
|
start = d
|
||||||
# Calculate sections
|
# Calculate sections
|
||||||
for i in range(0,nSections):
|
for i in range(0,nSections):
|
||||||
sec = i*d + start
|
sec = i*d + start
|
||||||
SectionList.append(sec)
|
SectionList.append(sec)
|
||||||
# Paste into class table
|
# Paste into class table
|
||||||
if ID == 0:
|
if ID == 0:
|
||||||
self.LSections = SectionList[:]
|
self.LSections = SectionList[:]
|
||||||
elif ID == 1:
|
elif ID == 1:
|
||||||
self.BSections = SectionList[:]
|
self.BSections = SectionList[:]
|
||||||
elif ID == 2:
|
elif ID == 2:
|
||||||
self.TSections = SectionList[:]
|
self.TSections = SectionList[:]
|
||||||
# Print the table
|
# Print the table
|
||||||
self.setSectionType(ID)
|
self.setSectionType(ID)
|
||||||
|
|
||||||
def loadSections(self):
|
def loadSections(self):
|
||||||
""" Loads from ship object previously selected sections.
|
""" Loads from ship object previously selected sections.
|
||||||
"""
|
"""
|
||||||
# Load sections
|
# Load sections
|
||||||
props = self.ship.PropertiesList
|
props = self.ship.PropertiesList
|
||||||
flag=True
|
flag=True
|
||||||
try:
|
try:
|
||||||
props.index("LSections")
|
props.index("LSections")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
flag=False
|
flag=False
|
||||||
if flag:
|
if flag:
|
||||||
self.LSections = self.ship.LSections[:]
|
self.LSections = self.ship.LSections[:]
|
||||||
self.BSections = self.ship.BSections[:]
|
self.BSections = self.ship.BSections[:]
|
||||||
self.TSections = self.ship.TSections[:]
|
self.TSections = self.ship.TSections[:]
|
||||||
# Load scale too
|
# Load scale too
|
||||||
flag=True
|
flag=True
|
||||||
try:
|
try:
|
||||||
props.index("PlotScale")
|
props.index("PlotScale")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
flag=False
|
flag=False
|
||||||
if flag:
|
if flag:
|
||||||
self.form.scale.setValue(self.ship.PlotScale)
|
self.form.scale.setValue(self.ship.PlotScale)
|
||||||
# Set UI
|
# Set UI
|
||||||
self.setSectionType(self.form.sectionType.currentIndex())
|
self.setSectionType(self.form.sectionType.currentIndex())
|
||||||
|
|
||||||
def saveSections(self):
|
def saveSections(self):
|
||||||
""" Save selected sections into ship object.
|
""" Save selected sections into ship object.
|
||||||
"""
|
"""
|
||||||
# Test if previous section have been created
|
# Test if previous section have been created
|
||||||
props = self.ship.PropertiesList
|
props = self.ship.PropertiesList
|
||||||
try:
|
try:
|
||||||
props.index("LSections")
|
props.index("LSections")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# Create new sections list
|
# Create new sections list
|
||||||
self.ship.addProperty("App::PropertyFloatList","LSections","Ship", str(Translator.translate("Transversal sections position [m]"))).LSections=[]
|
self.ship.addProperty("App::PropertyFloatList","LSections","Ship", str(Translator.translate("Transversal sections position [m]"))).LSections=[]
|
||||||
self.ship.addProperty("App::PropertyFloatList","BSections","Ship", str(Translator.translate("Longitudinal sections position [m]"))).BSections=[]
|
self.ship.addProperty("App::PropertyFloatList","BSections","Ship", str(Translator.translate("Longitudinal sections position [m]"))).BSections=[]
|
||||||
self.ship.addProperty("App::PropertyFloatList","TSections","Ship", str(Translator.translate("Water lines position [m]"))).TSections=[]
|
self.ship.addProperty("App::PropertyFloatList","TSections","Ship", str(Translator.translate("Water lines position [m]"))).TSections=[]
|
||||||
# Save sections
|
# Save sections
|
||||||
self.ship.LSections = self.LSections[:]
|
self.ship.LSections = self.LSections[:]
|
||||||
self.ship.BSections = self.BSections[:]
|
self.ship.BSections = self.BSections[:]
|
||||||
self.ship.TSections = self.TSections[:]
|
self.ship.TSections = self.TSections[:]
|
||||||
# Save also scale
|
# Save also scale
|
||||||
try:
|
try:
|
||||||
props.index("PlotScale")
|
props.index("PlotScale")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.ship.addProperty("App::PropertyInteger","PlotScale","Ship", str(Translator.translate("Plot scale (1:scale format)"))).PlotScale=250
|
self.ship.addProperty("App::PropertyInteger","PlotScale","Ship", str(Translator.translate("Plot scale (1:scale format)"))).PlotScale=250
|
||||||
self.ship.PlotScale = self.form.scale.value()
|
self.ship.PlotScale = self.form.scale.value()
|
||||||
|
|
||||||
def createTask():
|
def createTask():
|
||||||
panel = TaskPanel()
|
panel = TaskPanel()
|
||||||
Gui.Control.showDialog(panel)
|
Gui.Control.showDialog(panel)
|
||||||
if panel.setupUi():
|
if panel.setupUi():
|
||||||
Gui.Control.closeDialog(panel)
|
Gui.Control.closeDialog(panel)
|
||||||
return None
|
return None
|
||||||
return panel
|
return panel
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
import os
|
import os
|
||||||
# FreeCAD modules
|
# FreeCAD modules
|
||||||
import FreeCAD,FreeCADGui
|
import FreeCAD,FreeCADGui
|
||||||
from FreeCAD import Base, Image, ImageGui
|
from FreeCAD import Base
|
||||||
import Part
|
import Part, Image, ImageGui
|
||||||
# FreeCADShip modules
|
# FreeCADShip modules
|
||||||
from shipUtils import Paths, Translator
|
from shipUtils import Paths, Translator
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user