diff --git a/FunctionList.cc b/FunctionList.cc index fd214c12031d0fd29feb765a1b5f49bfefe12406..fca954d0b9b3d20672628a4647c003cb5f855694 100644 --- a/FunctionList.cc +++ b/FunctionList.cc @@ -41,7 +41,6 @@ \*===========================================================================*/ #include "FunctionList.hh" -#include <iostream> FunctionList::FunctionList(QWidget *parent) : QListWidget(parent) @@ -101,4 +100,4 @@ void FunctionList::filter(QString _filter){ void FunctionList::reset(){ for (int i=0; i < count(); i++) item(i)->setHidden(false); -} \ No newline at end of file +} diff --git a/ScriptingPlugin.cc b/ScriptingPlugin.cc index 31c2f5dcbde877e827e1bf033fe17e355712c460..387a4a5b37f4dc74aa2c042646b0520ede95bf2c 100644 --- a/ScriptingPlugin.cc +++ b/ScriptingPlugin.cc @@ -45,7 +45,6 @@ #include "ScriptingPlugin.hh" -#include <iostream> #include <ACG/GL/GLState.hh> #include <OpenFlipper/BasePlugin/PluginFunctions.hh> @@ -167,7 +166,7 @@ void ScriptingPlugin::pluginsInitialized() { scriptWidget_->description->setVisible( false ); - highlighterCurrent_ = new Highlighter( scriptWidget_->currentScript ); + highlighterCurrent_ = new Highlighter( scriptWidget_->currentScript->document() ); highlighterLive_ = new Highlighter( scriptWidget_->liveEdit ); // highlighterList_ = new Highlighter( scriptWidget_->functionList ); frameTime_.start(); @@ -275,8 +274,17 @@ void ScriptingPlugin::slotExecuteScript( QString _script ) { int lineNumber = engine->uncaughtExceptionLineNumber(); emit log( LOGERR , tr("Script execution failed at line %1, with : %2 ").arg(lineNumber).arg(exception) ); - if ( OpenFlipper::Options::gui()) + if ( OpenFlipper::Options::gui()) { statusBar_->showMessage(tr("Script execution failed at line %1, with : %2 ").arg(lineNumber).arg(exception)); + + // Get cursor and move it to the line containing the error + QTextCursor cursor = scriptWidget_->currentScript->textCursor(); + cursor.setPosition(0); + cursor.movePosition ( QTextCursor::Down, QTextCursor::MoveAnchor, lineNumber - 1 ); + scriptWidget_->currentScript->setTextCursor(cursor); + + scriptWidget_->currentScript->highLightErrorLine(lineNumber); + } } if ( OpenFlipper::Options::gui() && !error) @@ -297,7 +305,7 @@ void ScriptingPlugin::slotExecuteFileScript( QString _filename ) { } while (!input.atEnd()); if ( OpenFlipper::Options::gui() ) - scriptWidget_->currentScript->setText(script); + scriptWidget_->currentScript->setPlainText(script); // Set lastfilename to the opened file lastFile_ = _filename; @@ -437,7 +445,7 @@ void ScriptingPlugin::slotLoadScript( QString _filename ) { if (data.open(QFile::ReadOnly)) { QTextStream input(&data); do { - scriptWidget_->currentScript->append(input.readLine()); + scriptWidget_->currentScript->appendPlainText(input.readLine()); } while (!input.atEnd()); lastFile_ = _filename; @@ -569,7 +577,7 @@ void ScriptingPlugin::showScriptInEditor(QString _code) showScriptWidget (); - scriptWidget_->currentScript->setText (_code); + scriptWidget_->currentScript->setPlainText(_code); } void ScriptingPlugin::clearEditor() { diff --git a/ScriptingPlugin.hh b/ScriptingPlugin.hh index f2c7421b2820de5edfb7dcbba957ef2b665ae0d4..d72df96f4f26b1d8ccaefdac918c0b27c212bad0 100644 --- a/ScriptingPlugin.hh +++ b/ScriptingPlugin.hh @@ -57,6 +57,7 @@ #include "scriptingWidget.hh" + class ScriptingPlugin : public QObject, BaseInterface, MenuInterface, ScriptInterface, RPCInterface, LoggingInterface { Q_OBJECT diff --git a/codeeditor.cc b/codeeditor.cc new file mode 100644 index 0000000000000000000000000000000000000000..1d39191f9dced4c94a845a600e9f30930bf3cee0 --- /dev/null +++ b/codeeditor.cc @@ -0,0 +1,168 @@ + +/*===========================================================================*\ +* * +* OpenFlipper * +* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * +* www.openflipper.org * +* * +*--------------------------------------------------------------------------- * +* This file is part of OpenFlipper. * +* * +* OpenFlipper is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as * +* published by the Free Software Foundation, either version 3 of * +* the License, or (at your option) any later version with the * +* following exceptions: * +* * +* If other files instantiate templates or use macros * +* or inline functions from this file, or you compile this file and * +* link it with other files to produce an executable, this file does * +* not by itself cause the resulting executable to be covered by the * +* GNU Lesser General Public License. This exception does not however * +* invalidate any other reasons why the executable file might be * +* covered by the GNU Lesser General Public License. * +* * +* OpenFlipper is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU LesserGeneral Public * +* License along with OpenFlipper. If not, * +* see <http://www.gnu.org/licenses/>. * +* * +\*===========================================================================*/ + +/*===========================================================================*\ +* * +* $Revision$ * +* $LastChangedBy$ * +* $Date$ * +* * +\*===========================================================================*/ + +#include <QtGui> + +#include "codeeditor.hh" + + +CodeEditorWidget::CodeEditorWidget(QWidget *parent) : QPlainTextEdit(parent) { + lineNumberArea = new LineNumberArea(this); + + connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); + connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); + connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine())); + + updateLineNumberAreaWidth(0); + highlightCurrentLine(); +} + + + +int CodeEditorWidget::lineNumberAreaWidth() { + + int digits = 1; + int max = qMax(1, blockCount()); + while (max >= 10) { + max /= 10; + ++digits; + } + + int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits; + + return space; +} + + + +void CodeEditorWidget::updateLineNumberAreaWidth(int /* newBlockCount */) { + setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); +} + + + +void CodeEditorWidget::updateLineNumberArea(const QRect &rect, int dy) { + if (dy) + lineNumberArea->scroll(0, dy); + else + lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); + + if (rect.contains(viewport()->rect())) + updateLineNumberAreaWidth(0); +} + + + +void CodeEditorWidget::resizeEvent(QResizeEvent *e) { + QPlainTextEdit::resizeEvent(e); + + QRect cr = contentsRect(); + lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); +} + + + +void CodeEditorWidget::highlightCurrentLine() { + QList<QTextEdit::ExtraSelection> extraSelections; + + if (!isReadOnly()) { + QTextEdit::ExtraSelection selection; + + QColor lineColor = QColor(Qt::yellow).lighter(160); + + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + +void CodeEditorWidget::highLightErrorLine(int _line) { + QList<QTextEdit::ExtraSelection> extraSelections; + + if (!isReadOnly()) { + QTextEdit::ExtraSelection selection; + + QColor lineColor = QColor(Qt::red).lighter(160); + + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = QTextCursor(document()); + selection.cursor.movePosition ( QTextCursor::Down, QTextCursor::MoveAnchor, _line - 1 ); + selection.cursor.clearSelection(); + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + + + +void CodeEditorWidget::lineNumberAreaPaintEvent(QPaintEvent *event) { + + QPainter painter(lineNumberArea); + painter.fillRect(event->rect(), Qt::lightGray); + + + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top(); + int bottom = top + (int) blockBoundingRect(block).height(); + + while (block.isValid() && top <= event->rect().bottom()) { + if (block.isVisible() && bottom >= event->rect().top()) { + QString number = QString::number(blockNumber + 1); + painter.setPen(Qt::black); + painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),Qt::AlignRight, number); + } + + block = block.next(); + top = bottom; + bottom = top + (int) blockBoundingRect(block).height(); + ++blockNumber; + } + +} diff --git a/codeeditor.hh b/codeeditor.hh new file mode 100644 index 0000000000000000000000000000000000000000..93ff19806c6bbfcc609b23529d45c516a8e64966 --- /dev/null +++ b/codeeditor.hh @@ -0,0 +1,104 @@ +/*===========================================================================*\ +* * +* OpenFlipper * +* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * +* www.openflipper.org * +* * +*--------------------------------------------------------------------------- * +* This file is part of OpenFlipper. * +* * +* OpenFlipper is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as * +* published by the Free Software Foundation, either version 3 of * +* the License, or (at your option) any later version with the * +* following exceptions: * +* * +* If other files instantiate templates or use macros * +* or inline functions from this file, or you compile this file and * +* link it with other files to produce an executable, this file does * +* not by itself cause the resulting executable to be covered by the * +* GNU Lesser General Public License. This exception does not however * +* invalidate any other reasons why the executable file might be * +* covered by the GNU Lesser General Public License. * +* * +* OpenFlipper is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU LesserGeneral Public * +* License along with OpenFlipper. If not, * +* see <http://www.gnu.org/licenses/>. * +* * +\*===========================================================================*/ + +/*===========================================================================*\ +* * +* $Revision$ * +* $LastChangedBy$ * +* $Date$ * +* * +\*===========================================================================*/ + +#ifndef CODEEDITORWIDGET_HH +#define CODEEDITORWIDGET_HH + +#include <QPlainTextEdit> +#include <QObject> + +class QPaintEvent; +class QResizeEvent; +class QSize; +class QWidget; + +class LineNumberArea; + + +class CodeEditorWidget : public QPlainTextEdit +{ + Q_OBJECT + + public: + CodeEditorWidget(QWidget *parent = 0); + + void lineNumberAreaPaintEvent(QPaintEvent *event); + int lineNumberAreaWidth(); + + protected: + void resizeEvent(QResizeEvent *event); + + public: + void highLightErrorLine(int _line); + + private slots: + void updateLineNumberAreaWidth(int newBlockCount); + void highlightCurrentLine(); + void updateLineNumberArea(const QRect &, int); + + private: + QWidget *lineNumberArea; +}; + + +class LineNumberArea : public QWidget +{ + public: + LineNumberArea(CodeEditorWidget *editor) : QWidget(editor) { + codeEditor = editor; + } + + QSize sizeHint() const { + return QSize(codeEditor->lineNumberAreaWidth(), 0); + } + + protected: + void paintEvent(QPaintEvent *event) { + codeEditor->lineNumberAreaPaintEvent(event); + } + + private: + CodeEditorWidget *codeEditor; +}; + + +#endif diff --git a/highLighter.cc b/highLighter.cc index 82004a89c018f3e1696c60c82ef1c6fba3205aae..fe046e681b6cf5ffcbe7722b8141bea98d4064b3 100644 --- a/highLighter.cc +++ b/highLighter.cc @@ -44,63 +44,71 @@ #include "highLighter.hh" - Highlighter::Highlighter(QTextEdit *parent) + Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) { - // Set the basic format styles - keywordFormat_.setForeground(Qt::darkGreen); - keywordFormat_.setFontWeight(QFont::Bold); + init(); +} + +Highlighter::Highlighter(QTextEdit *parent) +: QSyntaxHighlighter(parent) +{ + init(); +} - pluginFormat_.setForeground(Qt::darkBlue); - pluginFormat_.setFontWeight(QFont::Bold); + void Highlighter::init() { + // Set the basic format styles + keywordFormat_.setForeground(Qt::darkGreen); + keywordFormat_.setFontWeight(QFont::Bold); - functionFormat_.setForeground(Qt::darkYellow); - functionFormat_.setFontWeight(QFont::Bold); + pluginFormat_.setForeground(Qt::darkBlue); + pluginFormat_.setFontWeight(QFont::Bold); - typeFormat_.setForeground(Qt::darkMagenta); - typeFormat_.setFontWeight(QFont::Bold); + functionFormat_.setForeground(Qt::darkYellow); + functionFormat_.setFontWeight(QFont::Bold); - quotationFormat_.setForeground(Qt::darkRed); + typeFormat_.setForeground(Qt::darkMagenta); + typeFormat_.setFontWeight(QFont::Bold); - listFormat_.setForeground(Qt::darkRed); + quotationFormat_.setForeground(Qt::darkRed); - singleLineCommentFormat_.setForeground(Qt::red); - multiLineCommentFormat_.setForeground(Qt::red); + listFormat_.setForeground(Qt::darkRed); - commentStartExpression_ = QRegExp("/\\*"); - commentEndExpression_ = QRegExp("\\*/"); + singleLineCommentFormat_.setForeground(Qt::red); + multiLineCommentFormat_.setForeground(Qt::red); - // Define basic keywords - keywordPatterns_ << "while" << "for" << "print" << "var"; + commentStartExpression_ = QRegExp("/\\*"); + commentEndExpression_ = QRegExp("\\*/"); - // Types which are accepted by the scripting system - typePatterns_ << "int" << "Matrix4x4" << "QString" << "idList" << "bool" << "Vector" << "double"; + // Define basic keywords + keywordPatterns_ << "while" << "for" << "print" << "var"; - update(); + // Types which are accepted by the scripting system + typePatterns_ << "int" << "Matrix4x4" << "QString" << "idList" << "bool" << "Vector" << "double"; -// classFormat.setFontWeight(QFont::Bold); -// classFormat.setForeground(Qt::darkMagenta); -// rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b"); -// rule.format = classFormat; -// highlightingRules.append(rule); -// + update(); + // classFormat.setFontWeight(QFont::Bold); + // classFormat.setForeground(Qt::darkMagenta); + // rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b"); + // rule.format = classFormat; + // highlightingRules.append(rule); + // -// functionFormat.setFontItalic(true); -// functionFormat.setForeground(Qt::blue); -// rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); -// rule.format = functionFormat; -// highlightingRules.append(rule); -// + // functionFormat.setFontItalic(true); + // functionFormat.setForeground(Qt::blue); + // rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); + // rule.format = functionFormat; + // highlightingRules.append(rule); + // } void Highlighter::update() { highlightingRules_.clear(); - HighlightingRule rule; // Create Rules for keywords @@ -150,7 +158,8 @@ void Highlighter::update() { void Highlighter::highlightBlock(const QString &text) { - foreach (HighlightingRule rule, highlightingRules_) { + + foreach (HighlightingRule rule, highlightingRules_) { QRegExp expression(rule.pattern); int index = text.indexOf(expression); while (index >= 0) { diff --git a/highLighter.hh b/highLighter.hh index 0f4bfa34f7ef8f53080fc4014bc587cf39ad35d2..f7fbcfff6a2d0e34e78d6d498019a6936cc17f68 100644 --- a/highLighter.hh +++ b/highLighter.hh @@ -55,9 +55,10 @@ class Highlighter : public QSyntaxHighlighter Q_OBJECT public: - Highlighter(QTextEdit *parent = 0); + Highlighter( QTextDocument* parent = 0); + Highlighter( QTextEdit* parent = 0); - // Updates the highlighter with the current rule set defined in the patterns + /// Updates the highlighter with the current rule set defined in the patterns void update(); QStringList keywordPatterns_; @@ -70,6 +71,8 @@ class Highlighter : public QSyntaxHighlighter void highlightBlock(const QString &text); private: + /// common initializer function called by the constructors + void init(); struct HighlightingRule { diff --git a/scriptingWidget.ui b/scriptingWidget.ui index d2fa033623912c1b2b42def69141010b040f9002..e8466ac9fa25b08ec46c526f6d11884eb086fcde 100644 --- a/scriptingWidget.ui +++ b/scriptingWidget.ui @@ -26,7 +26,7 @@ </property> <layout class="QVBoxLayout"> <item> - <widget class="QTextEdit" name="currentScript"> + <widget class="CodeEditorWidget" name="currentScript"> <property name="enabled"> <bool>true</bool> </property> @@ -176,6 +176,11 @@ <extends>QListWidget</extends> <header>FunctionList.hh</header> </customwidget> + <customwidget> + <class>CodeEditorWidget</class> + <extends>QTextEdit</extends> + <header>codeeditor.hh</header> + </customwidget> </customwidgets> <resources/> <connections>