diff --git a/editbox.cpp b/editbox.cpp index 1e89728..f7f18f3 100644 --- a/editbox.cpp +++ b/editbox.cpp @@ -41,7 +41,8 @@ EditBox::EditBox(ProgramModel *programUnit, QWidget *parent) : m_modifiedLine(-1), m_modifiedLineIsNew(false), m_lineCount(0), - m_cursorValid(false) + m_cursorValid(false), + m_recreatingLine(false) { // set the edit box to a fixed width font QFont font = this->font(); @@ -65,6 +66,10 @@ EditBox::EditBox(ProgramModel *programUnit, QWidget *parent) : // FROM PROGRAM CONNECTIONS //============================ + // connect to catch program line changes + connect(m_programUnit, SIGNAL(programChange(int)), + this, SLOT(programChanged(int))); + // connect to catch when an error has been inserted connect(m_programUnit, SIGNAL(errorInserted(int, ErrorItem)), this, SLOT(errorInserted(int, ErrorItem))); @@ -308,6 +313,11 @@ void EditBox::resetModified(void) void EditBox::documentChanged(int position, int charsRemoved, int charsAdded) { + if (m_recreatingLine) + { + return; // change due to recreated line, ignore + } + int linesInserted = 0; int linesDeleted = 0; QStringList lines; @@ -456,6 +466,10 @@ void EditBox::documentChanged(int position, int charsRemoved, int charsAdded) void EditBox::cursorMoved(void) { + if (m_recreatingLine) + { + return; // ignore cursor movements when recreating line + } if (!m_cursorValid) // waiting for cursor to be valid? { m_cursorValid = true; // cursor is now valid @@ -480,6 +494,32 @@ void EditBox::setPlainText(const QString &text) } +// function to received program model line changes +void EditBox::programChanged(int lineNumber) +{ + QString lineText = m_programUnit->lineText(lineNumber); + if (lineText.isNull()) // line has error? + { + return; // don't do anything + } + if (!m_cursorValid) + { + return; // FIXME can't replace lines until cursor is valid + } + + QTextCursor cursor = textCursor(); + cursor.setPosition(document()->findBlockByLineNumber(lineNumber) + .position()); + cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + + // prevent document changed and cursor moved signals + // from being processed before replacing line text + m_recreatingLine = true; + cursor.insertText(lineText); + m_recreatingLine = false; +} + + // function to check if current line was modified and to process it void EditBox::captureModifiedLine(int offset) diff --git a/editbox.h b/editbox.h index b7030a1..75d42f5 100644 --- a/editbox.h +++ b/editbox.h @@ -77,6 +77,7 @@ public slots: void documentChanged(int position, int charsRemoved, int charsAdded); void cursorMoved(void); void setPlainText(const QString &text); + void programChanged(int lineNumber); private slots: void errorListChanged(void); @@ -102,6 +103,7 @@ private slots: m_extraSelections; // error highlight extra selections list bool m_cursorValid; // flag for when text cursor is valid QList m_errors; // list of errors during startup + bool m_recreatingLine; // change due to recreated text flag }; diff --git a/programmodel.cpp b/programmodel.cpp index 540ed8c..961f021 100644 --- a/programmodel.cpp +++ b/programmodel.cpp @@ -178,11 +178,16 @@ QString ProgramModel::dictionariesDebugText(void) // function to return text for a given program line QString ProgramModel::lineText(int lineIndex) { + QString string; + LineInfo &lineInfo = m_lineInfo[lineIndex]; - RpnList *rpnList = decode(lineInfo); - QString string = m_recreator->recreate(rpnList); - delete rpnList; - return string; + if (lineInfo.errIndex == -1) + { + RpnList *rpnList = decode(lineInfo); + string = m_recreator->recreate(rpnList); + delete rpnList; + } + return string; // return null string if line has error } @@ -292,30 +297,30 @@ bool ProgramModel::updateLine(Operation operation, int lineNumber, { LineInfo &lineInfo = m_lineInfo[lineNumber]; RpnList *currentRpnList = decode(lineInfo); - bool same = *rpnList == *currentRpnList; + bool changed = *rpnList != *currentRpnList; delete currentRpnList; - if (same) + if (changed) { - delete rpnList; // not needed - return false; // line not changed; nothing more to do here - } + // derefence old line + // (line gets deleted if new line has an error) + dereference(lineInfo); - // derefence old line - // (line gets deleted if new line has an error) - dereference(lineInfo); + // line is different, encode it if there was no translation error + if (errorItem.isEmpty()) + { + lineCode = encode(rpnList); + } - // line is different, encode it if there was no translation error - if (errorItem.isEmpty()) - { - lineCode = encode(rpnList); - } - delete rpnList; // no longer needed + updateError(lineNumber, lineInfo, errorItem, false); - updateError(lineNumber, lineInfo, errorItem, false); + // replace with new line + m_code.replaceLine(lineInfo.offset, lineInfo.size, lineCode); + m_lineInfo.replace(lineNumber, lineCode.size()); + } - // replace with new line - m_code.replaceLine(lineInfo.offset, lineInfo.size, lineCode); - m_lineInfo.replace(lineNumber, lineCode.size()); + emit programChange(lineNumber); + delete rpnList; // no longer needed + return changed; } else if (operation == Insert_Operation) { @@ -346,6 +351,7 @@ bool ProgramModel::updateLine(Operation operation, int lineNumber, m_code.insertLine(lineInfo.offset, lineCode); m_lineInfo.insert(lineNumber, lineInfo); + emit programChange(lineNumber); } else if (operation == Remove_Operation) { diff --git a/programmodel.h b/programmodel.h index ec52f0b..19787bb 100644 --- a/programmodel.h +++ b/programmodel.h @@ -231,6 +231,7 @@ class ProgramModel : public QAbstractListModel signals: void lineCountChanged(int newLineCount); + void programChange(int lineNumber); void errorInserted(int errIndex, const ErrorItem &errorItem); void errorChanged(int errIndex, const ErrorItem &errorItem); void errorRemoved(int errIndex); diff --git a/recreator.cpp b/recreator.cpp index 6423b19..8aad17b 100644 --- a/recreator.cpp +++ b/recreator.cpp @@ -38,7 +38,7 @@ Recreator::Recreator(void) : // function to recreate original program text from an rpn list QString Recreator::recreate(RpnList *rpnList, bool exprMode) { - m_output.clear(); + m_output = ""; for (int i = 0; i < rpnList->count(); i++) { RpnItem *rpnItem = rpnList->at(i);