Merge branch 'master' into logari81/PartDesign

This commit is contained in:
logari81 2012-09-09 10:11:20 +02:00
commit 9f452bd6ca
29 changed files with 789 additions and 701 deletions

View File

@ -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

View File

@ -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}
) )

View File

@ -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 )

View File

@ -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 \

View File

@ -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 \

View File

@ -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 */

View File

@ -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;
}; };
/** /**

View File

@ -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());
} }

View File

@ -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

View File

@ -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)

View File

@ -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());

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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");

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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());

View File

@ -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
*/ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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