diff --git a/limereport/items/lrtextitemeditor.cpp b/limereport/items/lrtextitemeditor.cpp
index 76e6891..f46333d 100644
--- a/limereport/items/lrtextitemeditor.cpp
+++ b/limereport/items/lrtextitemeditor.cpp
@@ -33,7 +33,6 @@
 #include "lrdatasourcemanager.h"
 #include "lrscriptenginemanager.h"
 #include "lrdatadesignintf.h"
-#include "lrdatasourcemanager.h"
 
 #include <QMenu>
 #include <QScrollBar>
diff --git a/limereport/limereport.pri b/limereport/limereport.pri
index 69af57f..385ad4d 100644
--- a/limereport/limereport.pri
+++ b/limereport/limereport.pri
@@ -12,7 +12,8 @@ INCLUDEPATH += \
     $$REPORT_PATH/bands \
     $$REPORT_PATH/base \
     $$REPORT_PATH/objectinspector \
-    $$REPORT_PATH/databrowser
+    $$REPORT_PATH/databrowser \
+    $$REPORT_PATH/scripteditor
 
 SOURCES += \
     $$REPORT_PATH/bands/lrpageheader.cpp \
@@ -59,6 +60,9 @@ SOURCES += \
     $$REPORT_PATH/objectinspector/lrpropertydelegate.cpp \
     $$REPORT_PATH/objectsbrowser/lrobjectbrowser.cpp \   
     $$REPORT_PATH/scriptbrowser/lrscriptbrowser.cpp \
+    $$REPORT_PATH/scripteditor/lrscripteditor.cpp \
+    $$REPORT_PATH/scripteditor/lrcodeeditor.cpp \
+    $$REPORT_PATH/scripteditor/lrscripthighlighter.cpp \
     $$REPORT_PATH/items/lrsubitemparentpropitem.cpp \
     $$REPORT_PATH/items/lralignpropitem.cpp \
     $$REPORT_PATH/items/lrhorizontallayout.cpp \
@@ -161,6 +165,9 @@ HEADERS += \
     $$REPORT_PATH/objectinspector/lrpropertydelegate.h \
     $$REPORT_PATH/objectsbrowser/lrobjectbrowser.h \
     $$REPORT_PATH/scriptbrowser/lrscriptbrowser.h \
+    $$REPORT_PATH/scripteditor/lrscripteditor.h \
+    $$REPORT_PATH/scripteditor/lrcodeeditor.h \
+    $$REPORT_PATH/scripteditor/lrscripthighlighter.h \
     $$REPORT_PATH/items/editors/lritemeditorwidget.h \
     $$REPORT_PATH/items/editors/lrfonteditorwidget.h \
     $$REPORT_PATH/items/editors/lrtextalignmenteditorwidget.h \
@@ -235,7 +242,8 @@ FORMS += \
     $$REPORT_PATH/scriptbrowser/lrscriptbrowser.ui \
     $$REPORT_PATH/items/lrchartitemeditor.ui \
     $$REPORT_PATH/translationeditor/translationeditor.ui \
-    $$PWD/translationeditor/languageselectdialog.ui
+    $$REPORT_PATH/translationeditor/languageselectdialog.ui \
+    $$REPORT_PATH/scripteditor/lrscripteditor.ui
 
 RESOURCES += \
     $$REPORT_PATH/objectinspector/lobjectinspector.qrc \
diff --git a/limereport/lrreportdesignwidget.cpp b/limereport/lrreportdesignwidget.cpp
index 9472f13..0145940 100644
--- a/limereport/lrreportdesignwidget.cpp
+++ b/limereport/lrreportdesignwidget.cpp
@@ -35,6 +35,7 @@
 #include "lrsettingdialog.h"
 #include "dialogdesigner/lrdialogdesigner.h"
 #include "translationeditor/translationeditor.h"
+#include "scripteditor/lrscripteditor.h"
 
 #include <QDebug>
 #include <QObject>
@@ -183,6 +184,7 @@ void ReportDesignWidget::saveState(QSettings* settings)
     settings->setValue("vGridStep",m_verticalGridStep);
     settings->setValue("defaultFont",m_defaultFont);
     settings->setValue("useGrid",m_useGrid);
+    settings->setValue("ScriptEditorState", m_scriptEditor->saveState());
     settings->endGroup();
 }
 
@@ -215,6 +217,12 @@ void ReportDesignWidget::loadState(QSettings* settings)
     if (v.isValid()){
         m_useGrid = v.toBool();
     }
+
+    v = settings->value("ScriptEditorState");
+    if (v.isValid()){
+        m_scriptEditor->restoreState(v.toByteArray());
+    }
+
     settings->endGroup();
     applySettings();
 }
@@ -241,7 +249,8 @@ void ReportDesignWidget::createTabs(){
                 this, SLOT(slotPagePropertyObjectNameChanged(QString,QString)));
     }
 
-    m_scriptEditor = new QTextEdit(this);
+    m_scriptEditor = new ScriptEditor(this);
+    m_scriptEditor->setReportEngine(m_report);
     pageIndex = m_tabWidget->addTab(m_scriptEditor,QIcon(),tr("Script"));
     m_tabWidget->setTabWhatsThis(pageIndex,"script");
     m_tabWidget->setCurrentIndex(0);
@@ -435,9 +444,11 @@ bool ReportDesignWidget::save()
 bool ReportDesignWidget::loadFromFile(const QString &fileName)
 {
     if (m_report->loadFromFile(fileName,false)){
+        QByteArray editorState = m_scriptEditor->saveState();
         createTabs();
         //connectPage(m_report->pageAt(0));
         m_scriptEditor->setPlainText(m_report->scriptContext()->initScript());
+        m_scriptEditor->restoreState(editorState);
         emit loaded();
         m_dialogChanged = false;
         return true;
@@ -787,6 +798,12 @@ void ReportDesignWidget::slotCurrentTabChanged(int index)
     if (activeTabType() == Translations){
         m_traslationEditor->setReportEngine(report());
     }
+
+    if (activeTabType() == Script){
+        m_scriptEditor->initCompleter();
+        m_scriptEditor->setFocus();
+    }
+
     emit activePageChanged();
 }
 
diff --git a/limereport/lrreportdesignwidget.h b/limereport/lrreportdesignwidget.h
index 4d3b25d..b7e38b7 100644
--- a/limereport/lrreportdesignwidget.h
+++ b/limereport/lrreportdesignwidget.h
@@ -51,6 +51,8 @@ class ReportDesignWindow;
 class DialogDesignerManager;
 class DialogDesigner;
 class TranslationEditor;
+class ScriptEditor;
+
 
 class ReportDesignWidget : public QWidget
 {
@@ -189,7 +191,7 @@ private:
 private:
     ReportEnginePrivate* m_report;
     QGraphicsView *m_view;
-    QTextEdit* m_scriptEditor;
+    ScriptEditor* m_scriptEditor;
     TranslationEditor* m_traslationEditor;
 #ifdef HAVE_QTDESIGNER_INTEGRATION
     DialogDesignerManager* m_dialogDesignerManager;
@@ -205,5 +207,5 @@ private:
     bool m_dialogChanged;
 };
 
-}
+} // namespace LimeReport
 #endif // LRREPORTDESIGNWIDGET_H
diff --git a/limereport/lrreportdesignwindow.cpp b/limereport/lrreportdesignwindow.cpp
index 0bdae75..1ad41c7 100644
--- a/limereport/lrreportdesignwindow.cpp
+++ b/limereport/lrreportdesignwindow.cpp
@@ -664,14 +664,21 @@ void ReportDesignWindow::writeState()
 {
     settings()->beginGroup("DesignerWindow");
     switch (m_editorTabType) {
-    case ReportDesignWidget::Page:
-        settings()->setValue("PageEditorsState", saveState());
-        settings()->setValue("DialogEditorsState", m_dialogEditorsState);
-        break;
-    default:
-        settings()->setValue("DialogEditorsState", saveState());
-        settings()->setValue("PageEditorsState", m_pageEditorsState);
-        break;
+        case ReportDesignWidget::Page:
+            settings()->setValue("PageEditorsState", saveState());
+            settings()->setValue("DialogEditorsState", m_dialogEditorsState);
+            settings()->setValue("ScriptEditorsState", m_scriptEditorState);
+            break;
+        case ReportDesignWidget::Script:
+            settings()->setValue("ScriptEditorsState", saveState());
+            settings()->setValue("DialogEditorsState", m_dialogEditorsState);
+            settings()->setValue("PageEditorsState", m_pageEditorsState);
+            break;
+        default:
+            settings()->setValue("DialogEditorsState", saveState());
+            settings()->setValue("PageEditorsState", m_pageEditorsState);
+            settings()->setValue("ScriptEditorsState", m_scriptEditorState);
+            break;
     }
     settings()->setValue("InspectorFirsColumnWidth",m_objectInspector->columnWidth(0));
     settings()->endGroup();
@@ -775,6 +782,10 @@ void ReportDesignWindow::restoreSetting()
     if (v.isValid()){
         m_dialogEditorsState = v.toByteArray();
     }
+    v = settings()->value("ScriptEditorsState");
+    if (v.isValid()){
+        m_scriptEditorState = v.toByteArray();
+    }
     v = settings()->value("InspectorFirsColumnWidth");
     if (v.isValid()){
         m_objectInspector->setColumnWidth(0,v.toInt());
@@ -1277,12 +1288,15 @@ void ReportDesignWindow::slotActivePageChanged()
     updateAvaibleBands();
 
     switch (m_editorTabType) {
-    case ReportDesignWidget::Dialog:
-        m_dialogEditorsState = saveState();
+        case ReportDesignWidget::Dialog:
+            m_dialogEditorsState = saveState();
 #ifdef HAVE_UI_LOADER
-        m_scriptBrowser->updateDialogsTree();
+            m_scriptBrowser->updateDialogsTree();
 #endif
-        break;
+            break;
+        case ReportDesignWidget::Script:
+            m_scriptEditorState = saveState();
+            break;
     default:
         m_pageEditorsState = saveState();
         break;
@@ -1291,20 +1305,30 @@ void ReportDesignWindow::slotActivePageChanged()
     m_editorTabType = m_reportDesignWidget->activeTabType();
 
     switch (m_editorTabType) {
-    case ReportDesignWidget::Dialog:
-        if (!m_dialogEditorsState.isEmpty())
-            restoreState(m_dialogEditorsState);
-        else
-            showDefaultEditors();
-            showDefaultToolBars();
-        break;
-    default:
-        if (!m_pageEditors.isEmpty())
-            restoreState(m_pageEditorsState);
-        else
-            showDefaultEditors();
-            showDefaultToolBars();
-        break;
+        case ReportDesignWidget::Dialog:
+            if (!m_dialogEditorsState.isEmpty()){
+                restoreState(m_dialogEditorsState);
+            } else {
+                showDefaultEditors();
+                showDefaultToolBars();
+            }
+            break;
+        case ReportDesignWidget::Script:
+            if (!m_scriptEditorState.isEmpty()){
+                restoreState(m_scriptEditorState);
+            } else {
+                showDefaultEditors();
+                showDefaultToolBars();
+            }
+            break;
+        default:
+            if (!m_pageEditors.isEmpty()){
+                restoreState(m_pageEditorsState);
+            } else {
+                showDefaultEditors();
+                showDefaultToolBars();
+            }
+            break;
     }
 
 }
diff --git a/limereport/lrreportdesignwindow.h b/limereport/lrreportdesignwindow.h
index 94c4bd5..1779ed3 100644
--- a/limereport/lrreportdesignwindow.h
+++ b/limereport/lrreportdesignwindow.h
@@ -264,6 +264,7 @@ private:
     ReportDesignWidget::EditorTabType m_editorTabType;
     QByteArray m_pageEditorsState;
     QByteArray m_dialogEditorsState;
+    QByteArray m_scriptEditorState;
     QVector<QToolBar*> m_pageTools;
     QVector<QToolBar*> m_dialogTools;
 
diff --git a/limereport/scripteditor/lrcodeeditor.cpp b/limereport/scripteditor/lrcodeeditor.cpp
new file mode 100644
index 0000000..273a1b3
--- /dev/null
+++ b/limereport/scripteditor/lrcodeeditor.cpp
@@ -0,0 +1,322 @@
+#include "lrcodeeditor.h"
+
+#include <QAbstractItemView>
+#include <QWidget>
+#include <QCompleter>
+#include <QKeyEvent>
+#include <QScrollBar>
+#include <QPainter>
+#include <QTextBlock>
+#include <QDebug>
+
+#include "lrscripthighlighter.h"
+
+namespace LimeReport{
+
+CodeEditor::CodeEditor(QWidget *parent)
+    : QPlainTextEdit(parent), m_compleater(0)
+{
+    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();
+    new ScriptHighlighter(document());
+    connect(this, SIGNAL(cursorPositionChanged()),
+            this, SLOT(matchParentheses()));
+}
+
+void CodeEditor::setCompleter(QCompleter *value)
+{
+    if (value) disconnect(value,0,this,0);
+    m_compleater = value;
+    if (!m_compleater) return;
+    m_compleater->setWidget(this);
+    m_compleater->setCompletionMode(QCompleter::PopupCompletion);
+    m_compleater->setCaseSensitivity(Qt::CaseInsensitive);
+    connect(m_compleater,SIGNAL(activated(QString)),this,SLOT(insertCompletion(QString)));
+}
+
+void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent* event)
+{
+    QPainter painter(lineNumberArea);
+    painter.fillRect(event->rect(), QPalette().background().color());
+
+    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(QPalette().text().color());
+            painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
+                             Qt::AlignCenter, number);
+        }
+
+        block = block.next();
+        top = bottom;
+        bottom = top + (int) blockBoundingRect(block).height();
+        ++blockNumber;
+    }
+}
+
+int CodeEditor::lineNumberAreaWidth()
+{
+    int digits = 1;
+    int max = qMax(1, blockCount());
+    while (max >= 10) {
+        max /= 10;
+        ++digits;
+    }
+
+    int space = fontMetrics().width(QLatin1Char('9'))*2 + fontMetrics().width(QLatin1Char('9')) * digits;
+
+    return space;
+}
+
+void CodeEditor::keyPressEvent(QKeyEvent *e)
+{
+    if (m_compleater && m_compleater->popup()->isVisible()) {
+        switch (e->key()) {
+        case Qt::Key_Enter:
+        case Qt::Key_Return:
+        case Qt::Key_Escape:
+        case Qt::Key_Tab:
+        case Qt::Key_Backtab:
+            e->ignore();
+            return;
+        default:
+            break;
+        }
+    }
+
+    bool isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_Space);
+    if (!m_compleater || !isShortcut) QPlainTextEdit::keyPressEvent(e);
+
+    const bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
+    if (!m_compleater || (ctrlOrShift && e->text().isEmpty()))
+        return;
+
+    static QString eow("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word
+    bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift;
+
+    QString completionPrefix = textUnderCursor();
+
+    if (!isShortcut && (hasModifier || e->text().isEmpty()|| completionPrefix.length() < 3
+                        || eow.contains(e->text().right(1)))) {
+        m_compleater->popup()->hide();
+        return;
+    }
+
+    if (completionPrefix != m_compleater->completionPrefix()) {
+        m_compleater->setCompletionPrefix(completionPrefix);
+        m_compleater->popup()->setCurrentIndex(m_compleater->completionModel()->index(0, 0));
+    }
+
+    QRect cr = cursorRect();
+    cr.setWidth(m_compleater->popup()->sizeHintForColumn(0)
+                + m_compleater->popup()->verticalScrollBar()->sizeHint().width());
+    m_compleater->complete(cr);
+
+}
+
+void CodeEditor::focusInEvent(QFocusEvent *e)
+{
+    if (m_compleater) m_compleater->setWidget(this);
+    QPlainTextEdit::focusInEvent(e);
+}
+
+void CodeEditor::resizeEvent(QResizeEvent* event)
+{
+    QPlainTextEdit::resizeEvent(event);
+    QRect cr = contentsRect();
+    lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
+}
+
+QString CodeEditor::textUnderCursor() const
+{
+    QTextCursor tc = textCursor();
+    tc.select(QTextCursor::WordUnderCursor);
+    return tc.selectedText();
+}
+
+bool CodeEditor::matchLeftParenthesis(QTextBlock currentBlock, QChar parenthesisType, int i, int numLeftParentheses)
+{
+    TextBlockData *data = static_cast<TextBlockData *>(currentBlock.userData());
+    QVector<ParenthesisInfo *> infos = data->parentheses();
+
+    int docPos = currentBlock.position();
+    for (; i < infos.size(); ++i) {
+        ParenthesisInfo *info = infos.at(i);
+
+        if (info->character == parenthesisType) {
+            ++numLeftParentheses;
+            continue;
+        }
+
+        if (info->character == getParenthesisReverceChar(parenthesisType)){
+            if (numLeftParentheses == 0) {
+                createParenthesisSelection(docPos + info->position);
+                return true;
+            } else
+                --numLeftParentheses;
+        }
+
+    }
+
+    currentBlock = currentBlock.next();
+    if (currentBlock.isValid())
+        return matchLeftParenthesis(currentBlock, parenthesisType, 0, numLeftParentheses);
+
+    return false;
+}
+
+bool CodeEditor::matchRightParenthesis(QTextBlock currentBlock, QChar parenthesisType, int i, int numRightParentheses)
+{
+    TextBlockData *data = static_cast<TextBlockData *>(currentBlock.userData());
+    QVector<ParenthesisInfo *> parentheses = data->parentheses();
+
+    int docPos = currentBlock.position();
+    for (; i > -1 && parentheses.size() > 0; --i) {
+        ParenthesisInfo *info = parentheses.at(i);
+        if (info->character == parenthesisType) {
+            ++numRightParentheses;
+            continue;
+        }
+        if (info->character == getParenthesisReverceChar(parenthesisType)){
+            if (numRightParentheses == 0) {
+                createParenthesisSelection(docPos + info->position);
+                return true;
+            } else
+                --numRightParentheses;
+        }
+    }
+
+    currentBlock = currentBlock.previous();
+    if (currentBlock.isValid())
+        return matchRightParenthesis(currentBlock, parenthesisType, 0, numRightParentheses);
+
+    return false;
+}
+
+void CodeEditor::createParenthesisSelection(int pos)
+{
+    QList<QTextEdit::ExtraSelection> selections = extraSelections();
+
+    QTextEdit::ExtraSelection selection;
+    QTextCharFormat format = selection.format;
+    format.setBackground(QColor("#619934"));
+    format.setForeground(QColor("#ffffff"));
+    selection.format = format;
+
+    QTextCursor cursor = textCursor();
+    cursor.setPosition(pos);
+    cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+    selection.cursor = cursor;
+
+    selections.append(selection);
+
+    setExtraSelections(selections);
+}
+
+bool CodeEditor::charIsParenthesis(QChar character, ParenthesisType type)
+{
+    for (int i = 0; i < PARENHEIS_COUNT; ++i){
+        if (character == parenthesisCharacters[type][i])
+            return true;
+    }
+    return false;
+}
+
+QChar CodeEditor::getParenthesisReverceChar(QChar parenthesisChar)
+{
+    for (int i = 0; i < PARENHEIS_COUNT; ++i){
+        if ( parenthesisCharacters[RightParenthesis][i] == parenthesisChar)
+            return parenthesisCharacters[LeftParenthesis][i];
+        if ( parenthesisCharacters[LeftParenthesis][i] == parenthesisChar)
+            return parenthesisCharacters[RightParenthesis][i];
+    }
+    return ' ';
+}
+
+void CodeEditor::insertCompletion(const QString &completion)
+{
+    if (m_compleater->widget() != this)
+             return;
+    QTextCursor tc = textCursor();
+    int extra = completion.length() - m_compleater->completionPrefix().length();
+    tc.movePosition(QTextCursor::Left);
+    tc.movePosition(QTextCursor::EndOfWord);
+    tc.insertText(completion.right(extra));
+    setTextCursor(tc);
+}
+
+void CodeEditor::updateLineNumberAreaWidth(int /*newBlockCount*/)
+{
+    setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
+}
+
+void CodeEditor::highlightCurrentLine()
+{
+    QList<QTextEdit::ExtraSelection> extraSelections;
+
+    if (!isReadOnly()) {
+        QTextEdit::ExtraSelection selection;
+
+        QColor lineColor = QColor(QPalette().background().color()).darker(100);
+
+        selection.format.setBackground(lineColor);
+        selection.format.setProperty(QTextFormat::FullWidthSelection, true);
+        selection.cursor = textCursor();
+        selection.cursor.clearSelection();
+        extraSelections.append(selection);
+    }
+
+    setExtraSelections(extraSelections);
+}
+
+void CodeEditor::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 CodeEditor::matchParentheses()
+{
+    QList<QTextEdit::ExtraSelection> selections;
+    setExtraSelections(selections);
+
+    TextBlockData *data = static_cast<TextBlockData *>(textCursor().block().userData());
+
+    if (data) {
+        QVector<ParenthesisInfo *> infos = data->parentheses();
+
+        int pos = textCursor().block().position();
+        for (int i = 0; i < infos.size(); ++i) {
+            ParenthesisInfo *info = infos.at(i);
+
+            int curPos = textCursor().position() - textCursor().block().position();
+
+            if ( (info->position == (curPos - 1)) && charIsParenthesis(info->character, LeftParenthesis))
+            {
+                if (matchLeftParenthesis(textCursor().block(), info->character, i + 1, 0))
+                    createParenthesisSelection(pos + info->position);
+            } else if ( (info->position == (curPos - 1)) && charIsParenthesis(info->character, RightParenthesis)) {
+                if (matchRightParenthesis(textCursor().block(), info->character, i - 1, 0))
+                    createParenthesisSelection(pos + info->position);
+            }
+         }
+    }
+}
+
+} //namespace LimeReport
diff --git a/limereport/scripteditor/lrcodeeditor.h b/limereport/scripteditor/lrcodeeditor.h
new file mode 100644
index 0000000..851583f
--- /dev/null
+++ b/limereport/scripteditor/lrcodeeditor.h
@@ -0,0 +1,71 @@
+#ifndef LRCODEEDITOR_H
+#define LRCODEEDITOR_H
+
+#include <QPlainTextEdit>
+#include <QSyntaxHighlighter>
+#include "lrscripthighlighter.h"
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+class QCompleter;
+class QKeyEvent;
+class QScrollBar;
+QT_END_NAMESPACE
+
+namespace LimeReport{
+
+class CodeEditor :public QPlainTextEdit
+{
+    Q_OBJECT
+public:
+    CodeEditor(QWidget* parent=0);
+    void setCompleter(QCompleter* value);
+    QCompleter* compleater() const{ return m_compleater;}
+    void lineNumberAreaPaintEvent(QPaintEvent *event);
+    int lineNumberAreaWidth();
+protected:
+    void keyPressEvent(QKeyEvent *e);
+    void focusInEvent(QFocusEvent *e);
+    void resizeEvent(QResizeEvent *event);
+private:
+    QString textUnderCursor() const;
+    bool    matchLeftParenthesis(QTextBlock currentBlock, QChar parenthesisType, int i, int numLeftParentheses);
+    bool    matchRightParenthesis(QTextBlock currentBlock, QChar parenthesisType, int i, int numRightParentheses);
+    void    createParenthesisSelection(int pos);
+    bool    charIsParenthesis(QChar character, ParenthesisType type);
+    QChar   getParenthesisReverceChar(QChar parenthesisChar);
+private slots:
+    void insertCompletion(const QString& completion);
+    void updateLineNumberAreaWidth(int newBlockCount);
+    void highlightCurrentLine();
+    void updateLineNumberArea(const QRect &rect, int dy);
+    void matchParentheses();
+private:
+    QCompleter* m_compleater;
+    QWidget *lineNumberArea;
+};
+
+
+class LineNumberArea : public QWidget
+{
+public:
+    LineNumberArea(CodeEditor *editor) : QWidget(editor) {
+        codeEditor = editor;
+    }
+
+    QSize sizeHint() const {
+        return QSize(codeEditor->lineNumberAreaWidth(), 0);
+    }
+
+protected:
+    void paintEvent(QPaintEvent *event) {
+        codeEditor->lineNumberAreaPaintEvent(event);
+    }
+
+private:
+    CodeEditor *codeEditor;
+};
+
+} // namespace LimeReport
+
+#endif // LRCODEEDITOR_H
diff --git a/limereport/scripteditor/lrscripteditor.cpp b/limereport/scripteditor/lrscripteditor.cpp
new file mode 100644
index 0000000..461a8f9
--- /dev/null
+++ b/limereport/scripteditor/lrscripteditor.cpp
@@ -0,0 +1,150 @@
+#include "lrscripteditor.h"
+#include "ui_lrscripteditor.h"
+#include <QJSValueIterator>
+
+#include "lrdatasourcemanager.h"
+#include "lrscriptenginemanager.h"
+#include "lrdatadesignintf.h"
+#include "lrreportengine_p.h"
+
+namespace LimeReport{
+
+ScriptEditor::ScriptEditor(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::ScriptEditor)
+{
+    ui->setupUi(this);
+    setFocusProxy(ui->textEdit);
+    m_completer = new QCompleter(this);
+    ui->textEdit->setCompleter(m_completer);
+}
+
+ScriptEditor::~ScriptEditor()
+{
+    delete ui;
+}
+
+void ScriptEditor::setReportEngine(ReportEnginePrivate* reportEngine)
+{
+    m_reportEngine = reportEngine;
+    DataSourceManager* dm = m_reportEngine->dataManager();
+    ScriptEngineManager& se = LimeReport::ScriptEngineManager::instance();
+    se.setDataManager(dm);
+
+    initCompleter();
+
+    if (dm){
+        if (dm->isNeedUpdateDatasourceModel())
+           dm->updateDatasourceModel();
+        ui->twData->setModel(dm->datasourcesModel());
+        ui->twScriptEngine->setModel(se.model());
+    }
+
+}
+
+void ScriptEditor::initCompleter()
+{
+    QStringList dataWords;
+    DataSourceManager* dm = m_reportEngine->dataManager();
+    ScriptEngineManager& se = LimeReport::ScriptEngineManager::instance();
+
+    QJSValue globalObject = se.scriptEngine()->globalObject();
+    QJSValueIterator it(globalObject);
+    while (it.hasNext()){
+        it.next();
+        if (it.value().isCallable() ){
+            dataWords << it.name();
+        }
+    }
+
+    foreach(const QString &dsName,dm->dataSourceNames()){
+        dataWords << dsName;
+        foreach(const QString &field, dm->fieldNames(dsName)){
+            dataWords<<dsName+"."+field;
+        }
+    }
+
+    foreach (QString varName, dm->variableNames()) {
+        dataWords << varName.remove("#");
+    }
+
+    for ( int i = 0; i < m_reportEngine->pageCount(); ++i){
+        PageDesignIntf* page = m_reportEngine->pageAt(i);
+        dataWords << page->pageItem()->objectName();
+        foreach (BaseDesignIntf* item, page->pageItem()->childBaseItems()){
+            addItemToCompleater(page->pageItem()->objectName(), item, dataWords);
+        }
+    }
+
+    m_completer->setModel(new QStringListModel(dataWords,m_completer));
+}
+
+QByteArray ScriptEditor::saveState()
+{
+    return ui->splitter->saveState();
+}
+
+void ScriptEditor::restoreState(QByteArray state)
+{
+    ui->splitter->restoreState(state);
+}
+
+void ScriptEditor::setPlainText(const QString& text)
+{
+    ui->textEdit->setPlainText(text);
+}
+
+QString ScriptEditor::toPlainText()
+{
+    return ui->textEdit->toPlainText();
+}
+
+void ScriptEditor::addItemToCompleater(const QString& pageName, BaseDesignIntf* item, QStringList& dataWords)
+{
+    BandDesignIntf* band = dynamic_cast<BandDesignIntf*>(item);
+    if (band){
+        dataWords << band->objectName();
+        dataWords << pageName+"_"+band->objectName();
+        dataWords << pageName+"_"+band->objectName()+".beforeRender";
+        dataWords << pageName+"_"+item->objectName()+".afterData";
+        dataWords << pageName+"_"+band->objectName()+".afterRender";
+        foreach (BaseDesignIntf* child, band->childBaseItems()){
+            addItemToCompleater(pageName, child, dataWords);
+        }
+    } else {
+        dataWords << item->objectName();
+        dataWords << pageName+"_"+item->objectName();
+        dataWords << pageName+"_"+item->objectName()+".beforeRender";
+        dataWords << pageName+"_"+item->objectName()+".afterData";
+        dataWords << pageName+"_"+item->objectName()+".afterRender";
+    }
+}
+
+void ScriptEditor::on_twData_doubleClicked(const QModelIndex &index)
+{
+    if (!index.isValid()) return;
+    LimeReport::DataNode* node = static_cast<LimeReport::DataNode*>(index.internalPointer());
+    if (node->type()==LimeReport::DataNode::Field){
+        ui->textEdit->insertPlainText(QString("$D{%1.%2}").arg(node->parent()->name()).arg(node->name()));
+    }
+    if (node->type()==LimeReport::DataNode::Variable){
+        ui->textEdit->insertPlainText(QString("$V{%1}").arg(node->name()));
+    }
+    ui->textEdit->setFocus();
+}
+
+void ScriptEditor::on_twScriptEngine_doubleClicked(const QModelIndex &index)
+{
+    if (!index.isValid()) return;
+    LimeReport::ScriptEngineNode* node = static_cast<LimeReport::ScriptEngineNode*>(index.internalPointer());
+    if (node->type()==LimeReport::ScriptEngineNode::Function){
+        ui->textEdit->insertPlainText(node->name()+"()");
+    }
+    ui->textEdit->setFocus();
+}
+
+} // namespace LimeReport
+
+
+
+
diff --git a/limereport/scripteditor/lrscripteditor.h b/limereport/scripteditor/lrscripteditor.h
new file mode 100644
index 0000000..eedb66d
--- /dev/null
+++ b/limereport/scripteditor/lrscripteditor.h
@@ -0,0 +1,47 @@
+#ifndef LRSCRIPTEDITOR_H
+#define LRSCRIPTEDITOR_H
+
+#include <QWidget>
+#include <QCompleter>
+#include <QTextEdit>
+#include <QKeyEvent>
+#include <QScrollBar>
+
+namespace LimeReport{
+
+class ReportEnginePrivate;
+class BaseDesignIntf;
+
+namespace Ui {
+class ScriptEditor;
+}
+
+class ScriptEditor : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit ScriptEditor(QWidget *parent = 0);
+    ~ScriptEditor();
+    void setReportEngine(ReportEnginePrivate* reportEngine);
+    void initCompleter();
+    QByteArray saveState();
+    void restoreState(QByteArray state);
+    void setPlainText(const QString &text);
+    QString toPlainText();
+private slots:
+    void on_twData_doubleClicked(const QModelIndex &index);
+
+    void on_twScriptEngine_doubleClicked(const QModelIndex &index);
+
+private:
+    void addItemToCompleater(const QString& pageName, BaseDesignIntf* item, QStringList& dataWords);
+private:
+    Ui::ScriptEditor *ui;
+    ReportEnginePrivate* m_reportEngine;
+    QCompleter* m_completer;
+
+};
+
+} // namespace LimeReport
+
+#endif // LRSCRIPTEDITOR_H
diff --git a/limereport/scripteditor/lrscripteditor.ui b/limereport/scripteditor/lrscripteditor.ui
new file mode 100644
index 0000000..27f8e7f
--- /dev/null
+++ b/limereport/scripteditor/lrscripteditor.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LimeReport::ScriptEditor</class>
+ <widget class="QWidget" name="LimeReport::ScriptEditor">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>706</width>
+    <height>541</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QSplitter" name="splitter">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <widget class="LimeReport::CodeEditor" name="textEdit">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="font">
+       <font>
+        <pointsize>12</pointsize>
+       </font>
+      </property>
+     </widget>
+     <widget class="QTabWidget" name="tabWidget">
+      <property name="tabPosition">
+       <enum>QTabWidget::South</enum>
+      </property>
+      <property name="currentIndex">
+       <number>0</number>
+      </property>
+      <widget class="QWidget" name="tab">
+       <attribute name="title">
+        <string>Data</string>
+       </attribute>
+       <layout class="QVBoxLayout" name="verticalLayout_3">
+        <property name="spacing">
+         <number>3</number>
+        </property>
+        <property name="leftMargin">
+         <number>3</number>
+        </property>
+        <property name="topMargin">
+         <number>3</number>
+        </property>
+        <property name="rightMargin">
+         <number>3</number>
+        </property>
+        <property name="bottomMargin">
+         <number>3</number>
+        </property>
+        <item>
+         <widget class="QTreeView" name="twData">
+          <attribute name="headerVisible">
+           <bool>false</bool>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QWidget" name="tab_2">
+       <attribute name="title">
+        <string>Functions</string>
+       </attribute>
+       <layout class="QVBoxLayout" name="verticalLayout_4">
+        <item>
+         <widget class="QSplitter" name="splitter_2">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <widget class="QTreeView" name="twScriptEngine">
+           <attribute name="headerVisible">
+            <bool>false</bool>
+           </attribute>
+          </widget>
+          <widget class="QLabel" name="lblDescription">
+           <property name="text">
+            <string/>
+           </property>
+          </widget>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>LimeReport::CodeEditor</class>
+   <extends>QTextEdit</extends>
+   <header>lrcodeeditor.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/limereport/scripteditor/lrscripthighlighter.cpp b/limereport/scripteditor/lrscripthighlighter.cpp
new file mode 100644
index 0000000..d88e18f
--- /dev/null
+++ b/limereport/scripteditor/lrscripthighlighter.cpp
@@ -0,0 +1,226 @@
+#include "lrscripthighlighter.h"
+#include <QDebug>
+#include <QPalette>
+
+namespace LimeReport{
+
+#define KEYWORDS_COUNT 59
+
+static const char *const keywords[KEYWORDS_COUNT] = {
+    "do","if","in","for","int","new","try","var","byte","case","char","else","enum",
+    "goto","long","null","this","true","void","with","break","catch","class","const",
+    "false","final","float","short","super","throw","while","delete","double","export",
+    "import","native","public","return","static","switch","throws","typeof","boolean",
+    "default","extends","finally","package","private","abstract","continue","debugger",
+    "function","volatile","interface","protected","transient","implements","instanceof",
+    "synchronized"
+};
+
+enum LiteralsType{SpaceFound, AlpahabetFound, NumberFound, HashFound, SlashFound, AsterixFound,
+                 BracketFound, QuotationFound, ApostropheFound, SeparatorFound, BackSlashFound, LiteralsCount};
+enum States {Start, MayBeKeyWord, Code, MayBeComment, Comment, Comment2, MayBeComment2End, String, String2, MayBeNumber, Separator, StatesCount};
+
+void ScriptHighlighter::createParentheisisInfo(const char& literal, TextBlockData *data, const QString& text)
+{
+    int pos = text.indexOf(literal);
+    while (pos != -1) {
+        ParenthesisInfo *info = new ParenthesisInfo;
+        info->character = literal;
+        info->position = pos;
+        data->insert(info);
+        pos = text.indexOf(literal, pos + 1);
+    }
+}
+
+void ScriptHighlighter::highlightBlock(const QString& text)
+{
+    int literal = -1;
+    bool lastWasBackSlash = false;
+    int state = previousBlockState() != -1 ? previousBlockState() : Start ;
+    int oldState = -1;
+    int stateMaschine[StatesCount][LiteralsCount] = {
+        {Separator, MayBeKeyWord, MayBeNumber, Separator, MayBeComment, Separator, Separator, String, String2, Separator, Separator},
+        {Separator, MayBeKeyWord, Code, Separator, MayBeComment, Separator, Separator, String, String2, Separator, Separator},
+        {Separator, Code, Code, Separator, Separator, Separator, Separator, String, String2, Separator, Separator},
+        {Separator, Code, MayBeNumber, Code, Comment, Comment2, Code, String, String2, Separator, Code},
+        {Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment},
+        {Comment2, Comment2, Comment2, Comment2, Comment2, MayBeComment2End, Comment2, Comment2, Comment2, Comment2, Comment2},
+        {Comment2, Comment2, Comment2, Comment2, Separator, Comment2, Comment2, Comment2, Comment2, Comment2, Comment2},
+        {String, String, String, String, String, String, String, Separator, String, String, String},
+        {String2, String2, String2, String2, String2, String2, String2, String2, Separator, String2, String2},
+        {Separator, Code, MayBeNumber, Separator, MayBeComment, Separator, Separator, String, String2, Separator, Code},
+        {Separator, MayBeKeyWord, MayBeNumber, Separator, MayBeComment, Separator, Separator, String, String2, Separator, Separator }
+    };
+
+    QString buffer;
+
+    if (text.isEmpty()) return;
+    int i = 0;
+    for (;;){
+        QChar currentChar = text.at(i);
+        switch(currentChar.toLatin1()){
+            case ' ':
+                literal = SpaceFound;
+                break;
+            case '/':
+                literal = SlashFound;
+                break;
+            case '*':
+                literal = AsterixFound;
+                break;
+            case '#':
+                literal = HashFound;
+                break;
+            case '\'':
+                literal = ApostropheFound;
+                break;
+            case '\\':
+                literal = BackSlashFound;
+                break;
+            case '"':
+                literal = QuotationFound;
+                break;
+            case '{': case '[': case '(':
+            case '}': case ']': case ')':
+                literal = BracketFound;
+                break;
+            case '1': case '2': case '3': case '4': case '5':
+            case '6': case '7': case '8': case '9': case '0':
+                literal = NumberFound;
+                break;
+            default:
+                if (currentChar.isLetter())
+                    literal = AlpahabetFound;
+                else
+                    literal = SeparatorFound;
+        };
+
+        lastWasBackSlash = !lastWasBackSlash && currentChar == QLatin1Char('\\');
+
+        oldState = state;
+        state = stateMaschine[state][literal];
+
+        buffer += currentChar;
+
+        if (oldState != state){
+            switch( state ){
+                case MayBeComment:
+                    if (oldState == MayBeNumber){
+                        setFormat(i-(buffer.length()-1), buffer.length()-1, m_formats[NumberFormat]);
+                    }
+                    buffer.clear();
+                    buffer += currentChar;
+
+                    break;
+                case MayBeKeyWord:
+                case MayBeNumber:
+                    buffer.clear();
+                    buffer += currentChar;
+                    break;
+                case Comment2:
+                    setCurrentBlockState(Comment2);
+                case Separator:
+                    switch(oldState){
+                        case MayBeComment2End:
+                            setFormat(i-(buffer.length()-1), buffer.length(), m_formats[CommentFormat]);
+                            setCurrentBlockState(-1);
+                            buffer.clear();
+                            break;
+                        case MayBeKeyWord:
+                            if (isKeyWord(buffer.left(buffer.length()-1))){
+                                setFormat(i-(buffer.length()-1), buffer.length()-1, m_formats[KeywordFormat]);
+                            }
+                            buffer.clear();
+                            break;
+                        case MayBeNumber:
+                            setFormat(i-(buffer.length()-1), buffer.length()-1, m_formats[NumberFormat]);
+                            buffer.clear();
+                        case String:
+                        case String2:
+                            setFormat(i-(buffer.length()-1), buffer.length(), m_formats[StringFormat]);
+                            buffer.clear();
+                            break;
+                    }
+                default:
+                    break;
+            }
+        }
+
+        if ( state == Comment || state == Comment2 ){
+            setFormat(i-(buffer.length()-1), buffer.length(), m_formats[CommentFormat]);
+        }
+
+        if ( state == String || state == String2 ){
+            setFormat(i-(buffer.length()-1), buffer.length(), m_formats[StringFormat]);
+        }
+
+        i++;
+        if ( i>= text.length()) break;
+    }
+
+    TextBlockData *data = new TextBlockData;
+
+
+    for (int i = 0; i < PARENHEIS_COUNT; ++i){
+        createParentheisisInfo(parenthesisCharacters[LeftParenthesis][i].toLatin1(), data, text);
+        createParentheisisInfo(parenthesisCharacters[RightParenthesis][i].toLatin1(), data, text);
+    }
+//    createParentheisisInfo('(', data, text);
+//    createParentheisisInfo(')', data, text);
+//    createParentheisisInfo('{', data, text);
+//    createParentheisisInfo('}', data, text);
+//    createParentheisisInfo('[', data, text);
+//    createParentheisisInfo(']', data, text);
+
+    setCurrentBlockUserData(data);
+}
+
+bool ScriptHighlighter::isKeyWord(const QString& word)
+{
+    for (int i = 0; i < KEYWORDS_COUNT-1; ++i){
+        if (QLatin1String(keywords[i]) == word) return true;
+    }
+    return false;
+}
+
+bool ScriptHighlighter::isDark(QColor color)
+{
+    double a = 1 - ( 0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255;
+    return  (a < 0.5);
+}
+
+ScriptHighlighter::ScriptHighlighter(QTextDocument* parent):
+    QSyntaxHighlighter(parent)
+{
+
+    if ( isDark(QPalette().background().color())){
+        m_formats[NumberFormat].setForeground(Qt::darkBlue);
+        m_formats[StringFormat].setForeground(Qt::darkGreen);
+        m_formats[KeywordFormat].setForeground(Qt::darkYellow);
+        m_formats[CommentFormat].setForeground(Qt::darkGreen);
+        m_formats[CommentFormat].setFontItalic(true);
+    } else {
+        m_formats[NumberFormat].setForeground(QColor("#ff6aad"));
+        m_formats[StringFormat].setForeground(QColor("#b27f40"));
+        m_formats[KeywordFormat].setForeground(QColor("#45c5d5"));
+        m_formats[CommentFormat].setForeground(QColor("#a1a4a9"));
+        m_formats[CommentFormat].setFontItalic(true);
+    }
+}
+
+QVector<ParenthesisInfo*> TextBlockData::parentheses()
+{
+    return m_parentheses;
+}
+
+void TextBlockData::insert(ParenthesisInfo* info)
+{
+    int i = 0;
+    while (i < m_parentheses.size() &&
+        info->position > m_parentheses.at(i)->position)
+        ++i;
+
+    m_parentheses.insert(i, info);
+}
+
+} // namespace LimeReport
diff --git a/limereport/scripteditor/lrscripthighlighter.h b/limereport/scripteditor/lrscripthighlighter.h
new file mode 100644
index 0000000..4580484
--- /dev/null
+++ b/limereport/scripteditor/lrscripthighlighter.h
@@ -0,0 +1,50 @@
+#ifndef LRSCRIPTHIGHLIGHTER_H
+#define LRSCRIPTHIGHLIGHTER_H
+
+#include <QSyntaxHighlighter>
+
+namespace LimeReport{
+
+enum ParenthesisType {LeftParenthesis, RightParenthesis, ParenthesisTypeCount};
+
+#define PARENHEIS_COUNT 3
+const QChar parenthesisCharacters[ParenthesisTypeCount][PARENHEIS_COUNT] = {
+    {'(', '{', '['},
+    {')', '}', ']'}
+};
+
+struct ParenthesisInfo
+{
+    char character;
+    int position;
+};
+
+class TextBlockData : public QTextBlockUserData
+{
+public:
+    TextBlockData(){}
+    QVector<ParenthesisInfo *> parentheses();
+    void insert(ParenthesisInfo *info);
+
+private:
+    QVector<ParenthesisInfo *> m_parentheses;
+};
+
+class ScriptHighlighter : QSyntaxHighlighter{
+public:
+    ScriptHighlighter(QTextDocument* parent);
+protected:
+    void highlightBlock(const QString& text);
+    enum ScriptFormats {
+        NumberFormat, StringFormat, KeywordFormat,
+        CommentFormat, FormatsCount
+    };
+    QTextCharFormat m_formats[FormatsCount];
+    bool isKeyWord(const QString& word);
+    bool isDark(QColor color);
+    void createParentheisisInfo(const char& literal, TextBlockData *data, const QString& text);
+};
+
+
+}
+#endif // LRSCRIPTHIGHLIGHTER_H