From 9ddf2107791cb150f37ba5744bd849422755a863 Mon Sep 17 00:00:00 2001
From: Mathias Paulin <mathias.paulin@irit.fr>
Date: Thu, 25 Mar 2021 18:19:40 +0100
Subject: [PATCH] Improve the Visualization renderer controller. Add a gui ton
 interact with the controler. Modify the demo to give access to this
 controller.

---
 src/DemoApp/main.cpp                          |  17 +
 src/libRender/CMakeLists.txt                  |  26 +
 .../RadiumNBR/Gui/CodeEditor/CodeEditor.cpp   | 287 +++++++++
 .../RadiumNBR/Gui/CodeEditor/CodeEditor.hpp   | 285 +++++++++
 .../Gui/CodeEditor/CodeEditorDesign.cpp       | 596 ++++++++++++++++++
 .../Gui/CodeEditor/CodeEditorDesign.hpp       | 399 ++++++++++++
 .../Gui/CodeEditor/CodeEditorEvents.cpp       | 295 +++++++++
 .../Gui/CodeEditor/CodeEditorHighlighter.cpp  | 244 +++++++
 .../Gui/CodeEditor/CodeEditorHighlighter.hpp  | 142 +++++
 .../Gui/CodeEditor/CodeEditorLineWidget.cpp   | 125 ++++
 .../Gui/CodeEditor/CodeEditorLineWidget.hpp   |  56 ++
 .../Gui/CodeEditor/CodeEditorPopup.cpp        |  91 +++
 .../Gui/CodeEditor/CodeEditorPopup.hpp        |  51 ++
 .../Gui/CodeEditor/CodeEditorResources.qrc    |   6 +
 .../Gui/CodeEditor/CodeEditorSheets.cpp       |  98 +++
 .../Gui/CodeEditor/CodeEditorSheets.hpp       |  91 +++
 .../Gui/CodeEditor/CodeEditorSlots.cpp        |  86 +++
 .../Gui/CodeEditor/EditorDefaultDesign.xml    |  25 +
 .../Gui/CodeEditor/HighlightRules_cpp.xml     |  76 +++
 .../Gui/CodeEditor/LineColumnPadding.cpp      |  95 +++
 .../Gui/CodeEditor/LineColumnPadding.hpp      |  80 +++
 .../RadiumNBR/Gui/CodeEditor/SyntaxRule.cpp   | 358 +++++++++++
 .../RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp   | 218 +++++++
 .../RadiumNBR/Gui/CodeEditor/XmlHelper.cpp    | 252 ++++++++
 .../RadiumNBR/Gui/CodeEditor/XmlHelper.hpp    |  71 +++
 src/libRender/RadiumNBR/Gui/GlslEditor.cpp    |  68 ++
 src/libRender/RadiumNBR/Gui/GlslEditor.hpp    |  54 ++
 src/libRender/RadiumNBR/Gui/RendererPanel.cpp |  56 +-
 src/libRender/RadiumNBR/Gui/RendererPanel.hpp |  13 +-
 .../RadiumNBR/Gui/VisualizationGui.cpp        |  61 +-
 30 files changed, 4305 insertions(+), 17 deletions(-)
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditor.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditor.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorDesign.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorEvents.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorPopup.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorPopup.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorResources.qrc
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSheets.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSheets.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSlots.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/EditorDefaultDesign.xml
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/HighlightRules_cpp.xml
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/LineColumnPadding.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/LineColumnPadding.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/SyntaxRule.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/XmlHelper.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/CodeEditor/XmlHelper.hpp
 create mode 100644 src/libRender/RadiumNBR/Gui/GlslEditor.cpp
 create mode 100644 src/libRender/RadiumNBR/Gui/GlslEditor.hpp

diff --git a/src/DemoApp/main.cpp b/src/DemoApp/main.cpp
index 9c7b0d2..2ee6066 100644
--- a/src/DemoApp/main.cpp
+++ b/src/DemoApp/main.cpp
@@ -9,6 +9,7 @@
 #include <Engine/Scene/GeometrySystem.hpp>
 
 // Include the customizable renderer system (only the used part here)
+#include <RadiumNBR/Gui/VisualizationGui.hpp>
 #include <RadiumNBR/NodeBasedRenderer.hpp>
 #include <RadiumNBR/Renderer/Visualization.hpp>
 
@@ -21,6 +22,8 @@
 #include <Core/Utils/Log.hpp>
 using namespace Ra::Core::Utils; // log
 
+#include <QDockWidget>
+#include <QToolBar>
 /**
  * This class parameterize the renderer just after the OpenGL system was initialized.
  * when a method of this controller is called, the OpenGL context of the drawing window is
@@ -181,6 +184,20 @@ class DemoWindowFactory : public Ra::Gui::BaseApplication::WindowFactory
     inline Ra::Gui::MainWindowInterface* createMainWindow() const override {
         auto window = new Ra::Gui::SimpleWindow();
         window->addRenderer( renderer->getRendererName(), renderer );
+        // Build the gui for the renderer
+        auto controlPanel =
+            RadiumNBR::buildControllerGui( renderer.get(), [window]() { window->frameUpdate(); } );
+        auto dock = new QDockWidget( "Renderer Controller", window );
+        dock->setAllowedAreas( Qt::BottomDockWidgetArea );
+        dock->setWidget( controlPanel );
+        window->addDockWidget( Qt::BottomDockWidgetArea, dock );
+        dock->hide();
+
+        auto toolbar = new QToolBar( "Show Controls ", window );
+        toolbar->setAllowedAreas( Qt::BottomToolBarArea );
+        toolbar->addAction( dock->toggleViewAction() );
+        window->addToolBar( Qt::BottomToolBarArea, toolbar );
+
         return window;
     }
 
diff --git a/src/libRender/CMakeLists.txt b/src/libRender/CMakeLists.txt
index 7e0f3e8..f32cea2 100644
--- a/src/libRender/CMakeLists.txt
+++ b/src/libRender/CMakeLists.txt
@@ -135,18 +135,44 @@ set(gui_sources
     RadiumNBR/Gui/FullFeaturedRendererGui.cpp
     RadiumNBR/Gui/VisualizationGui.cpp
     RadiumNBR/Gui/RendererPanel.cpp
+
+    RadiumNBR/Gui/CodeEditor/CodeEditor.cpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorDesign.cpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorEvents.cpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.cpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.cpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorPopup.cpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorSheets.cpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorSlots.cpp
+    RadiumNBR/Gui/CodeEditor/LineColumnPadding.cpp
+    RadiumNBR/Gui/CodeEditor/SyntaxRule.cpp
+    RadiumNBR/Gui/CodeEditor/XmlHelper.cpp
+    RadiumNBR/Gui/GlslEditor.cpp
     )
 
 set(gui_public_headers
     RadiumNBR/Gui/FullFeaturedRendererGui.hpp
     RadiumNBR/Gui/VisualizationGui.hpp
     RadiumNBR/Gui/RendererPanel.hpp
+
+    RadiumNBR/Gui/CodeEditor/CodeEditor.hpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.hpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorPopup.hpp
+    RadiumNBR/Gui/CodeEditor/CodeEditorSheets.hpp
+    RadiumNBR/Gui/CodeEditor/LineColumnPadding.hpp
+    RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp
+    RadiumNBR/Gui/CodeEditor/XmlHelper.hpp
+    RadiumNBR/Gui/GlslEditor.hpp
     )
 
 set(gui_headers
+
     )
 
 set(gui_resources
+    RadiumNBR/Gui/CodeEditor/CodeEditorResources.qrc
     )
 
 # Our library project uses these sources and headers.
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditor.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditor.cpp
new file mode 100644
index 0000000..aebcd85
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditor.cpp
@@ -0,0 +1,287 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <QCompleter>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditor.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorPopup.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorSheets.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        Default constructor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+QCodeEditor::QCodeEditor( QWidget* parent ) :
+    QPlainTextEdit( parent ),
+    m_Popup( NULL ),
+    m_Highlighter( NULL ),
+    m_SourceModel( NULL ),
+    m_RuleFilter( NULL ),
+    m_AutoComplete( NULL ),
+    m_CompletionTrigger( 3 ) {
+
+    // Changes miscellaneous properties
+    setAutoFillBackground( true );
+    setFrameStyle( QFrame::NoFrame );
+
+    // Specifies the default font for the code editor
+    QFont editorFont( "Courier" );
+    editorFont.setPointSize( 14 );
+    editorFont.setKerning( true );
+    editorFont.setStyleHint( QFont::TypeWriter );
+    editorFont.setStyleStrategy( QFont::PreferAntialias );
+    setFont( editorFont );
+
+    // Constructs the highlighter and the intelliBox
+    m_Highlighter = new QCodeEditorHighlighter( this );
+    m_Popup       = new QCodeEditorPopup( this );
+
+    // Constructs the intelliBox's completer
+    m_AutoComplete = new QCompleter;
+    m_AutoComplete->setWidget( this );
+    m_AutoComplete->setCompletionMode( QCompleter::PopupCompletion );
+    m_AutoComplete->setModelSorting( QCompleter::CaseInsensitivelySortedModel );
+    m_AutoComplete->setPopup( m_Popup );
+
+    // Constructs the source model
+    m_SourceModel = new QStandardItemModel;
+
+    // Constructs the sorting proxy model
+    m_RuleFilter = new QSortFilterProxyModel;
+    m_RuleFilter->setFilterCaseSensitivity( Qt::CaseInsensitive );
+    m_RuleFilter->setDynamicSortFilter( false );
+
+    // Constructs the line widget
+    m_LineWidget = new QCodeEditorLineWidget( this );
+    updateLineColumn( 0 );
+
+    // Connects signals with slots
+    connect(
+        m_AutoComplete, SIGNAL( activated( QString ) ), this, SLOT( completeWord( QString ) ) );
+    connect(
+        this, SIGNAL( updateRequest( QRect, int ) ), this, SLOT( scrollLineColumn( QRect, int ) ) );
+    connect( this, SIGNAL( blockCountChanged( int ) ), this, SLOT( updateLineColumn( int ) ) );
+    connect( this, SIGNAL( textChanged() ), this, SLOT( textChanged() ) );
+}
+
+///
+///  @fn        Destructor
+///  @author    Nicolas Kogler
+///
+QCodeEditor::~QCodeEditor() {
+    delete m_Highlighter;
+    delete m_LineWidget;
+    delete m_RuleFilter;
+    delete m_AutoComplete;
+}
+
+///
+///  @fn        rules
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QList<QSyntaxRule>& QCodeEditor::rules() const {
+    return m_Rules;
+}
+
+///
+///  @fn        design
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QCodeEditorDesign& QCodeEditor::design() const {
+    return m_Design;
+}
+
+///
+///  @fn        lineCount
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+quint32 QCodeEditor::lineCount() const {
+    return static_cast<quint32>( document()->blockCount() );
+}
+
+///
+///  @fn        textAtLine
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+QString QCodeEditor::textAtLine( quint32 index ) const {
+    return document()->findBlockByLineNumber( index ).text();
+}
+
+///
+///  @fn        highlighter
+///  @author    Nicolas Kogler
+///  @date      October 15th, 2016
+///
+QCodeEditorHighlighter* QCodeEditor::highlighter() const {
+    return m_Highlighter;
+}
+
+///
+///  @fn        setRules
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::setRules( const QList<QSyntaxRule>& rules ) {
+    m_Rules = rules;
+    m_Highlighter->updateFormats();
+    m_Highlighter->rehighlight();
+}
+
+///
+///  @fn        setDesign
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::setDesign( const QCodeEditorDesign& design ) {
+    m_Design = design;
+    setFont( design.editorFont() );
+
+    // Modifies the palette of the underlying QPlainTextEdit
+    QPalette palette;
+    palette.setColor( QPalette::Base, design.editorBackColor() );
+    palette.setColor( QPalette::Text, design.editorTextColor() );
+    setPalette( palette );
+
+    // Modifies the border through a style-sheet
+    setStyleSheet( QCodeEditorSheets::border( design ) );
+    m_Highlighter->updateFormats();
+}
+
+///
+///  @fn        setDesign
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+void QCodeEditor::setCompletionTrigger( qint32 amount ) {
+    m_CompletionTrigger = amount;
+}
+
+///
+///  @fn        setKeywords
+///  @author    Nicolas Kogler
+///  @date      October 9th, 2016
+///
+void QCodeEditor::setKeywords( const QStringList& keywords ) {
+    qint32 size = keywords.size();
+
+    // Constructs the model from the keywords
+    for ( int i = 0; i < size; ++i )
+    {
+        QStandardItem* item = new QStandardItem;
+        item->setText( keywords.at( i ) );
+        m_SourceModel->appendRow( item );
+    }
+
+    // Changes the auto complete menu model
+    m_RuleFilter->setSourceModel( m_SourceModel );
+    m_RuleFilter->sort( 0 );
+    m_AutoComplete->setModel( m_RuleFilter );
+}
+
+///
+///  @fn        setKeywordModel
+///  @author    Nicolas Kogler
+///  @date      October 9th, 2016
+///
+void QCodeEditor::setKeywordModel( QStandardItemModel* model ) {
+    m_RuleFilter->setSourceModel( model );
+    m_AutoComplete->setModel( m_RuleFilter );
+}
+
+///
+///  @fn        addKeyword
+///  @author    Nicolas Kogler
+///  @date      October 19th, 2016
+///
+void QCodeEditor::addKeyword( const QString& keyword ) {
+    if ( !keywordExists( keyword ) )
+    {
+        QStandardItem* item = new QStandardItem;
+        item->setText( keyword );
+        m_SourceModel->appendRow( item );
+        m_RuleFilter->sort( 0 );
+    }
+}
+
+///
+///  @fn        removeKeyword
+///  @author    Nicolas Kogler
+///  @date      October 19th, 2016
+///
+void QCodeEditor::removeKeyword( const QString& keyword ) {
+    QList<QStandardItem*> m = m_SourceModel->findItems( keyword );
+    if ( m.size() == 1 ) { m_SourceModel->removeRow( m.at( 0 )->row() ); }
+}
+
+///
+///  @fn        keywordExists
+///  @author    Nicolas Kogler
+///  @date      October 19th, 2016
+///
+bool QCodeEditor::keywordExists( const QString& keyword ) {
+    return !m_SourceModel->findItems( keyword ).isEmpty();
+}
+
+///
+///  @fn        rehighlight
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::rehighlight() {
+    m_Highlighter->rehighlight();
+}
+
+///
+///  @fn        lineColumnWidth
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+int QCodeEditor::lineColumnWidth() const {
+    // Gets the amount of lines
+    int minDigits = 1;
+    int maxDigits = qMax( minDigits, document()->blockCount() );
+
+    // Calculates the number of digits in the biggest line number
+    while ( maxDigits >= 10 )
+    {
+        maxDigits /= 10;
+        minDigits++;
+    }
+
+    // Retrieves the line column padding
+    QLineColumnPadding pad = m_Design.lineColumnPadding();
+
+    // Instead of going through all numbers and picking the one
+    // rendering the widest, we approximate the width of it.
+    return fontMetrics().horizontalAdvance( '0' ) * minDigits + pad.left() + pad.right();
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditor.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditor.hpp
new file mode 100644
index 0000000..c76889a
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditor.hpp
@@ -0,0 +1,285 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp>
+#include <RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp>
+
+#include <QAbstractProxyModel>
+#include <QCompleter>
+#include <QPlainTextEdit>
+#include <QStandardItemModel>
+#include <QTextBlock>
+
+namespace RadiumNBR::Gui {
+
+//
+// Forward declarations
+//
+class QCodeEditorLineWidget;
+class QCodeEditorHighlighter;
+class QCodeEditorPopup;
+
+///
+///  @file      QCodeEditor.hpp
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///  @class     QCodeEditor
+///  @brief     Highlights and auto-completes code.
+///
+class NodeBasedRenderer_LIBRARY_API QCodeEditor : public QPlainTextEdit
+{
+    Q_OBJECT
+  public:
+    ///
+    ///  @fn    Default constructor
+    ///  @brief Initializes a new instance of QCodeEditor.
+    ///
+    QCodeEditor( QWidget* parent = NULL );
+
+    ///
+    ///  @fn    Destructor
+    ///  @brief Frees all resources allocated by QCodeEditor.
+    ///
+    ~QCodeEditor();
+
+    ///
+    ///  @fn      rules : const
+    ///  @brief   Retrieves all the syntax highlighting rules.
+    ///  @returns a ref to a list of QSyntaxRule instances.
+    ///
+    const QList<QSyntaxRule>& rules() const;
+
+    ///
+    ///  @fn      design : const
+    ///  @brief   Retrieves all the visual properties.
+    ///  @returns a ref to a QCodeEditorDesign instance.
+    ///
+    const QCodeEditorDesign& design() const;
+
+    ///
+    ///  @fn      lineCount : const
+    ///  @brief   Retrieves the amount of lines.
+    ///  @returns the the amount of lines.
+    ///
+    quint32 lineCount() const;
+
+    ///
+    ///  @fn      textAtLine : const
+    ///  @brief   Retrieves the text on the specified line number.
+    ///  @param   index Line index starting from zero
+    ///  @returns the string value at line 'index'.
+    ///
+    QString textAtLine( quint32 index ) const;
+
+    ///
+    ///  @fn      highlighter : const
+    ///  @brief   Retrieves the syntax highlighter for this editor.
+    ///  @returns the sytax highlighter.
+    ///
+    QCodeEditorHighlighter* highlighter() const;
+
+    ///
+    ///  @fn    setRules
+    ///  @brief Specifies the syntax highlighting rules.
+    ///  @param rules List of QSyntaxRule instances
+    ///
+    void setRules( const QList<QSyntaxRule>& rules );
+
+    ///
+    ///  @fn    setDesign
+    ///  @brief Specifies the visual properties.
+    ///  @param design Instance of QCodeEditorDesign
+    ///
+    void setDesign( const QCodeEditorDesign& design );
+
+    ///
+    ///  @fn    setCompletionTrigger
+    ///  @brief Sets the completion trigger.
+    ///
+    ///  Specifies the amount of characters to be typed in the
+    ///  currently written word until the auto-completion menu
+    ///  is opened (in case it is part of a registered keyword, function ...).
+    ///
+    ///  @param amount Amount of characters to be typed
+    ///  @default The default value is 3.
+    ///
+    void setCompletionTrigger( qint32 amount );
+
+    ///
+    ///  @fn    setKeywords
+    ///  @brief Specifies the keywords for auto-completion.
+    ///
+    ///  It is not possible to add icons or anything else
+    ///  if only the keywords are specified. The keywords
+    ///  are sorted alphabetically. If you want to add
+    ///  icons or other things to the keywords, you have to
+    ///  specify a custom model through setKeywordModel.
+    ///
+    ///  @param keywords List of keywords
+    ///
+    void setKeywords( const QStringList& keywords );
+
+    ///
+    ///  @fn    setKeywordModel
+    ///  @brief Specifies the auto-complete model directly.
+    ///  @param model QStandardItemModel to use
+    ///
+    void setKeywordModel( QStandardItemModel* model );
+
+    ///
+    ///  @fn    addKeyword
+    ///  @brief Adds a keyword to the existing model.
+    ///  @param keyword New auto-complete keyword.
+    ///  @note  If you specified a custom model, append
+    ///         the keyword on your own and it will be
+    ///         immediately visible to the intelliBox.
+    ///
+    void addKeyword( const QString& keyword );
+
+    ///
+    ///  @fn    removeKeyword
+    ///  @brief Removes a keyword from the existing model.
+    ///  @param keyword Keyword to remove from the list
+    ///
+    void removeKeyword( const QString& keyword );
+
+    ///
+    ///  @fn      keywordsExist
+    ///  @brief   Determines whether the given keyword exists.
+    ///  @param   keyword Keyword to check
+    ///  @returns true if the keyword exĂ­sts.
+    ///
+    bool keywordExists( const QString& keyword );
+
+    ///
+    ///  @fn    rehighlight
+    ///  @brief Applies syntax highlighting manually.
+    ///
+    ///  Normally one would not need this, because 'setRules'
+    ///  already performs rehighlighting of the QCodeEditor.
+    ///
+    void rehighlight();
+
+    ///
+    ///  @fn      lineColumnWidth
+    ///  @brief   Retrieves the width of the line column.
+    ///  @returns the width of the line column.
+    ///
+    int lineColumnWidth() const;
+
+  protected:
+    ///
+    ///  @fn    paintEvent
+    ///  @brief Paints additional widgets or plugins.
+    ///  @param event Pointer to a QPaintEvent instance
+    ///
+    void paintEvent( QPaintEvent* event ) Q_DECL_OVERRIDE;
+
+    ///
+    ///  @fn    keyPressEvent
+    ///  @brief Intercepts the key-press event.
+    ///
+    ///  Under the hood, it triggers the intellisense box
+    ///  in case a partial keyword or function has been
+    ///  detected or if one of the trigger keys for the
+    ///  intellisense box have been pressed (e.g dot or
+    ///  arrow for C++ methods).
+    ///
+    ///  @param event Pointer to a QKeyEvent instance
+    ///
+    void keyPressEvent( QKeyEvent* event ) Q_DECL_OVERRIDE;
+
+    ///
+    ///  @fn    keyReleaseEvent
+    ///  @brief Intercepts the key-release event.
+    ///
+    ///  Almost all IDEs convert tabulator characters to
+    ///  whitespaces (mostly 4). This ensures that the
+    ///  document looks the same, regardless of the context.
+    ///
+    ///  @param event Pointer to a QKeyEvent instance
+    ///
+    void keyReleaseEvent( QKeyEvent* event ) Q_DECL_OVERRIDE;
+
+    ///
+    ///  @fn    resizeEvent
+    ///  @brief Intercepts the resize event.
+    ///
+    ///  Whenever the user resizes the code editor in the
+    ///  vertical direction, the line-number widget should
+    ///  also be resized.
+    ///
+    ///  @param event Pointer to a QResizeEvent instance
+    ///
+    void resizeEvent( QResizeEvent* event ) Q_DECL_OVERRIDE;
+
+  signals:
+
+    ///
+    ///  @fn    lineChanged
+    ///  @brief Is emitted when a line's text changed.
+    ///  @param block Block (line) that was changed
+    ///
+    void lineChanged( QTextBlock block );
+
+  private slots:
+
+    ///
+    ///  @fn    updateLineColumn : slot
+    ///  @brief Updates the line column width.
+    ///
+    ///  We need to recalculate the width of the line
+    ///  column because the amount of digits per line
+    ///  number changes if the user exceeds line 9, 99, ...
+    ///
+    ///  @param lineCount Current amount of lines
+    ///
+    void updateLineColumn( int lineCount );
+
+    ///
+    ///  @fn    scrollLineColumn : slot
+    ///  @brief Updates the scroll value of the line widget.
+    ///
+    ///  The first visible line number must be updated
+    ///  in case the user scrolled the code editor vertically.
+    ///
+    ///  @param view Visible rectangle within the editor
+    ///  @param scroll Vertical scroll value
+    ///
+    void scrollLineColumn( QRect view, int scroll );
+
+    ///
+    ///  @fn    completeWord : slot
+    ///  @brief Auto-completes the given keyword, function, ...
+    ///
+    ///  This slot is executed as soon as the user picked an
+    ///  element from the QCodeEditorPopup list.
+    ///
+    ///  @param word The word to complete
+    ///
+    void completeWord( const QString& word );
+
+    ///
+    ///  @fn    textChanged : slot
+    ///  @brief Emits a line-changed event when appropriate
+    ///
+    void textChanged();
+
+  private:
+    //
+    // Private class members
+    //
+    QList<QSyntaxRule> m_Rules;            ///< Holds all syntax highlighting rules
+    QCodeEditorDesign m_Design;            ///< Holds all visual properties
+    QCodeEditorLineWidget* m_LineWidget;   ///< Line column widget
+    QCodeEditorPopup* m_Popup;             ///< Intellisense popup widget
+    QCodeEditorHighlighter* m_Highlighter; ///< The syntax highlighter
+    QStandardItemModel* m_SourceModel;     ///< Source model for the rule filter
+    QSortFilterProxyModel* m_RuleFilter;   ///< Filters all the keywords, funcs, ...
+    QCompleter* m_AutoComplete;            ///< Auto completion widget
+    qint32 m_CompletionTrigger;            ///< Amount of characters till AC trigger
+
+    // Allow the line widget to access vars/funcs while rendering
+    friend class QCodeEditorLineWidget;
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorDesign.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorDesign.cpp
new file mode 100644
index 0000000..c52170a
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorDesign.cpp
@@ -0,0 +1,596 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp>
+#include <RadiumNBR/Gui/CodeEditor/XmlHelper.hpp>
+#include <qrgb.h>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        Default constructor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+QCodeEditorDesign::QCodeEditorDesign() :
+    m_EditorBackColor( 0xffffffff ),
+    m_EditorTextColor( 0xff333333 ),
+    m_EditorBorderColor( 0xffb9b9b9 ),
+    m_LineColumnBackColor( 0xffe9e9e9 ),
+    m_LineColumnTextColor( 0xff6a9fc6 ),
+    m_LineColumnSeparatorColor( 0xffb9b9b9 ),
+    m_ActiveLineColor( 0xfffc9100 ),
+    m_IntelliBoxBackColor( 0xfffafafa ),
+    m_IntelliBoxTextColor( 0xff333333 ),
+    m_IntelliBoxBorderColor( 0xffb9b9b9 ),
+    m_IntelliBoxSelectionBackColor( 0xffc0dcf3 ),
+    m_IntelliBoxSelectionBorderColor( 0xff90c8f6 ),
+    m_IntelliBoxPressBackColor( 0xff90c8f6 ),
+    m_IntelliBoxPressBorderColor( 0xff60b0f9 ),
+    m_EditorBorder( QMargins( 0, 0, 0, 0 ) ),
+    m_IntelliBoxBorder( QMargins( 1, 1, 1, 1 ) ),
+    m_PopupSize( 200, 200 ),
+    m_HasLineColumn( true ),
+    m_ShowFocusRect( false ),
+    m_FirstLineOne( true ) {
+
+    // Tries to find a monospaced font
+#ifndef Q_OS_WIN32
+    m_EditorFont.setFamily( "Courier" );
+    m_IntelliBoxFont.setFamily( "Courier" );
+    m_EditorFont.setStyleHint( QFont::TypeWriter );
+    m_IntelliBoxFont.setStyleHint( QFont::TypeWriter );
+#else
+    m_EditorFont.setFamily( "Consolas" );
+    m_IntelliBoxFont.setFamily( "Consolas" );
+#endif
+    m_EditorFont.setPointSize( 14 );
+    m_IntelliBoxFont.setPointSize( 14 );
+}
+
+///
+///  @fn        Copy constructor
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QCodeEditorDesign::QCodeEditorDesign( const QCodeEditorDesign& design ) :
+    m_EditorBackColor( design.editorBackColor() ),
+    m_EditorTextColor( design.editorTextColor() ),
+    m_EditorBorderColor( design.editorBorderColor() ),
+    m_LineColumnBackColor( design.lineColumnBackColor() ),
+    m_LineColumnTextColor( design.lineColumnTextColor() ),
+    m_LineColumnSeparatorColor( design.lineColumnSeparatorColor() ),
+    m_ActiveLineColor( design.activeLineColor() ),
+    m_IntelliBoxBackColor( design.intelliBoxBackColor() ),
+    m_IntelliBoxTextColor( design.intelliBoxTextColor() ),
+    m_IntelliBoxBorderColor( design.intelliBoxBorderColor() ),
+    m_IntelliBoxSelectionBackColor( design.intelliBoxSelectionBackColor() ),
+    m_IntelliBoxSelectionBorderColor( design.intelliBoxSelectionBorderColor() ),
+    m_IntelliBoxPressBackColor( design.intelliBoxPressBackColor() ),
+    m_IntelliBoxPressBorderColor( design.intelliBoxPressBorderColor() ),
+    m_EditorFont( design.editorFont() ),
+    m_IntelliBoxFont( design.intelliBoxFont() ),
+    m_EditorBorder( design.editorBorder() ),
+    m_IntelliBoxBorder( design.intelliBoxBorder() ),
+    m_PopupSize( design.popupSize() ),
+    m_HasLineColumn( design.isLineColumnVisible() ),
+    m_ShowFocusRect( design.hasFocusRect() ) {}
+
+///
+///  @fn        Constructor
+///  @author    Nicolas Kogler
+///  @date      October 18th, 2016
+///
+QCodeEditorDesign::QCodeEditorDesign( const QString& path ) : QCodeEditorDesign() {
+    QFile file( path );
+
+    // Determines whether file can be opened
+    if ( !file.open( QIODevice::ReadOnly ) )
+    {
+        qDebug( "kgl::QCodeEditorDesign: Cannot open XML file." );
+        return;
+    }
+
+    // Attempts to read top element
+    QXmlStreamReader xmlReader( &file );
+    if ( !xmlReader.readNextStartElement() && xmlReader.name() != "design" )
+    {
+        qDebug( "kgl::QCodeEditorDesign: Top tag is not <design>." );
+        return;
+    }
+
+    while ( !xmlReader.hasError() && !xmlReader.atEnd() )
+    {
+        if ( !xmlReader.readNextStartElement() ) { continue; }
+
+        QString name = xmlReader.name().toString().toLower();
+
+        // Order and case of elements does not matter
+        if ( name == "editorbackcolor" ) { m_EditorBackColor = readColor( &xmlReader ); }
+        else if ( name == "editortextcolor" )
+        { m_EditorTextColor = readColor( &xmlReader ); }
+        else if ( name == "editorbordercolor" )
+        { m_EditorBorderColor = readColor( &xmlReader ); }
+        else if ( name == "linecolumnbackcolor" )
+        { m_LineColumnBackColor = readColor( &xmlReader ); }
+        else if ( name == "linecolumntextcolor" )
+        { m_LineColumnTextColor = readColor( &xmlReader ); }
+        else if ( name == "linecolumnseparatorcolor" )
+        { m_LineColumnSeparatorColor = readColor( &xmlReader ); }
+        else if ( name == "activelinecolor" )
+        { m_ActiveLineColor = readColor( &xmlReader ); }
+        else if ( name == "intelliboxbackcolor" )
+        { m_IntelliBoxBackColor = readColor( &xmlReader ); }
+        else if ( name == "intelliboxtextcolor" )
+        { m_IntelliBoxTextColor = readColor( &xmlReader ); }
+        else if ( name == "intelliboxbordercolor" )
+        { m_IntelliBoxBorderColor = readColor( &xmlReader ); }
+        else if ( name == "intelliboxselectionbackcolor" )
+        { m_IntelliBoxSelectionBackColor = readColor( &xmlReader ); }
+        else if ( name == "intelliboxselectionbordercolor" )
+        { m_IntelliBoxSelectionBorderColor = readColor( &xmlReader ); }
+        else if ( name == "intelliboxpressbackcolor" )
+        { m_IntelliBoxPressBackColor = readColor( &xmlReader ); }
+        else if ( name == "intelliboxpressbordercolor" )
+        { m_IntelliBoxPressBorderColor = readColor( &xmlReader ); }
+        else if ( name == "editorborder" )
+        { m_EditorBorder = readMargin( &xmlReader ); }
+        else if ( name == "intelliboxborder" )
+        { m_IntelliBoxBorder = readMargin( &xmlReader ); }
+        else if ( name == "linecolumnpadding" )
+        { m_LineColumnPadding = QLineColumnPadding( readSize( &xmlReader ) ); }
+        else if ( name == "popupsize" )
+        { m_PopupSize = readSize( &xmlReader ); }
+        else if ( name == "haslinecolumn" )
+        { m_HasLineColumn = readBool( &xmlReader ); }
+        else if ( name == "showfocusrect" )
+        { m_ShowFocusRect = readBool( &xmlReader ); }
+        else if ( name == "firstlineone" )
+        { m_FirstLineOne = readBool( &xmlReader ); }
+        else if ( name == "editorfont" )
+        { m_EditorFont = readFont( &xmlReader, QFont( "Courier" ) ); }
+        else if ( name == "intelliboxfont" )
+        { m_IntelliBoxFont = readFont( &xmlReader, QFont( "Courier" ) ); }
+        else
+        {
+            QString s( "kgl::QCodeEditorDesign: Element '%0' is unknown." );
+            qDebug( s.arg( name ).toStdString().c_str() );
+        }
+    }
+
+    file.close();
+}
+
+///
+///  @fn        Destructor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+QCodeEditorDesign::~QCodeEditorDesign() {}
+
+///
+///  @fn        editorBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::editorBackColor() const {
+    return m_EditorBackColor;
+}
+
+///
+///  @fn        editorTextColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::editorTextColor() const {
+    return m_EditorTextColor;
+}
+
+///
+///  @fn        editorBorderColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::editorBorderColor() const {
+    return m_EditorBorderColor;
+}
+
+///
+///  @fn        lineColumnBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::lineColumnBackColor() const {
+    return m_LineColumnBackColor;
+}
+
+///
+///  @fn        lineColumnTextColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::lineColumnTextColor() const {
+    return m_LineColumnTextColor;
+}
+
+///
+///  @fn        lineColumnSeparatorColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::lineColumnSeparatorColor() const {
+    return m_LineColumnSeparatorColor;
+}
+
+///
+///  @fn        activeLineColor
+///  @author    Nicolas Kogler
+///  @date      October 15th, 2016
+///
+const QColor& QCodeEditorDesign::activeLineColor() const {
+    return m_ActiveLineColor;
+}
+
+///
+///  @fn        intelliBoxBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::intelliBoxBackColor() const {
+    return m_IntelliBoxBackColor;
+}
+
+///
+///  @fn        intelliBoxTextColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::intelliBoxTextColor() const {
+    return m_IntelliBoxTextColor;
+}
+
+///
+///  @fn        intelliBoxBorderColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::intelliBoxBorderColor() const {
+    return m_IntelliBoxBorderColor;
+}
+
+///
+///  @fn        intelliBoxSelectionBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::intelliBoxSelectionBackColor() const {
+    return m_IntelliBoxSelectionBackColor;
+}
+
+///
+///  @fn        intelliBoxSelectionBorderColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::intelliBoxSelectionBorderColor() const {
+    return m_IntelliBoxSelectionBorderColor;
+}
+
+///
+///  @fn        intelliBoxPressBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::intelliBoxPressBackColor() const {
+    return m_IntelliBoxPressBackColor;
+}
+
+///
+///  @fn        intelliBoxPressBorderColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QColor& QCodeEditorDesign::intelliBoxPressBorderColor() const {
+    return m_IntelliBoxPressBorderColor;
+}
+
+///
+///  @fn        editorFont
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QFont& QCodeEditorDesign::editorFont() const {
+    return m_EditorFont;
+}
+
+///
+///  @fn        intelliBoxFont
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QFont& QCodeEditorDesign::intelliBoxFont() const {
+    return m_IntelliBoxFont;
+}
+
+///
+///  @fn        editorBorder
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QMargins& QCodeEditorDesign::editorBorder() const {
+    return m_EditorBorder;
+}
+
+///
+///  @fn        intelliBoxBorder
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QMargins& QCodeEditorDesign::intelliBoxBorder() const {
+    return m_IntelliBoxBorder;
+}
+
+///
+///  @fn        lineColumnPadding
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+const QLineColumnPadding& QCodeEditorDesign::lineColumnPadding() const {
+    return m_LineColumnPadding;
+}
+
+///
+///  @fn        popupSize
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+const QSize& QCodeEditorDesign::popupSize() const {
+    return m_PopupSize;
+}
+
+///
+///  @fn        isLineColumnVisible
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+bool QCodeEditorDesign::isLineColumnVisible() const {
+    return m_HasLineColumn;
+}
+
+///
+///  @fn        hasFocusRect
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+bool QCodeEditorDesign::hasFocusRect() const {
+    return m_ShowFocusRect;
+}
+
+///
+///  @fn        startsWithOne
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+bool QCodeEditorDesign::startsWithOne() const {
+    return m_FirstLineOne;
+}
+
+///
+///  @fn        setEditorBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setEditorBackColor( const QColor& color ) {
+    m_EditorBackColor = color;
+}
+
+///
+///  @fn        setEditorTextColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setEditorTextColor( const QColor& color ) {
+    m_EditorTextColor = color;
+}
+
+///
+///  @fn        setEditorBorderColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setEditorBorderColor( const QColor& color ) {
+    m_EditorBorderColor = color;
+}
+
+///
+///  @fn        setLineColumnBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setLineColumnBackColor( const QColor& color ) {
+    m_LineColumnBackColor = color;
+}
+
+///
+///  @fn        setLineColumnTextColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setLineColumnTextColor( const QColor& color ) {
+    m_LineColumnTextColor = color;
+}
+
+///
+///  @fn        setActiveLineColor
+///  @author    Nicolas Kogler
+///  @date      October 15th, 2016
+///
+void QCodeEditorDesign::setActiveLineColor( const QColor& color ) {
+    m_ActiveLineColor = color;
+}
+
+///
+///  @fn        setLineColumnSeparatorColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setLineColumnSeparatorColor( const QColor& color ) {
+    m_LineColumnSeparatorColor = color;
+}
+
+///
+///  @fn        setIntelliBoxBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxBackColor( const QColor& color ) {
+    m_IntelliBoxBackColor = color;
+}
+
+///
+///  @fn        setIntelliBoxTextColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxTextColor( const QColor& color ) {
+    m_IntelliBoxTextColor = color;
+}
+
+///
+///  @fn        setIntelliBoxBorderColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxBorderColor( const QColor& color ) {
+    m_IntelliBoxBorderColor = color;
+}
+
+///
+///  @fn        setIntelliBoxSelectionBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxSelectionBackColor( const QColor& color ) {
+    m_IntelliBoxSelectionBackColor = color;
+}
+
+///
+///  @fn        setIntelliBoxSelectionBorderColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxSelectionBorderColor( const QColor& color ) {
+    m_IntelliBoxSelectionBorderColor = color;
+}
+
+///
+///  @fn        setIntelliBoxPressBackColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxPressBackColor( const QColor& color ) {
+    m_IntelliBoxPressBackColor = color;
+}
+
+///
+///  @fn        setIntelliBoxPressBorderColor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxPressBorderColor( const QColor& color ) {
+    m_IntelliBoxPressBorderColor = color;
+}
+
+///
+///  @fn        setEditorFont
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setEditorFont( const QFont& font ) {
+    m_EditorFont = font;
+}
+
+///
+///  @fn        setIntelliBoxFont
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxFont( const QFont& font ) {
+    m_IntelliBoxFont = font;
+}
+
+///
+///  @fn        setEditorBorder
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setEditorBorder( const QMargins& border ) {
+    m_EditorBorder = border;
+}
+
+///
+///  @fn        setIntelliBoxBorder
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setIntelliBoxBorder( const QMargins& border ) {
+    m_IntelliBoxBorder = border;
+}
+
+///
+///  @fn        setLineColumnPadding
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setLineColumnPadding( const QLineColumnPadding& padding ) {
+    m_LineColumnPadding = padding;
+}
+
+///
+///  @fn        setLineColumnVisible
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditorDesign::setLineColumnVisible( bool visible ) {
+    m_HasLineColumn = visible;
+}
+
+///
+///  @fn        showFocusRect
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+void QCodeEditorDesign::showFocusRect( bool show ) {
+    m_ShowFocusRect = show;
+}
+
+///
+///  @fn        setFirstLineAsOne
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+void QCodeEditorDesign::setFirstLineAsOne( bool one ) {
+    m_FirstLineOne = one;
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp
new file mode 100644
index 0000000..dd56240
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp
@@ -0,0 +1,399 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+//
+//  Included headers
+//
+#include <QColor>
+#include <QFont>
+#include <RadiumNBR/Gui/CodeEditor/LineColumnPadding.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @file      QCodeEditorDesign.hpp
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///  @class     QCodeEditorDesign
+///  @brief     Specifies the visual appearance of the QCodeEditor.
+///
+class NodeBasedRenderer_LIBRARY_API QCodeEditorDesign
+{
+  public:
+    ///
+    ///  @fn    Default constructor
+    ///  @brief Initializes a new instance of QCodeEditorDesign.
+    ///
+    QCodeEditorDesign();
+
+    ///
+    ///  @fn    Constructor
+    ///  @brief Loads a code editor design from a file.
+    ///  @param path Path to the XML design file
+    ///
+    QCodeEditorDesign( const QString& path );
+
+    ///
+    ///  @fn    Copy constructor
+    ///  @brief Copies one QCodeEditorDesign to another.
+    ///  @param design Other design
+    ///
+    QCodeEditorDesign( const QCodeEditorDesign& design );
+
+    ///
+    ///  @fn     Destructor
+    ///  @brief  Frees all resources allocated by QCodeEditorDesign.
+    ///
+    ~QCodeEditorDesign();
+
+    ///
+    ///  @fn      editorBackColor : const
+    ///  @brief   Retrieves the background color of the code editor.
+    ///  @returns the background color of the editor.
+    ///
+    const QColor& editorBackColor() const;
+
+    ///
+    ///  @fn      editorTextColor : const
+    ///  @brief   Retrieves the text color of the code editor.
+    ///  @returns the text color of the editor.
+    ///
+    const QColor& editorTextColor() const;
+
+    ///
+    ///  @fn      editorBorderColor : const
+    ///  @brief   Retrieves the border color of the code editor.
+    ///  @returns the border color of the editor.
+    ///
+    const QColor& editorBorderColor() const;
+
+    ///
+    ///  @fn      lineColumnBackColor : const
+    ///  @brief   Retrieves the bg color of the line column.
+    ///  @returns the bg color of the line column.
+    ///
+    const QColor& lineColumnBackColor() const;
+
+    ///
+    ///  @fn      lineColumnSeparatorColor : const
+    ///  @brief   Retrieves the color of the separator between column and editor.
+    ///  @returns the separator color between line widget and editor.
+    ///
+    const QColor& lineColumnSeparatorColor() const;
+
+    ///
+    ///  @fn      lineColumnTextColor : const
+    ///  @brief   Retrieves the color of the line number texts.
+    ///  @returns the color in which the line numbers are rendered.
+    ///
+    const QColor& lineColumnTextColor() const;
+
+    ///
+    ///  @fn      activeLineColor : const
+    ///  @brief   Retrieves the color of the line number text that is currently active.
+    ///  @returns the active line number text.
+    ///
+    const QColor& activeLineColor() const;
+
+    ///
+    ///  @fn      intelliBoxBackColor : const
+    ///  @brief   Retrieves the bg color of the intellisense box.
+    ///  @returns the bg color of the intellisense box.
+    ///
+    const QColor& intelliBoxBackColor() const;
+
+    ///
+    ///  @fn      intelliBoxTextColor : const
+    ///  @brief   Retrieves the text color of the intellisense box.
+    ///  @returns the text color of the intellisense box.
+    ///
+    const QColor& intelliBoxTextColor() const;
+
+    ///
+    ///  @fn      intelliBoxBorderColor : const
+    ///  @brief   Retrieves the border color of the intellisense box.
+    ///  @returns the border color of the intellisense box.
+    ///
+    const QColor& intelliBoxBorderColor() const;
+
+    ///
+    ///  @fn      intelliBoxSelectionBackColor : const
+    ///  @brief   Retrieves the selection back color of the intellisense items.
+    ///  @returns the selection back color of the intellisense items.
+    ///
+    const QColor& intelliBoxSelectionBackColor() const;
+
+    ///
+    ///  @fn      intelliBoxSelectionBorderColor : const
+    ///  @brief   Retrieves the selection border color of the intellisense items.
+    ///  @returns the selection border color of the intellisense items.
+    ///
+    const QColor& intelliBoxSelectionBorderColor() const;
+
+    ///
+    ///  @fn      intelliBoxPressBackColor : const
+    ///  @brief   Retrieves the back color of the intellisense items on mouse-press.
+    ///  @returns the back color of the intellisense items on mouse-press.
+    ///
+    const QColor& intelliBoxPressBackColor() const;
+
+    ///
+    ///  @fn      intelliBoxPressBorderColor : const
+    ///  @brief   Retrieves the border color of the intellisense items on mouse-press.
+    ///  @returns the Press border color of the intellisense items on mouse-press.
+    ///
+    const QColor& intelliBoxPressBorderColor() const;
+
+    ///
+    ///  @fn      editorFont : const
+    ///  @brief   Retrieves the font of the default editor text.
+    ///  @returns a pointer to the editor font.
+    ///
+    const QFont& editorFont() const;
+
+    ///
+    ///  @fn      intelliBoxFont : const
+    ///  @brief   Retrieves the font of the intellisense box text.
+    ///  @returns a pointer to the intellisense box font.
+    ///
+    const QFont& intelliBoxFont() const;
+
+    ///
+    ///  @fn      editorBorder : const
+    ///  @brief   Retrieves the border-width in all directions.
+    ///  @returns a reference to a QMargins instance.
+    ///
+    const QMargins& editorBorder() const;
+
+    ///
+    ///  @fn      intelliBoxBorder : const
+    ///  @brief   Retrieves the border-width in all directions.
+    ///  @returns a reference to a QMargins instance.
+    ///
+    const QMargins& intelliBoxBorder() const;
+
+    ///
+    ///  @fn      lineColumnPadding : const
+    ///  @brief   Retrieves the padding in the right- and left direction.
+    ///  @returns a ref to a QLineColumnPadding instance.
+    ///
+    const QLineColumnPadding& lineColumnPadding() const;
+
+    ///
+    ///  @fn      popupSize : const
+    ///  @brief   Retrieves the size of the auto-completion menu.
+    ///  @returns a ref to a QSize instance.
+    ///
+    const QSize& popupSize() const;
+
+    ///
+    ///  @fn      isLineColumnVisible : const
+    ///  @brief   Determines whether the line column is visible.
+    ///  @returns true if the line column is visible.
+    ///
+    bool isLineColumnVisible() const;
+
+    ///
+    ///  @fn      hasFocusRect : const
+    ///  @brief   Determines whether the intelliBox items should have a focus rectangle.
+    ///  @returns true if a dotted rectangle should be drawn around a focused item.
+    ///
+    bool hasFocusRect() const;
+
+    ///
+    ///  @fn      startsWithOne : const
+    ///  @brief   Determines whether the line numbers start with 1.
+    ///  @returns true if 1 is the first line.
+    ///
+    bool startsWithOne() const;
+
+    ///
+    ///  @fn    setEditorBackColor
+    ///  @brief Specifies the bg color of the code editor.
+    ///  @param color Color to use as background
+    ///
+    void setEditorBackColor( const QColor& color );
+
+    ///
+    ///  @fn    setEditorTextColor
+    ///  @brief Specifies the bg color of the code editor.
+    ///  @param color Color to draw text in
+    ///
+    void setEditorTextColor( const QColor& color );
+
+    ///
+    ///  @fn    setEditorBorderColor
+    ///  @brief Specifies the bg color of the code editor.
+    ///  @param color Color to draw border in
+    ///
+    void setEditorBorderColor( const QColor& color );
+
+    ///
+    ///  @fn    setLineColumnBackColor
+    ///  @brief Specifies the bg color of the line column.
+    ///  @param color Color to use as background
+    ///
+    void setLineColumnBackColor( const QColor& color );
+
+    ///
+    ///  @fn    setLineColumnSeparatorColor
+    ///  @brief Specifies the separator color of the line column.
+    ///  @param color Color to draw separator in
+    ///
+    void setLineColumnSeparatorColor( const QColor& color );
+
+    ///
+    ///  @fn    setLineColumnTextColor
+    ///  @brief Specifies the text color of the line column.
+    ///  @param color Color to draw text in
+    ///
+    void setLineColumnTextColor( const QColor& color );
+
+    ///
+    ///  @fn    setActiveLineColor
+    ///  @brief Specifies the active line color
+    ///  @param color Color to draw active line text in
+    ///
+    void setActiveLineColor( const QColor& color );
+
+    ///
+    ///  @fn    setIntelliBoxBackColor
+    ///  @brief Specifies the bg color of the intelliBox.
+    ///  @param color Color to use as background
+    ///
+    void setIntelliBoxBackColor( const QColor& color );
+
+    ///
+    ///  @fn    setIntelliBoxTextColor
+    ///  @brief Specifies the text color of the intelliBox.
+    ///  @param color Color to draw text in
+    ///
+    void setIntelliBoxTextColor( const QColor& color );
+
+    ///
+    ///  @fn    setIntelliBoxBorderColor
+    ///  @brief Specifies the border color of the intelliBox.
+    ///  @param color Color to draw border in
+    ///
+    void setIntelliBoxBorderColor( const QColor& color );
+
+    ///
+    ///  @fn    setIntelliBoxSelectionBackColor
+    ///  @brief Specifies the bg color of the intelliBox-selection.
+    ///  @param color Color to use as selection background
+    ///
+    void setIntelliBoxSelectionBackColor( const QColor& color );
+
+    ///
+    ///  @fn    setIntelliBoxSelectionBorderColor
+    ///  @brief Specifies the border color of the intelliBox-selection.
+    ///  @param color Color to draw selection border in
+    ///
+    void setIntelliBoxSelectionBorderColor( const QColor& color );
+
+    ///
+    ///  @fn    setIntelliBoxPressBackColor
+    ///  @brief Specifies the bg color of the items on mouse-press.
+    ///  @param color Color to use on mouse-press
+    ///
+    void setIntelliBoxPressBackColor( const QColor& color );
+
+    ///
+    ///  @fn    setIntelliBoxPressBorderColor
+    ///  @brief Specifies the border color of the items on mouse-press.
+    ///  @param color Color to draw border in on mouse-press
+    ///
+    void setIntelliBoxPressBorderColor( const QColor& color );
+
+    ///
+    ///  @fn    setEditorFont
+    ///  @brief Specifies the default font for editor-text.
+    ///  @param font Pointer to font to use for default text
+    ///
+    void setEditorFont( const QFont& font );
+
+    ///
+    ///  @fn    setIntelliBoxFont
+    ///  @brief Specifies the default font for intelliBox-text.
+    ///  @param font Pointer to font to use for default text
+    ///
+    void setIntelliBoxFont( const QFont& font );
+
+    ///
+    ///  @fn    setEditorBorder
+    ///  @brief Specifies the thickness of the editor border.
+    ///  @param border QMargins specifying the thickness in all directions
+    ///
+    void setEditorBorder( const QMargins& border );
+
+    ///
+    ///  @fn    setIntelliBoxBorder
+    ///  @brief Specifies the thickness of the intelliBox border.
+    ///  @param border QMargins specifying the thickness in all directions
+    ///
+    void setIntelliBoxBorder( const QMargins& border );
+
+    ///
+    ///  @fn    setLineColumnPadding
+    ///  @brief Specifies the line column padding.
+    ///  @param padding Ref to instance of QLineColumnPadding
+    ///
+    void setLineColumnPadding( const QLineColumnPadding& padding );
+
+    ///
+    ///  @fn    setPopupSize
+    ///  @brief Specifies the size of the auto-complete menu.
+    ///  @param size Ref to instance of QSize
+    ///
+    void setPopupSize( const QSize& size );
+
+    ///
+    ///  @fn    setLineColumnVisible
+    ///  @brief Determines the visibility of the line column.
+    ///  @param visible True if should be drawn, otherwise false
+    ///
+    void setLineColumnVisible( bool visible );
+
+    ///
+    ///  @fn    showFocusRect
+    ///  @brief Specifies whether to show a dotted rectangle around a focused intelliBox item.
+    ///  @param show True if a dotted rectangle should be drawn.
+    ///
+    void showFocusRect( bool show );
+
+    ///
+    ///  @fn    setFirstLineOne
+    ///  @brief Specifies whether to set the first line as one and not zero.
+    ///  @param one True if line numbers should start with 1.
+    ///
+    void setFirstLineAsOne( bool one );
+
+  private:
+    //
+    // Private class members
+    //
+    QColor m_EditorBackColor;
+    QColor m_EditorTextColor;
+    QColor m_EditorBorderColor;
+    QColor m_LineColumnBackColor;
+    QColor m_LineColumnTextColor;
+    QColor m_LineColumnSeparatorColor;
+    QColor m_ActiveLineColor;
+    QColor m_IntelliBoxBackColor;
+    QColor m_IntelliBoxTextColor;
+    QColor m_IntelliBoxBorderColor;
+    QColor m_IntelliBoxSelectionBackColor;
+    QColor m_IntelliBoxSelectionBorderColor;
+    QColor m_IntelliBoxPressBackColor;
+    QColor m_IntelliBoxPressBorderColor;
+    QFont m_EditorFont;
+    QFont m_IntelliBoxFont;
+    QMargins m_EditorBorder;
+    QMargins m_IntelliBoxBorder;
+    QLineColumnPadding m_LineColumnPadding;
+    QSize m_PopupSize;
+    bool m_HasLineColumn;
+    bool m_ShowFocusRect;
+    bool m_FirstLineOne;
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorEvents.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorEvents.cpp
new file mode 100644
index 0000000..43e7e54
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorEvents.cpp
@@ -0,0 +1,295 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <QAbstractItemView>
+#include <QCompleter>
+#include <QPainter>
+#include <QScrollBar>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditor.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        paintEvent
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::paintEvent( QPaintEvent* event ) {
+    // Paints the text edit and the line column
+    QPlainTextEdit::paintEvent( event );
+
+    // Using style-sheets as for now!
+    /*// Paints a border around the widget, if requested
+    if (!m_Design.editorBorder().isNull()) {
+        QPainter painter(viewport());
+
+        // Changes the pen-color of the painter
+        painter.setBrush(QBrush(m_Design.editorBorderColor()));
+
+        // Draws a line in each direction requested
+        QMargins border = m_Design.editorBorder();
+        if (border.top()) {
+            painter.fillRect(0, 0, width(), border.top(), Qt::SolidPattern);
+        } if (border.left()) {
+            painter.fillRect(0, 0, border.left(), height(), Qt::SolidPattern);
+        } if (border.bottom()) {
+            painter.fillRect(0, height()-border.bottom(), width(), border.bottom(),
+    Qt::SolidPattern); } if (border.right()) { painter.fillRect(width()-border.right(), 0,
+    border.right(), height(), Qt::SolidPattern);
+        }
+    }*/
+}
+
+///
+///  @fn        keyReleaseEvent
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::keyReleaseEvent( QKeyEvent* event ) {
+    if ( event->key() == Qt::Key_Tab ) { return; }
+
+    QPlainTextEdit::keyReleaseEvent( event );
+}
+
+///
+///  @fn        keyPressEvent
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::keyPressEvent( QKeyEvent* event ) {
+    static QChar par( 0x2029 ); // Qt uses paragraph separators
+    static QString tab = QString( " " ).repeated( 4 );
+
+    // The code editor should not receive keys
+    // while the auto complete menu is open.
+    if ( m_AutoComplete->popup()->isVisible() )
+    {
+        switch ( event->key() )
+        {
+        case Qt::Key_Tab:
+        case Qt::Key_Enter:
+        case Qt::Key_Return:
+        case Qt::Key_Escape:
+        case Qt::Key_Backtab:
+            event->ignore();
+            return;
+        default:
+            break;
+        }
+    }
+
+    // Adds tabs in front of the selected block(s)
+    if ( event->key() == Qt::Key_Tab && !textCursor().selectedText().isEmpty() )
+    {
+        // Retrieves the amount of lines within the selected text
+        QTextCursor cursor   = textCursor();
+        QString selected     = cursor.selectedText();
+        qint32 amountOfLines = selected.count( par ) + 1;
+
+        // Does not do anything if only one line is selected
+        if ( amountOfLines == 1 ) { return; }
+
+        // Selects the start of the current line and retrieves the position
+        int linePos, lineCopy;
+        cursor.setPosition( cursor.selectionStart() );
+        cursor.movePosition( QTextCursor::StartOfLine );
+        linePos = lineCopy = cursor.position();
+        cursor.beginEditBlock();
+
+        // Inserts tabs for each selected line
+        for ( int i = 0; i < amountOfLines; ++i )
+        {
+            cursor.setPosition( linePos );
+            cursor.insertText( tab );
+            cursor.movePosition( QTextCursor::Down );
+            cursor.movePosition( QTextCursor::StartOfLine );
+            linePos = cursor.position();
+        }
+
+        // Selects all the text
+        cursor.movePosition( QTextCursor::Down );
+        cursor.movePosition( QTextCursor::EndOfLine );
+        cursor.setPosition( lineCopy, QTextCursor::KeepAnchor );
+        cursor.endEditBlock();
+        setTextCursor( cursor );
+        return;
+    }
+
+    // Removes tabs in front of selected block(s)
+    if ( event->key() == Qt::Key_Backtab && !textCursor().selectedText().isEmpty() )
+    {
+        // Retrieves the amount of lines within the selected text
+        QTextCursor cursor   = textCursor();
+        QString selected     = cursor.selectedText();
+        qint32 amountOfLines = selected.count( par ) + 1;
+
+        // Does not do anything if only one line is selected
+        if ( amountOfLines == 1 ) { return; }
+
+        // Retrieves the start of the selection
+        int start = 0, line, diff, copy;
+        cursor.setPosition( cursor.selectionStart() );
+        cursor.movePosition( QTextCursor::StartOfLine );
+        copy = cursor.position();
+
+        if ( selected.at( 0 ).isSpace() )
+        {
+            cursor.movePosition( QTextCursor::NextWord );
+            start = cursor.position();
+        }
+
+        cursor.clearSelection();
+        cursor.beginEditBlock();
+
+        // Removes a tab from each line
+        for ( int i = 0; i < amountOfLines; ++i )
+        {
+            cursor.setPosition( start );
+            cursor.movePosition( QTextCursor::StartOfLine );
+            line = cursor.position();
+            cursor.setPosition( start );
+
+            if ( start == line )
+            {
+                continue; // nothing to remove
+            }
+
+            diff = qMin( 4, start - line );
+            for ( int i = 0; i < diff; ++i )
+            {
+                cursor.deletePreviousChar();
+            }
+
+            // Finds position of the first word in the next line
+            cursor.movePosition( QTextCursor::Down );
+            cursor.movePosition( QTextCursor::StartOfLine );
+            cursor.movePosition( QTextCursor::NextWord );
+            cursor.movePosition( QTextCursor::StartOfWord );
+            start = cursor.position();
+        }
+
+        // Selects all the text
+        cursor.movePosition( QTextCursor::Down );
+        cursor.movePosition( QTextCursor::EndOfLine );
+        cursor.setPosition( copy, QTextCursor::KeepAnchor );
+        cursor.endEditBlock();
+        setTextCursor( cursor );
+        return;
+    }
+
+    // Replaces a tab with four whitespaces
+    if ( event->key() == Qt::Key_Tab )
+    {
+        QTextCursor cursor = textCursor();
+        cursor.insertText( QString( " " ).repeated( 4 ) );
+        setTextCursor( cursor );
+        return;
+    }
+
+    // Forwards the pressed key to the QPlainTextEdit
+    QPlainTextEdit::keyPressEvent( event );
+
+    // Retrieves the underlying word for further checks
+    QTextCursor cursor = textCursor();
+    cursor.select( QTextCursor::WordUnderCursor );
+
+    // Close intellisense box if the current character is a
+    // whitespace and the backspace key was pressed.
+    if ( event->key() == Qt::Key_Backspace )
+    {
+        if ( cursor.selectedText().trimmed().isEmpty() )
+        {
+            m_AutoComplete->popup()->hide();
+            return;
+        }
+    }
+
+    // Does absolutely nothing if a single modifier key was pressed
+    if ( ( event->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier ) ) &&
+         event->text().isEmpty() )
+    { return; }
+
+    // Does absolutely nothing if:
+    // the word is interrupted by an invalid character
+    // the word is too short to trigger a completion
+    static QString invalidChars( "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=" );
+    if ( event->text().isEmpty() || cursor.selectedText().length() < m_CompletionTrigger ||
+         invalidChars.contains( event->text().right( 1 ) ) )
+    {
+
+        // Hides the completion menu
+        m_AutoComplete->popup()->hide();
+        return;
+    }
+
+    // Filters the keyword list
+    QString prefix = QString( "^" ) + cursor.selectedText();
+    m_RuleFilter->setFilterRegExp( QRegExp( prefix, Qt::CaseInsensitive ) );
+    m_AutoComplete->popup()->setCurrentIndex( m_AutoComplete->completionModel()->index( 0, 0 ) );
+
+    // Determines whether any match has been found
+    if ( m_AutoComplete->popup()->model()->rowCount() == 0 )
+    {
+        m_AutoComplete->popup()->hide();
+        return;
+    }
+
+    // Shows the auto-complete box, if not already
+    if ( !m_AutoComplete->popup()->isVisible() )
+    {
+        // Sets the position of the popup menu and shows it
+        QRect rect = cursorRect();
+        rect.moveTo( rect.x() + lineColumnWidth() - fontMetrics().horizontalAdvance( prefix ),
+                     rect.y() + 4 );
+        rect.setWidth( m_AutoComplete->popup()->sizeHintForColumn( 0 ) +
+                       m_AutoComplete->popup()->verticalScrollBar()->sizeHint().width() );
+
+        m_AutoComplete->complete( rect );
+    }
+}
+
+///
+///  @fn        resizeEvent
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::resizeEvent( QResizeEvent* event ) {
+    Q_UNUSED( event );
+
+    // Makes space for the line widget
+    if ( m_Design.isLineColumnVisible() )
+    {
+        QRect content = contentsRect();
+        setViewportMargins( lineColumnWidth(), 0, 0, 0 );
+        m_LineWidget->setGeometry(
+            content.left(), content.top(), lineColumnWidth(), content.height() );
+    }
+    else
+    {
+        setViewportMargins( 0, 0, 0, 0 );
+        m_LineWidget->setGeometry( 0, 0, 0, 0 );
+    }
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.cpp
new file mode 100644
index 0000000..f0e6e9b
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.cpp
@@ -0,0 +1,244 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <RadiumNBR/Gui/CodeEditor/CodeEditor.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.hpp>
+
+#include <QUuid>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        Constructor
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QCodeEditorHighlighter::QCodeEditorHighlighter( QCodeEditor* parent ) :
+    QSyntaxHighlighter( parent->document() ),
+    m_Rules( &parent->rules() ),
+    m_Design( &parent->design() ),
+    m_Parent( parent ) {}
+
+///
+///  @fn        Destructor
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QCodeEditorHighlighter::~QCodeEditorHighlighter() {}
+
+///
+///  @fn        updateFormats
+///  @author    Nicolas Kogler
+///  @date      October 8th, 2016
+///
+void QCodeEditorHighlighter::updateFormats() {
+
+    m_Formats.clear();
+
+    // Pre-parses the rules' style into a list of QTextCharFormat
+    for ( const QSyntaxRule& rule : m_Parent->rules() )
+    {
+        QTextCharFormat format;
+
+        if ( rule.useFont() ) { format.setFont( rule.font() ); }
+        else
+        { format.setFont( m_Parent->font() ); }
+        if ( rule.foreColor().alpha() == 0 )
+        { format.setForeground( QBrush( m_Parent->design().editorTextColor() ) ); }
+        else
+        { format.setForeground( rule.foreColor() ); }
+
+        format.setBackground( QBrush( rule.backColor() ) );
+        m_Formats.push_back( format );
+    }
+}
+
+///
+///  @fn        setHighlighting
+///  @author    Nicolas Kogler
+///  @date      October 12th, 2016
+///
+void QCodeEditorHighlighter::setHighlighting( int start,
+                                              int length,
+                                              const QTextCharFormat& format ) {
+    setFormat( start, length, format );
+}
+
+///
+///  @fn        highlightBlock
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+void QCodeEditorHighlighter::highlightBlock( const QString& text ) {
+    if ( currentBlockUserData() != NULL )
+    {
+        auto d = static_cast<QCodeEditorBlockData*>( currentBlockUserData() );
+        QRegularExpression regex( d->re );
+        if ( !regex.match( text ).hasMatch() ) { onRemove( d ); }
+    }
+
+    int ruleIndex = 0;
+    setCurrentBlockState( -1 );
+
+    // Applies highlighting rules
+    const QList<QSyntaxRule>& rules = *m_Rules;
+    for ( const QSyntaxRule& rule : rules )
+    {
+        const QTextCharFormat& format = m_Formats.at( ruleIndex );
+        QRegularExpression regex( rule.regex() );
+        QRegularExpressionMatch match;
+
+        if ( rule.isGlobal() )
+        {
+
+            // Searches for more than one match
+            QRegularExpressionMatchIterator iter = regex.globalMatch( text );
+
+            if ( iter.hasNext() && !rule.closeRegex().isEmpty() && currentBlockState() == -1 )
+            { setCurrentBlockState( ruleIndex ); }
+
+            // Iterates through all other matches and highlights them
+            while ( iter.hasNext() )
+            {
+                match = iter.next();
+                setFormat( match.capturedStart(), match.capturedLength(), format );
+                if ( !rule.id().isEmpty() )
+                {
+                    if ( currentBlockUserData() == NULL )
+                    {
+                        setCurrentBlockUserData( new QCodeEditorBlockData( rule.regex() ) );
+                        emit onMatch( rule, match.captured(), currentBlock() );
+                    }
+                    else
+                    {
+                        auto d = static_cast<QCodeEditorBlockData*>( currentBlockUserData() );
+                        if ( d->re == rule.regex() )
+                        {
+                            // Already containing a match that has the exact regex:
+                            // Remove it first, then add it again
+                            emit onRemove( d );
+                            setCurrentBlockUserData( new QCodeEditorBlockData( rule.regex() ) );
+                            emit onMatch( rule, match.captured(), currentBlock() );
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+
+            // Searches for only one match
+            match = regex.match( text );
+
+            if ( match.hasMatch() )
+            {
+                if ( !rule.closeRegex().isEmpty() && currentBlockState() == -1 )
+                {
+                    // Before setting the multiline trigger, checks if
+                    // the closing sequence is on the same line.
+                    QRegularExpression mulEnd( rule.closeRegex() );
+                    if ( !mulEnd.match( text ).hasMatch() ) setCurrentBlockState( ruleIndex );
+                }
+                if ( !rule.id().isEmpty() )
+                {
+                    if ( currentBlockUserData() == NULL )
+                    {
+                        setCurrentBlockUserData( new QCodeEditorBlockData( rule.regex() ) );
+                        emit onMatch( rule, match.captured(), currentBlock() );
+                    }
+                    else
+                    {
+                        auto d = static_cast<QCodeEditorBlockData*>( currentBlockUserData() );
+                        if ( d->re == rule.regex() )
+                        {
+                            // Already containing a match that has the exact regex:
+                            // Remove it first, then add it again
+                            emit onRemove( d );
+                            setCurrentBlockUserData( new QCodeEditorBlockData( rule.regex() ) );
+                            emit onMatch( rule, match.captured(), currentBlock() );
+                        }
+                    }
+                }
+
+                setFormat( match.capturedStart(), match.capturedLength(), format );
+            }
+        }
+
+        ++ruleIndex;
+    }
+
+    // If there has been a multi-line-rule match in the previous
+    // block, we need to check against its closing regex.
+    if ( previousBlockState() != -1 )
+    {
+        const QSyntaxRule& rule      = m_Rules->at( previousBlockState() );
+        const QTextCharFormat format = m_Formats.at( previousBlockState() );
+        QRegularExpression regex( rule.closeRegex() );
+        QRegularExpressionMatch match = regex.match( text );
+
+        // If now has a match, ends the multi-line regex
+        if ( match.hasMatch() )
+        {
+            setFormat( match.capturedStart(), match.capturedLength(), format );
+            setCurrentBlockState( -1 );
+
+            if ( !rule.id().isEmpty() )
+            {
+                if ( currentBlockUserData() == NULL )
+                {
+                    setCurrentBlockUserData( new QCodeEditorBlockData( rule.regex() ) );
+                    emit onMatch( rule, match.captured(), currentBlock() );
+                }
+                else
+                {
+                    auto d = static_cast<QCodeEditorBlockData*>( currentBlockUserData() );
+                    if ( d->re == rule.regex() )
+                    {
+                        // Already containing a match that has the exact regex:
+                        // Remove it first, then add it again
+                        emit onRemove( d );
+                        setCurrentBlockUserData( new QCodeEditorBlockData( rule.regex() ) );
+                        emit onMatch( rule, match.captured(), currentBlock() );
+                    }
+                }
+            }
+        }
+        else
+        {
+            // Has no match, highlights the entire line and
+            // forwards the previous state to the next line.
+            setFormat( 0, text.length(), format );
+            setCurrentBlockState( previousBlockState() );
+        }
+    }
+
+    // Provides custom highlighting logic
+    emit onHighlight( this );
+}
+
+///
+///  @brief Defines the global uuid list
+///
+QList<QUuid> QCodeEditorBlockData::p;
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.hpp
new file mode 100644
index 0000000..8d333f4
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.hpp
@@ -0,0 +1,142 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+//
+//  Included headers
+//
+
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp>
+#include <RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp>
+
+#include <QObject>
+#include <QSyntaxHighlighter>
+#include <QTextBlockUserData>
+#include <QTextDocument>
+
+namespace RadiumNBR::Gui {
+
+//
+// Forward declarations
+//
+class QCodeEditor;
+class QCodeEditorBlockData;
+
+///
+///  @file      QCodeEditorHighlighter.hpp
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///  @class     QCodeEditorHighlighter
+///  @brief     Highlights keywords, functions, ...
+///
+class NodeBasedRenderer_LIBRARY_API QCodeEditorHighlighter : public QSyntaxHighlighter
+{
+    Q_OBJECT
+  public:
+    ///
+    ///  @fn    Constructor
+    ///  @brief Initializes a new instance of QCodeEditorHighlighter.
+    ///
+    QCodeEditorHighlighter( QCodeEditor* parent );
+
+    ///
+    ///  @fn    Destructor
+    ///  @brief Frees all resources allocated by QCodeEditorHighlighter.
+    ///
+    ~QCodeEditorHighlighter();
+
+    ///
+    ///  @fn    updateFormats
+    ///  @brief Updates the text char formats.
+    ///
+    ///  Always call after setting new rules.
+    ///
+    void updateFormats();
+
+    ///
+    ///  @fn    setHighlighting
+    ///  @brief Applies some visual styling to text in the current line.
+    ///  @param start Start index to apply styling to
+    ///  @param length Length of the text to style
+    ///  @param format Format to apply
+    ///
+    void setHighlighting( int start, int length, const QTextCharFormat& format );
+
+  signals:
+
+    ///
+    ///  @fn    onMatch : signal
+    ///  @brief Will fire if a match is found.
+    ///
+    ///  The signal will only fire if the rule containing the match
+    ///  has a valid and unique string identifier (e.g <rule id="foo">)
+    ///
+    ///  @param rule The rule that emitted this signal
+    ///  @param sequence The matched sequence
+    ///  @param block The current QTextBlock
+    ///
+    void onMatch( const QSyntaxRule& rule, QString sequence, QTextBlock block );
+
+    ///
+    ///  @fn    onHighlight : signal
+    ///  @brief Will fire if a line was highlighted.
+    ///
+    ///  Gives the possibility to add own highlighting logic afterwards.
+    ///
+    ///  @param highlighter Pointer to this highlighter instance
+    ///
+    void onHighlight( QCodeEditorHighlighter* highlighter );
+
+    ///
+    ///  @fn    onRemove : signal
+    ///  @brief Will fire if a line's highlighting was removed.
+    ///  @param data Data containing the UUID.
+    ///
+    void onRemove( QCodeEditorBlockData* data );
+
+  protected:
+    ///
+    ///  @fn    highlightBlock
+    ///  @brief Highlights the given text line.
+    ///  @param text Current line to process
+    ///
+    void highlightBlock( const QString& text ) Q_DECL_OVERRIDE;
+
+  private:
+    //
+    // Private class members
+    //
+    const QList<QSyntaxRule>* m_Rules;
+    const QCodeEditorDesign* m_Design;
+    const QCodeEditor* m_Parent;
+    QList<QTextCharFormat> m_Formats;
+};
+
+///
+///  @file      QCodeEditorHighlighter.hpp
+///  @author    Nicolas Kogler
+///  @date      October 29th, 2016
+///  @class     QCodeEditorBlockData
+///  @brief     Holds an unique identifier.
+///
+class QCodeEditorBlockData : public QTextBlockUserData
+{
+  public:
+    ///  @brief Tries to create a unique QUuid
+    QCodeEditorBlockData( QString r ) {
+        // Ensures that ID really is unique!
+        do
+        { id = QUuid::createUuid(); } while ( p.contains( id ) );
+
+        p.push_back( id );
+        re = r;
+    }
+
+    ~QCodeEditorBlockData() { p.removeOne( id ); }
+
+    QUuid id;   ///< Unique identifier for each match
+    QString re; ///< Causing regular expression
+
+  private:
+    static QList<QUuid> p; ///< Holds all IDs to check uniqueness
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.cpp
new file mode 100644
index 0000000..a9cd320
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.cpp
@@ -0,0 +1,125 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp>
+
+#include <QPainter>
+#include <QTextBlock>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        Constructor
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QCodeEditorLineWidget::QCodeEditorLineWidget( QCodeEditor* parent ) :
+    QWidget( parent ), m_Parent( parent ), m_EditorView( parent->viewport() ) {}
+
+///
+///  @fn        Destructor
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QCodeEditorLineWidget::~QCodeEditorLineWidget() {}
+
+///
+///  @fn        sizeHint
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QSize QCodeEditorLineWidget::sizeHint() const {
+    if ( m_Parent->design().isLineColumnVisible() )
+    { return QSize( m_Parent->lineColumnWidth(), 0 ); }
+    else
+    {
+        return QSize( 0, 0 ); // "Hide" line column
+    }
+}
+
+///
+///  @fn        paintEvent
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+void QCodeEditorLineWidget::paintEvent( QPaintEvent* event ) {
+
+    if ( !m_Parent->design().isLineColumnVisible() ) { return; }
+
+    // Retrieves the content rectangle and creates the QPainter
+    const QCodeEditorDesign& design = m_Parent->design();
+    const QRect& content            = event->rect();
+    QPainter painter( this );
+
+    // Paints the background and the separator
+    painter.fillRect( content, design.lineColumnBackColor() );
+    painter.setPen( design.lineColumnSeparatorColor() );
+    painter.drawLine( content.width() - 1, 0, content.width() - 1, height() - 1 );
+    painter.setPen( design.lineColumnTextColor() );
+
+    // Retrieves the visible line numbers
+    QTextBlock firstLine = m_Parent->firstVisibleBlock();
+    qint32 bnActive = m_Parent->textCursor().blockNumber() + ( ( design.startsWithOne() ) ? 1 : 0 );
+    qint32 blockNumber = firstLine.blockNumber() + ( ( design.startsWithOne() ) ? 1 : 0 );
+    qint32 blockTop    = static_cast<int>( m_Parent->blockBoundingGeometry( firstLine )
+                                            .translated( m_Parent->contentOffset() )
+                                            .top() );
+    qint32 blockBottom =
+        static_cast<int>( m_Parent->blockBoundingRect( firstLine ).height() ) + blockTop;
+
+    // Paints all visible line numbers
+    while ( firstLine.isValid() && blockTop <= content.bottom() )
+    {
+        if ( firstLine.isVisible() && blockBottom >= content.top() )
+        {
+            if ( blockNumber == bnActive )
+            {
+                painter.setPen( design.activeLineColor() );
+                painter.drawText( 0,
+                                  blockTop,
+                                  width(),
+                                  fontMetrics().height(),
+                                  Qt::AlignCenter,
+                                  QString::number( blockNumber ) );
+                painter.setPen( design.lineColumnTextColor() );
+            }
+            else
+            {
+                painter.drawText( 0,
+                                  blockTop,
+                                  width(),
+                                  fontMetrics().height(),
+                                  Qt::AlignCenter,
+                                  QString::number( blockNumber ) );
+            }
+        }
+
+        // Jumps to the next line
+        blockNumber++;
+        firstLine = firstLine.next();
+        blockTop  = blockBottom;
+        blockBottom += static_cast<int>( m_Parent->blockBoundingRect( firstLine ).height() );
+    }
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp
new file mode 100644
index 0000000..5e8f4c0
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp
@@ -0,0 +1,56 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+//
+//  Included headers
+//
+#include <QWidget>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditor.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @file      QCodeEditorLineWidget.hpp
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///  @class     QCodeEditorLineWidget
+///  @brief     Paints the line column and the line numbers.
+///
+class NodeBasedRenderer_LIBRARY_API QCodeEditorLineWidget : public QWidget
+{
+  public:
+    ///
+    ///  @fn    Constructor
+    ///  @brief Initializes a new instance of QCodeEditorLineWidget.
+    ///
+    QCodeEditorLineWidget( QCodeEditor* parent );
+
+    ///
+    ///  @fn    Destructor
+    ///  @brief Frees all resources allocated by QCodeEditorLineWidget.
+    ///
+    ~QCodeEditorLineWidget();
+
+    ///
+    ///  @fn      sizeHint
+    ///  @brief   Reserves space for the line widget.
+    ///  @returns the desired size.
+    ///
+    QSize sizeHint() const Q_DECL_OVERRIDE;
+
+  protected:
+    ///
+    ///  @fn    paintEvent
+    ///  @brief Paints the line column and the line numbers.
+    ///  @param event Pointer to a QPaintEvent instance
+    ///
+    void paintEvent( QPaintEvent* event ) Q_DECL_OVERRIDE;
+
+  private:
+    //
+    // Private class members
+    //
+    QCodeEditor* m_Parent;
+    QWidget* m_EditorView;
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorPopup.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorPopup.cpp
new file mode 100644
index 0000000..9368ff1
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorPopup.cpp
@@ -0,0 +1,91 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorPopup.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorSheets.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        Constructor
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QCodeEditorPopup::QCodeEditorPopup( QCodeEditor* parent ) :
+    QListView( parent ), m_Parent( parent ) {
+
+    // Generates the stylesheets from the visual properties
+    m_StyleSheetNormal = QCodeEditorPopupSheets::hover( parent->design() );
+    m_StyleSheetPress  = QCodeEditorPopupSheets::press( parent->design() );
+
+    // Changes listview properties
+    setMouseTracking( true );
+    setFrameShape( QFrame::NoFrame );
+    setSelectionMode( QAbstractItemView::SingleSelection );
+    setSelectionBehavior( QAbstractItemView::SelectItems );
+    setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
+    setFixedWidth( parent->design().popupSize().width() );
+    setFixedHeight( parent->design().popupSize().height() );
+    setStyleSheet( m_StyleSheetNormal );
+
+    // Applies several other properties
+    setFont( parent->design().intelliBoxFont() );
+}
+
+///
+///  @fn        Destructor
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QCodeEditorPopup::~QCodeEditorPopup() {}
+
+///
+///  @fn        viewportEvent
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+bool QCodeEditorPopup::viewportEvent( QEvent* event ) {
+    if ( event->type() == QEvent::MouseMove )
+    {
+        // Retrieves the item at the current mouse position
+        QMouseEvent* me   = static_cast<QMouseEvent*>( event );
+        QModelIndex index = indexAt( me->pos() );
+
+        // Selects the item at the mouse cursor position
+        selectionModel()->setCurrentIndex( index, QItemSelectionModel::ClearAndSelect );
+    }
+    else if ( event->type() == QEvent::MouseButtonPress )
+    {
+        // This is a little hack: There is no 'pressed' pseudo class
+        // to style the listview item on mouse-press, therefore we
+        // dynamically change the style-sheet.
+        if ( !selectedIndexes().isEmpty() ) { setStyleSheet( m_StyleSheetPress ); }
+    }
+    else if ( event->type() == QEvent::MouseButtonRelease )
+    { setStyleSheet( m_StyleSheetNormal ); }
+
+    // Processes the default event logic
+    return QListView::viewportEvent( event );
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorPopup.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorPopup.hpp
new file mode 100644
index 0000000..de1b940
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorPopup.hpp
@@ -0,0 +1,51 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+//
+//  Included headers
+//
+#include <QListView>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditor.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @file      QCodeEditorPopup.hpp
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///  @class     QCodeEditorPopup
+///  @brief
+///
+class NodeBasedRenderer_LIBRARY_API QCodeEditorPopup : public QListView
+{
+  public:
+    ///
+    ///  @fn    Constructor
+    ///  @brief Initializes a new instance of QCodeEditorPopup.
+    ///
+    QCodeEditorPopup( QCodeEditor* parent );
+
+    ///
+    ///  @fn    Destructor
+    ///  @brief Frees all resources allocated by QCodeEditorPopup.
+    ///
+    ~QCodeEditorPopup();
+
+  protected:
+    ///
+    /// @fn      viewportEvent
+    /// @brief   Intercepts events for the QCodeEditor viewport.
+    /// @param   event Event of unknown type
+    /// @returns true to indicate we have handled the event ourselves.
+    ///
+    bool viewportEvent( QEvent* event ) Q_DECL_OVERRIDE;
+
+  private:
+    //
+    // Private class members
+    //
+    QString m_StyleSheetNormal; ///< Holds the stylesheet on mouse-hover
+    QString m_StyleSheetPress;  ///< Holds the stylesheet on mouse-press
+    QCodeEditor* m_Parent;      ///< Holds the parent for design-property access
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorResources.qrc b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorResources.qrc
new file mode 100644
index 0000000..aec566a
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorResources.qrc
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="CodeEditor">
+        <file>EditorDefaultDesign.xml</file>
+        <file>HighlightRules_cpp.xml</file>
+    </qresource>
+</RCC>
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSheets.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSheets.cpp
new file mode 100644
index 0000000..cc39bed
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSheets.cpp
@@ -0,0 +1,98 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorSheets.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        border
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QString QCodeEditorSheets::border( const QCodeEditorDesign& design ) {
+    QString sheet( CSS_Editor_Widget );
+    const QMargins& border = design.editorBorder();
+
+    // Replaces each variable with the respective design property
+    sheet.replace( "%t", QString::number( border.top() ) );
+    sheet.replace( "%r", QString::number( border.right() ) );
+    sheet.replace( "%b", QString::number( border.bottom() ) );
+    sheet.replace( "%l", QString::number( border.left() ) );
+    sheet.replace( "%c", QString::number( design.editorBorderColor().rgba(), 16 ) );
+
+    // Returns the modified sheet; can be applied immediately
+    return sheet;
+}
+
+///
+///  @fn        hover
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QString QCodeEditorPopupSheets::hover( const QCodeEditorDesign& design ) {
+    QString sheet( CSS_Popup_Widget );
+
+    // Replaces each variable with the respective design property
+    sheet.replace( "%border", QString::number( design.intelliBoxBorderColor().rgba(), 16 ) );
+    sheet.replace( "%back", QString::number( design.intelliBoxBackColor().rgba(), 16 ) );
+    sheet.replace( "%text", QString::number( design.intelliBoxTextColor().rgba(), 16 ) );
+    sheet.replace( "%focus", design.hasFocusRect() ? "dotted" : "none" );
+    sheet.replace( "%selbrd",
+                   QString::number( design.intelliBoxSelectionBorderColor().rgba(), 16 ) );
+    sheet.replace( "%selback",
+                   QString::number( design.intelliBoxSelectionBackColor().rgba(), 16 ) );
+    sheet.replace( "%t", QString::number( design.intelliBoxBorder().top() ) );
+    sheet.replace( "%r", QString::number( design.intelliBoxBorder().right() ) );
+    sheet.replace( "%b", QString::number( design.intelliBoxBorder().bottom() ) );
+    sheet.replace( "%l", QString::number( design.intelliBoxBorder().left() ) );
+
+    // Returns the modified sheet; can be applied immediately
+    return sheet;
+}
+
+///
+///  @fn        press
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QString QCodeEditorPopupSheets::press( const QCodeEditorDesign& design ) {
+    QString sheet( CSS_Popup_Widget );
+
+    // Replaces each variable with the respective design property
+    sheet.replace( "%border", QString::number( design.intelliBoxBorderColor().rgba(), 16 ) );
+    sheet.replace( "%back", QString::number( design.intelliBoxBackColor().rgba(), 16 ) );
+    sheet.replace( "%text", QString::number( design.intelliBoxTextColor().rgba(), 16 ) );
+    sheet.replace( "%focus", design.hasFocusRect() ? "dotted" : "none" );
+    sheet.replace( "%selbrd", QString::number( design.intelliBoxPressBorderColor().rgba(), 16 ) );
+    sheet.replace( "%selback", QString::number( design.intelliBoxPressBackColor().rgba(), 16 ) );
+    sheet.replace( "%t", QString::number( design.intelliBoxBorder().top() ) );
+    sheet.replace( "%r", QString::number( design.intelliBoxBorder().right() ) );
+    sheet.replace( "%b", QString::number( design.intelliBoxBorder().bottom() ) );
+    sheet.replace( "%l", QString::number( design.intelliBoxBorder().left() ) );
+
+    // Returns the modified sheet; can be applied immediately
+    return sheet;
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSheets.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSheets.hpp
new file mode 100644
index 0000000..e0918b5
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSheets.hpp
@@ -0,0 +1,91 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @file      QCodeEditorSheets.hpp
+///  @author    Nicolas Kogler
+///  @date      October 7th, 2016
+///  @def       CSS_Editor_Widget
+///  @brief     Stylesheet for the editor widget.
+///
+const char CSS_Editor_Widget[] = {"QPlainTextEdit {"
+                                  "   border-top: %tpx solid #%c;"
+                                  "   border-right: %rpx solid #%c;"
+                                  "   border-bottom: %bpx solid #%c;"
+                                  "   border-left: %lpx solid #%c;"
+                                  "}"};
+
+///
+///  @file      QCodeEditorSheets.hpp
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///  @def       CSS_Popup_Widget
+///  @brief     Stylesheet for the popup widget.
+///
+const char CSS_Popup_Widget[] = {"QListView {"
+                                 "   border-top: %tpx solid #%border;"
+                                 "   border-left: %lpx solid #%border;"
+                                 "   border-right: %rpx solid #%border;"
+                                 "   border-bottom: %bpx solid #%border;"
+                                 "   background-color: #%back;"
+                                 "   color: #%text;"
+                                 "   outline: %focus;"
+                                 "}"
+                                 "QListView::item:selected {"
+                                 "   padding: -1px;"
+                                 "   border: 1px solid #%selbrd;"
+                                 "   background-color: #%selback;"
+                                 "   color: #%text;"
+                                 "}"
+                                 "QListView::item:!selected:hover {"
+                                 "   background: transparent;"
+                                 "}"};
+
+///
+///  @file      QCodeEditorSheets.hpp
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///  @class     QCodeEditorSheets
+///
+class QCodeEditorSheets
+{
+  public:
+    ///
+    ///  @fn      border
+    ///  @brief   Retrieves the style-sheet for the border.
+    ///  @param   design Current code editor design
+    ///  @returns the style-sheet for the border.
+    ///
+    static QString border( const QCodeEditorDesign& design );
+};
+
+///
+///  @file      QCodeEditorSheets.hpp
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///  @class     QCodeEditorPopupSheets
+///
+class QCodeEditorPopupSheets
+{
+  public:
+    ///
+    ///  @fn      hover
+    ///  @brief   Retrieves the style-sheet for mouse-hover.
+    ///  @param   design Current code editor design
+    ///  @returns the style-sheet for mouse-hovers.
+    ///
+    static QString hover( const QCodeEditorDesign& design );
+
+    ///
+    ///  @fn      press
+    ///  @brief   Retrieves the style-sheet for mouse-press.
+    ///  @param   design Current code editor design
+    ///  @returns the style-sheet for mouse-presses.
+    ///
+    static QString press( const QCodeEditorDesign& design );
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSlots.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSlots.cpp
new file mode 100644
index 0000000..94c587a
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/CodeEditorSlots.cpp
@@ -0,0 +1,86 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <QCompleter>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditor.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorLineWidget.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        updateLineColumn
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::updateLineColumn( int lineCount ) {
+    Q_UNUSED( lineCount );
+    setViewportMargins( lineColumnWidth(), 0, 0, 0 );
+}
+
+///
+///  @fn        scrollLineColumn
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::scrollLineColumn( QRect view, int scroll ) {
+    // Scrolls the line widget to the current scrollbar value
+    if ( m_Design.isLineColumnVisible() )
+    {
+        if ( scroll != 0 ) { m_LineWidget->scroll( 0, scroll ); }
+        else
+        { m_LineWidget->update( 0, view.y(), m_LineWidget->width(), view.height() ); }
+
+        // Changes margins, line number digits may have changed
+        setViewportMargins( lineColumnWidth(), 0, 0, 0 );
+    }
+    else
+    { setViewportMargins( 0, 0, 0, 0 ); }
+}
+
+///
+///  @fn        completeWord
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QCodeEditor::completeWord( const QString& word ) {
+    QTextCursor caretPos = textCursor();
+
+    // Inserts the missing characters at the current pos
+    caretPos.movePosition( QTextCursor::Left );
+    caretPos.movePosition( QTextCursor::StartOfWord );
+    caretPos.select( QTextCursor::WordUnderCursor );
+    caretPos.removeSelectedText();
+    caretPos.insertText( word );
+    setTextCursor( caretPos );
+}
+
+///
+///  @fn        textChanged
+///  @author    Nicolas Kogler
+///  @date      October 20th, 2016
+///
+void QCodeEditor::textChanged() {
+    emit lineChanged( textCursor().block() );
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/EditorDefaultDesign.xml b/src/libRender/RadiumNBR/Gui/CodeEditor/EditorDefaultDesign.xml
new file mode 100644
index 0000000..0426505
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/EditorDefaultDesign.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<design>
+    <!-- Order of declaration and character case does not matter -->
+    <editorbackcolor>#222222</editorbackcolor>
+    <editortextcolor>#eeeeee</editortextcolor>
+    <editorbordercolor>#b9b9b9</editorbordercolor>
+    <linecolumnbackcolor>#e9e9e9</linecolumnbackcolor>
+    <linecolumntextcolor>#6a9fc6</linecolumntextcolor>
+    <linecolumnseparatorcolor>#b9b9b9</linecolumnseparatorcolor>
+    <activelinecolor>#fc9100</activelinecolor>
+    <intelliboxbackcolor>#333333</intelliboxbackcolor>
+    <intelliboxtextcolor>#fafafa</intelliboxtextcolor>
+    <intelliboxbordercolor>#b9b9b9</intelliboxbordercolor>
+    <intelliboxselectionbackcolor>#c0dcf3</intelliboxselectionbackcolor>
+    <intelliboxselectionbordercolor>#90c8f6</intelliboxselectionbordercolor>
+    <intelliboxpressbackcolor>#90c8f6</intelliboxpressbackcolor>
+    <intelliboxpressbordercolor>#60b0f9</intelliboxpressbordercolor>
+    <editorborder>0 0 0 0</editorborder> <!-- left, top, right, bottom -->
+    <intelliboxborder>1 1 1 1</intelliboxborder>
+    <linecolumnpadding>16 16</linecolumnpadding> <!-- left, right -->
+    <popupsize>400 300</popupsize> <!-- width, height -->
+    <haslinecolumn>true</haslinecolumn>
+    <showfocusrect>false</showfocusrect>
+    <firstlineone>true</firstlineone>
+</design>
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/HighlightRules_cpp.xml b/src/libRender/RadiumNBR/Gui/CodeEditor/HighlightRules_cpp.xml
new file mode 100644
index 0000000..9f2c146
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/HighlightRules_cpp.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<rules>
+    <rule>
+        <!-- Styles binary, hexadecimal and decimal numbers -->
+        <regex>(\b\d+\b)|(\b0[xX][0-9a-fA-F]+\b)|(\b0[b][01]+\b)</regex>
+        <forecolor>#fc9100</forecolor>
+    </rule>
+    <rule>
+        <!-- Styles all C++ operators -->
+        <regex>(\B|\b)(::|\.|-&gt;|\[\]|\(\)|\+\+|-=|--|~|!|-|\+=|\+|&amp;&amp;|&amp;=|&amp;|\*=|\*|\/=|\/|%=|%|&lt;&lt;=|&lt;&lt;|&gt;&gt;=|&gt;&gt;|&lt;=|&lt;|&gt;=|&gt;|==|!=|\|\||\|=|\||\?|:|\^=|\^|\,)(\B|\b)</regex>
+        <font>
+            <bold>true</bold>
+        </font>
+    </rule>
+    <rule>
+        <!-- Styles strings and muli-line strings -->
+        <regex>(\&quot;|&lt;)((\\.)|[^\\&quot;])*(\&quot;|&gt;)</regex>
+        <forecolor>#fc9100</forecolor>
+    </rule>
+    <rule global="false">
+        <!-- Styles the C++ preprocessor diretives -->
+        <keywords start="true">
+            #include #define #undef #if #ifdef #ifndef #error #pragma
+        </keywords>
+        <forecolor>#ca5179</forecolor>
+    </rule>
+    <rule>
+        <!-- Styles predefined compiler values like __FILE__ -->
+        <keywords>
+            defined __FILE__ __LINE__ __DATE__ __TIME__ __TIMESTAMP__
+        </keywords>
+        <forecolor>#ca5179</forecolor>
+    </rule>
+    <rule id="macro" global="false">
+        <!-- Styles definitions defined via #define -->
+        <regex>(\s*#define\s+\K)\S+(?=\s+\S+)</regex>
+        <forecolor>#795db2</forecolor>
+    </rule>
+    <rule>
+        <!-- Styles all C++ keywords -->
+        <keywords>
+            alignas alignof and and_eq asm auto bitand bitor bool break case catch char char16_t char32_t
+            class compl const constexpr const_cast continue decltype default delete do double dynamic_cast
+            else enum explicit export extern false float for friend goto if inline int long mutable namespace
+            new noexcept not not_eq nullptr operator or or_eq private protected public register reinterpret_cast
+            return short signed sizeof static static_assert static_cast struct switch template this thread_local
+            throw true try typedef typeid typename union unsigned using virtual void volatile wchar_t while
+            xor xor_eq override final
+        </keywords>
+        <forecolor>#2b8f49</forecolor>
+    </rule>
+    <rule global="false">
+        <!-- Styles an enum or class type -->
+        <regex>((class\s+\K)|(enum\s+\K)|(namespace\s+\K))[A-Za-z]\w*</regex>
+        <forecolor>#3392ac</forecolor>
+    </rule>
+    <rule global="false">
+        <!-- Styles multi-line comments -->
+        <startRegex>(\/\*.*\*\/)|(\/\*.*)</startRegex>
+        <closeRegex>.*\*\/</closeRegex>
+        <forecolor>#969698</forecolor>
+    </rule>
+    <rule global="false">
+        <!-- Styles comments -->
+        <regex>(\/\*([\s\S]*?)\*\/)|(\/\/.*)</regex>
+        <forecolor>#969698</forecolor>
+    </rule>
+    <rule global="false">
+        <!-- Styles doxygen keywords -->
+        <regex>(\/(\/|\*)(\/|!|\*)\s*\K)(\\|@)(addindex|addtogroup|anchor|arg|attention|authors|author|a|brief|bug|b|callergraph|callgraph|cite|class|code|cond|copybrief|copydetails|copydoc|copyright|c|date|def|defgroup|deprecated|details|diafile|dir|docbookonly|dontinclude|dot|dotfile|e|else|elseif|em|endcode|endcond|enddocbookonly|enddot|endhtmlonly|endif|endinternal|endlatexonly|endmsc|endparblock|enduml|enum|example|exception|extends|file|fn|headerfile|hidecallergraph|hidecallgraph|htmlonly|if|ifnot|image|implements|include|includedoc|ingroup|internal|interface|invariant|latexinclude|latexonly|mainpage|manonly|memberof|msc|mscfile|name|namespace|note|overload|package|page|par|paragraph|param|parblock|post|pre|private|property|protected|protocol|public|pure|p|ref|refitem|related|remark|remarks|result|return|returns|retval|section|see|short|since|skip|snippet|startuml|struct|throw|throws|todo|typedef|union|until|var|version|warning|xmlonly)\b</regex>
+        <forecolor>#969698</forecolor>
+        <font>
+            <bold>true</bold>
+        </font>
+    </rule>
+</rules>
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/LineColumnPadding.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/LineColumnPadding.cpp
new file mode 100644
index 0000000..112e7ce
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/LineColumnPadding.cpp
@@ -0,0 +1,95 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <RadiumNBR/Gui/CodeEditor/LineColumnPadding.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        Default constructor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+QLineColumnPadding::QLineColumnPadding() : m_Left( 16 ), m_Right( 16 ) {}
+
+///
+///  @fn        Default constructor
+///  @author    Nicolas Kogler
+///  @date      October 19th, 2016
+///
+QLineColumnPadding::QLineColumnPadding( const QSize& size ) :
+    m_Left( static_cast<quint32>( size.width() ) ),
+    m_Right( static_cast<quint32>( size.height() ) ) {}
+
+///
+///  @fn        Constructor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+QLineColumnPadding::QLineColumnPadding( quint32 left, quint32 right ) :
+    m_Left( left ), m_Right( right ) {}
+
+///
+///  @fn        Destructor
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+QLineColumnPadding::~QLineColumnPadding() {}
+
+///
+///  @fn        left
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+quint32 QLineColumnPadding::left() const {
+    return m_Left;
+}
+
+///
+///  @fn        right
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+quint32 QLineColumnPadding::right() const {
+    return m_Right;
+}
+
+///
+///  @fn        setLeft
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QLineColumnPadding::setLeft( quint32 left ) {
+    m_Left = left;
+}
+
+///
+///  @fn        setRight
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///
+void QLineColumnPadding::setRight( quint32 right ) {
+    m_Right = right;
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/LineColumnPadding.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/LineColumnPadding.hpp
new file mode 100644
index 0000000..b8fa0ba
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/LineColumnPadding.hpp
@@ -0,0 +1,80 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+#include <QtCore>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @file      QLineColumnPadding.hpp
+///  @author    Nicolas Kogler
+///  @date      October 5th, 2016
+///  @class     QLineColumnPadding
+///  @brief     Defines a padding in the right- and left direction.
+///
+class NodeBasedRenderer_LIBRARY_API QLineColumnPadding
+{
+  public:
+    ///
+    ///  @fn    Default constructor
+    ///  @brief Initializes a new instance of QLineColumnPadding.
+    ///
+    QLineColumnPadding();
+
+    ///
+    ///  @fn    Constructor
+    ///  @brief Constructs a padding out of a QSize.
+    ///  @param size Size representing left and right padding
+    ///
+    QLineColumnPadding( const QSize& size );
+
+    ///
+    ///  @fn    Constructor
+    ///  @brief Initializes a new instance of QLineColumnPadding.
+    ///  @param left Initial left padding
+    ///  @param right Initial right padding
+    ///
+    QLineColumnPadding( quint32 left, quint32 right );
+
+    ///
+    ///  @fn     Destructor
+    ///  @brief  Frees all resources allocated by QLineColumnPadding.
+    ///
+    ~QLineColumnPadding();
+
+    ///
+    ///  @fn      left : const
+    ///  @brief   Retrieves the padding in the left direction.
+    ///  @returns the left padding.
+    ///
+    quint32 left() const;
+
+    ///
+    ///  @fn      right : const
+    ///  @brief   Retrieves the padding in the right direction.
+    ///  @returns the right padding.
+    ///
+    quint32 right() const;
+
+    ///
+    ///  @fn    setLeft
+    ///  @brief Specifies the left padding
+    ///  @param left Left padding, in pixels
+    ///
+    void setLeft( quint32 left );
+
+    ///
+    ///  @fn    setRight
+    ///  @brief Specifies the right padding
+    ///  @param left Right padding, in pixels
+    ///
+    void setRight( quint32 right );
+
+  private:
+    //
+    // Private class members
+    //
+    quint32 m_Left;
+    quint32 m_Right;
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/SyntaxRule.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/SyntaxRule.cpp
new file mode 100644
index 0000000..617f31a
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/SyntaxRule.cpp
@@ -0,0 +1,358 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <QFont>
+#include <QtXml/QtXml>
+#include <RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp>
+#include <RadiumNBR/Gui/CodeEditor/XmlHelper.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        Default constructor
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+QSyntaxRule::QSyntaxRule() :
+    m_Regex( "" ),
+    m_BackColor( Qt::transparent ),
+    m_ForeColor( Qt::transparent ),
+    m_Id( "" ),
+    m_StartReg( "" ),
+    m_EndReg( "" ),
+    m_IsGlobal( true ),
+    m_UseFont( false ) {}
+
+///
+///  @fn        Copy constructor
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+QSyntaxRule::QSyntaxRule( const QSyntaxRule& rule ) :
+    m_Regex( rule.regex() ),
+    m_Font( rule.m_Font ),
+    m_BackColor( rule.backColor() ),
+    m_ForeColor( rule.foreColor() ),
+    m_Id( rule.id() ),
+    m_StartReg( rule.startRegex() ),
+    m_EndReg( rule.closeRegex() ),
+    m_IsGlobal( rule.isGlobal() ),
+    m_UseFont( rule.useFont() ) {}
+
+///
+///  @fn        Destructor
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+QSyntaxRule::~QSyntaxRule() {}
+
+///
+///  @fn        regex
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+const QString& QSyntaxRule::regex() const {
+    return m_Regex;
+}
+
+///
+///  @fn        font
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+const QFont& QSyntaxRule::font() const {
+    return m_Font;
+}
+
+///
+///  @fn        backColor
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+const QColor& QSyntaxRule::backColor() const {
+    return m_BackColor;
+}
+
+///
+///  @fn        backColor
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+const QColor& QSyntaxRule::foreColor() const {
+    return m_ForeColor;
+}
+
+///
+///  @fn        id
+///  @author    Nicolas Kogler
+///  @date      October 8th, 2016
+///
+const QString& QSyntaxRule::id() const {
+    return m_Id;
+}
+
+///
+///  @fn        startRegex
+///  @author    Nicolas Kogler
+///  @date      October 9th, 2016
+///
+const QString& QSyntaxRule::startRegex() const {
+    return m_StartReg;
+}
+
+///
+///  @fn        closeRegex
+///  @author    Nicolas Kogler
+///  @date      October 9th, 2016
+///
+const QString& QSyntaxRule::closeRegex() const {
+    return m_EndReg;
+}
+
+///
+///  @fn        isGlobal
+///  @author    Nicolas Kogler
+///  @date      October 9th, 2016
+///
+bool QSyntaxRule::isGlobal() const {
+    return m_IsGlobal;
+}
+
+///
+///  @fn        useFont
+///  @author    Nicolas Kogler
+///  @date      October 7th, 2016
+///
+bool QSyntaxRule::useFont() const {
+    return m_UseFont;
+}
+
+///
+///  @fn        setRegex
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+void QSyntaxRule::setRegex( const QString& regex ) {
+    m_Regex = regex;
+}
+
+///
+///  @fn        setKeywords
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+void QSyntaxRule::setKeywords( const QStringList& keywords, bool lineBegin ) {
+    m_Regex.clear();
+
+    // Appends a regex that requires the given keywords either to be at the
+    // start of the line or to be the first non-whitespace on the line.
+    if ( lineBegin ) { m_Regex.append( "(^|\\s.)(" ); }
+    else
+    { m_Regex.append( "\\b(" ); }
+
+    // Appends all the keywords as OR'ed expressions
+    foreach ( const QString& k, keywords )
+    { m_Regex.append( k + "|" ); }
+
+    // Adds the closing braces and a word boundary attribute
+    m_Regex.append( "(?!))\\b" );
+}
+
+///
+///  @fn        setFont
+///  @author    Nicolas Kogler
+///  @date      October 6th, 2016
+///
+void QSyntaxRule::setFont( const QFont& font ) {
+    m_Font    = font;
+    m_UseFont = true;
+}
+
+///
+///  @fn        setBackColor
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+void QSyntaxRule::setBackColor( const QColor& backColor ) {
+    m_BackColor = backColor;
+}
+
+///
+///  @fn        setForeColor
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///
+void QSyntaxRule::setForeColor( const QColor& foreColor ) {
+    m_ForeColor = foreColor;
+}
+
+///
+///  @fn        setId
+///  @author    Nicolas Kogler
+///  @date      October 8th, 2016
+///
+void QSyntaxRule::setId( const QString& id ) {
+    m_Id = id;
+}
+
+///
+///  @fn        setStartRegex
+///  @author    Nicolas Kogler
+///  @date      October 9th, 2016
+///
+void QSyntaxRule::setStartRegex( const QString& regex ) {
+    m_StartReg = regex;
+    m_Regex    = regex;
+}
+
+///
+///  @fn        setCloseRegex
+///  @author    Nicolas Kogler
+///  @date      October 9th, 2016
+///
+void QSyntaxRule::setCloseRegex( const QString& regex ) {
+    m_EndReg = regex;
+}
+
+///
+///  @fn        setGlobal
+///  @author    Nicolas Kogler
+///  @date      October 9th, 2016
+///
+void QSyntaxRule::setGlobal( bool global ) {
+    m_IsGlobal = global;
+}
+
+///
+///  @fn        loadFromFile
+///  @author    Nicolas Kogler
+///  @date      October 7th, 2016
+///
+QList<QSyntaxRule> QSyntaxRules::loadFromFile( const char* path, const QCodeEditorDesign& design ) {
+    QList<QSyntaxRule> rules;
+
+    // Attempts to open the XML file
+    QFile xmlFile( path );
+    if ( !xmlFile.open( QIODevice::ReadOnly ) )
+    {
+        qDebug( "Gui::QSyntaxRules: Cannot open XML file." );
+        return rules; // check against <retval>.isEmpty();
+    }
+
+    // Loads the file into a XML reader and tries
+    // to find the <rules> tag.
+    QXmlStreamReader xmlReader( &xmlFile );
+    if ( !xmlReader.readNextStartElement() || xmlReader.name() != "rules" )
+    {
+        qDebug( "Gui::QSyntaxRules: There is no <rules> tag." );
+        return rules;
+    }
+
+    // Iterates through every rule until reader finished
+    while ( !xmlReader.hasError() )
+    {
+        if ( !xmlReader.readNextStartElement() )
+        {
+            break; // no more elements
+        }
+        else if ( xmlReader.name() != "rule" )
+        {
+            break; // no more rule element
+        }
+        else if ( xmlReader.isComment() )
+        {
+            continue; // comments are ignored
+        }
+
+        QSyntaxRule rule;
+        QXmlStreamAttributes a = xmlReader.attributes();
+        if ( !a.isEmpty() )
+        {
+            auto first = a.at( 0 );
+            if ( first.name() == "id" ) { rule.setId( first.value().toString() ); }
+            else if ( first.name() == "global" )
+            { rule.setGlobal( ( first.value().toString() == "true" ) ? true : false ); }
+            if ( a.size() > 1 )
+            {
+                auto second = a.at( 1 );
+                if ( second.name() == "id" ) { rule.setId( second.value().toString() ); }
+                else if ( second.name() == "global" )
+                { rule.setGlobal( ( second.value().toString() == "true" ) ? true : false ); }
+            }
+        }
+
+        // Extracts the information out of the rule child
+        while ( !( xmlReader.isEndElement() && xmlReader.name() == "rule" ) )
+        {
+            if ( !xmlReader.readNextStartElement() ) break;
+            if ( xmlReader.isComment() ) break;
+
+            // Attempts to parse the rule
+            auto name = xmlReader.name().toString().toLower();
+            if ( name == "regex" ) { rule.setRegex( xmlReader.readElementText() ); }
+            else if ( name == "startregex" )
+            { rule.setStartRegex( xmlReader.readElementText() ); }
+            else if ( name == "closeregex" )
+            { rule.setCloseRegex( xmlReader.readElementText() ); }
+            else if ( name == "keywords" )
+            {
+
+                // Attempts to read the attribute
+                bool firstWord = false;
+                auto attr      = xmlReader.attributes();
+                if ( !attr.isEmpty() && attr.at( 0 ).name() == "start" )
+                {
+                    if ( attr.at( 0 ).value() == "true" ) { firstWord = true; }
+                }
+
+                rule.setKeywords( readKeywords( &xmlReader ), firstWord );
+            }
+            else if ( name == "backcolor" )
+            { rule.setBackColor( readColor( &xmlReader ) ); }
+            else if ( name == "forecolor" )
+            { rule.setForeColor( readColor( &xmlReader ) ); }
+            else if ( name == "font" )
+            { rule.setFont( readFont( &xmlReader, design.editorFont() ) ); }
+            else
+            {
+                QString s( "kgl::QSyntaxRule: Element '%0' is unknown." );
+                qDebug( s.arg( name ).toStdString().c_str() );
+            }
+        }
+
+        // Determines if the required element (regex||keywords) was found
+        if ( rule.regex().isEmpty() &&
+             ( rule.startRegex().isEmpty() && rule.closeRegex().isEmpty() ) )
+        {
+            qDebug( "kgl::QSyntaxRule: Required element 'regex' or 'keywords' not found." );
+            return rules;
+        }
+        else
+        { rules.push_back( rule ); }
+    }
+
+    xmlFile.close();
+    return rules;
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp
new file mode 100644
index 0000000..cc7f954
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/SyntaxRule.hpp
@@ -0,0 +1,218 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+#include <QColor>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorDesign.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @file      QSyntaxRule.hpp
+///  @author    Nicolas Kogler
+///  @date      October 4th, 2016
+///  @class     QSyntaxRule
+///  @brief     Specifies the appearance of keywords or regular expressions.
+///
+///  Under the hood, each regular expression is forwarded to a function
+///  that searches for matches between the rule and the code editor's text.
+///  If there are matches, they are coloured and transformed as specified.
+///  Keywords will be directly converted to a regular expression.
+///
+class NodeBasedRenderer_LIBRARY_API QSyntaxRule
+{
+  public:
+    ///
+    ///  @fn    Default constructor
+    ///  @brief Initializes a new instance of QSyntaxRule.
+    ///
+    QSyntaxRule();
+
+    ///
+    ///  @fn    Copy constructor
+    ///  @brief Copies one QSyntaxRule to another.
+    ///  @param rule Other rule
+    ///
+    QSyntaxRule( const QSyntaxRule& rule );
+
+    ///
+    ///  @fn     Destructor
+    ///  @brief  Frees all resources allocated by QSyntaxRule.
+    ///
+    ~QSyntaxRule();
+
+    ///
+    ///  @fn      regex : const
+    ///  @brief   Retrieves the underlying regular expression.
+    ///
+    ///  If keywords were specified instead of a regex,
+    ///  this will be returned: "(keyword1|keyword2|...)"
+    ///
+    ///  @returns a ref to the regex string being styled.
+    ///
+    const QString& regex() const;
+
+    ///
+    ///  @fn      font : const
+    ///  @brief   Retrieves the font of the matching text.
+    ///  @returns the font in which matches are rendered.
+    ///
+    const QFont& font() const;
+
+    ///
+    ///  @fn      backColor : const
+    ///  @brief   Retrieves the background color of the matching text.
+    ///  @returns the background color.
+    ///
+    const QColor& backColor() const;
+
+    ///
+    ///  @fn      foreColor : const
+    ///  @brief   Retrieves the foreground color of the matching text.
+    ///  @returns the foreground (text) color.
+    ///
+    const QColor& foreColor() const;
+
+    ///
+    ///  @fn      id : const
+    ///  @brief   Retrieves the unique id for this rule.
+    ///  @returns the rule string identifier.
+    ///
+    const QString& id() const;
+
+    ///
+    ///  @fn      startRegex : const
+    ///  @brief   Retrieves the starting regex for this multiline rule.
+    ///  @returns the staring regex.
+    ///
+    const QString& startRegex() const;
+
+    ///
+    ///  @fn      closeRegex : const
+    ///  @brief   Retrieves the closing regex for this multiline rule.
+    ///  @returns the staring regex.
+    ///
+    const QString& closeRegex() const;
+
+    ///
+    ///  @fn      isGlobal : const
+    ///  @brief   Determines whether the regex search should be global.
+    ///  @returns true to search globally.
+    ///
+    bool isGlobal() const;
+
+    ///
+    ///  @fn      useFont : const
+    ///  @brief   Determines whether a custom font is used.
+    ///  @returns true if a custom font is used.
+    ///
+    bool useFont() const;
+
+    ///
+    ///  @fn    setRegex
+    ///  @brief Specifies the regular expression for this rule.
+    ///  @param regex Escaped regex sequence
+    ///
+    void setRegex( const QString& regex );
+
+    ///
+    ///  @fn    setKeywords
+    ///  @brief Specifies the keywords.
+    ///
+    ///  The keywords will be automatically translated
+    ///  into a regular expression string. A usage example
+    ///  for 'lineBegin=true' could be preprocessor directives.
+    ///
+    ///  @param keywords List of keyword strings
+    ///  @param lineBegin Should keywords only be at the beginning (also with whitespace) of a line?
+    ///
+    void setKeywords( const QStringList& keywords, bool lineBegin = false );
+
+    ///
+    ///  @fn    setFont
+    ///  @brief Specifies the font in which matches are rendered.
+    ///
+    ///  This class will NOT take ownership of the font
+    ///  and will NOT delete it. Must be managed by the user.
+    ///  If the font is NULL, the matches will be rendered
+    ///  with the font of the parental QCodeEditor.
+    ///
+    ///  @param font Pointer to font instance
+    ///
+    void setFont( const QFont& font );
+
+    ///
+    ///  @fn    setBackColor
+    ///  @brief Specifies the background-color of the matches.
+    ///  @param backColor Reference to QColor instance
+    ///
+    void setBackColor( const QColor& backColor );
+
+    ///
+    ///  @fn    setForeColor
+    ///  @brief Specifies the foreground-color of the matches.
+    ///  @param foreColor Reference to QColor instance
+    ///
+    void setForeColor( const QColor& foreColor );
+
+    ///
+    ///  @fn    setId
+    ///  @brief Specifies the identifier for this rule.
+    ///  @param id String identifier for this rule
+    ///
+    void setId( const QString& id );
+
+    ///
+    ///  @fn    setStartRegex
+    ///  @brief Specifies the starting regular expression for this rule.
+    ///  @param regex Escaped regex sequence
+    ///
+    void setStartRegex( const QString& regex );
+
+    ///
+    ///  @fn    setCloseRegex
+    ///  @brief Specifies the closing regular expression for this rule.
+    ///  @param regex Escaped regex sequence
+    ///
+    void setCloseRegex( const QString& regex );
+
+    ///
+    ///  @fn    setGlobal
+    ///  @brief Specifies whether the regex search should be global.
+    ///  @param global True to perform a global regex search
+    ///
+    void setGlobal( bool global );
+
+  private:
+    //
+    // Private class members
+    //
+    QString m_Regex;    ///< Underlying regular expr
+    QFont m_Font;       ///< Font to render matches in
+    QColor m_BackColor; ///< Background color of the matches
+    QColor m_ForeColor; ///< Foreground color of the matches
+    QString m_Id;       ///< The rule name. NULL by default
+    QString m_StartReg; ///< Starting regex for multiline matches
+    QString m_EndReg;   ///< Closing regex for multiline matches
+    bool m_IsGlobal;    ///< Is regex search global?
+    bool m_UseFont;     ///< Use the font or not?
+};
+
+///
+///  @file      QSyntaxRule.hpp
+///  @author    Nicolas Kogler
+///  @date      October 7th, 2016
+///  @class     QSyntaxRules
+///  @brief     Wraps a static loader function.
+///
+class NodeBasedRenderer_LIBRARY_API QSyntaxRules
+{
+  public:
+    ///
+    ///  @fn    loadFromFile
+    ///  @brief Loads a list of rules from a XML file.
+    ///  @param path Absolute path or resource path
+    ///  @param design Current editor design (need the default font)
+    ///
+    static QList<QSyntaxRule> loadFromFile( const char* path, const QCodeEditorDesign& design );
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/XmlHelper.cpp b/src/libRender/RadiumNBR/Gui/CodeEditor/XmlHelper.cpp
new file mode 100644
index 0000000..7cacadb
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/XmlHelper.cpp
@@ -0,0 +1,252 @@
+//
+//  QCodeEditor - Widget to highlight and auto-complete code.
+//  Copyright (C) 2016 Nicolas Kogler (kogler.cml@hotmail.com)
+//
+//  This file is part of QCodeEditor.
+//
+//  QCodeEditor 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.
+//
+//  This program 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 Lesser General Public License
+//  along with QCodeEditor.  If not, see <http://www.gnu.org/licenses/>.
+//
+//
+
+//
+//  Included headers
+//
+#include <QColor>
+#include <QFont>
+#include <QSize>
+#include <RadiumNBR/Gui/CodeEditor/XmlHelper.hpp>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @fn        convertNumber
+///  @author    Nicolas Kogler
+///  @date      October 18th, 2016
+///
+inline bool convertNumber( const QString& str, int* out ) {
+    bool success;
+    *out = str.toInt( &success );
+    return success;
+}
+
+///
+///  @fn        readFloat
+///  @author    Nicolas Kogler
+///  @date      October 19th, 2016
+inline float readFloat( QXmlStreamReader* reader ) {
+    QString str = reader->readElementText();
+    bool success;
+
+    // Attempts to convert float
+    float result = str.toFloat( &success );
+    if ( !success ) { qDebug( "XmlHelper: Invalid float!" ); }
+
+    return result;
+}
+
+///
+///  @fn        readBool
+///  @author    Nicolas Kogler
+///  @date      October 7th, 2016
+///
+bool readBool( QXmlStreamReader* reader ) {
+    auto string = reader->readElementText();
+    if ( string.isEmpty() || string != "true" ) { return false; }
+    else
+    { return true; }
+}
+
+///
+///  @fn        readColor
+///  @author    Nicolas Kogler
+///  @date      October 7th, 2016
+///
+QColor readColor( QXmlStreamReader* reader ) {
+    auto string = reader->readElementText();
+    if ( string.isEmpty() ) { return QColor( Qt::transparent ); }
+
+    // Attempts to replace a hashtag with '0x'
+    if ( string.startsWith( '#' ) )
+    {
+        string.remove( 0, 1 );
+        string.insert( 0, "0x" );
+    }
+
+    // Tries to convert it to a number;
+    // if it failed, is a color name or rgba
+    bool success = false;
+    quint32 rgba = string.toUInt( &success, 16 );
+    if ( success == true )
+    {
+        if ( rgba <= 0xFFFFFF )
+        {
+            // make it format '0xFF<rgb>'
+            return QColor( ( 0xffu << 24 ) | rgba );
+        }
+        else
+        { return QColor( rgba ); }
+    }
+    else
+    {
+        if ( QColor::isValidColor( string ) ) { return QColor( string ); }
+        else
+        {
+            if ( string.startsWith( "rgba" ) )
+            {
+                string.remove( 0, 4 );
+                string.remove( QRegExp( "(\\(|\\))" ) );
+
+                QStringList s = string.split( ',', QString::SkipEmptyParts );
+                int r, g, b, a;
+                if ( convertNumber( s.at( 0 ), &r ) && convertNumber( s.at( 1 ), &g ) &&
+                     convertNumber( s.at( 2 ), &b ) && convertNumber( s.at( 3 ), &a ) )
+                { return QColor( r, g, b, a ); }
+                else
+                { return QColor( Qt::transparent ); }
+            }
+            else if ( string.startsWith( "rgb" ) )
+            {
+                string.remove( 0, 4 );
+                string.remove( QRegExp( "(\\(|\\))" ) );
+
+                QStringList s = string.split( ',', QString::SkipEmptyParts );
+                int r, g, b;
+                if ( convertNumber( s.at( 0 ), &r ) && convertNumber( s.at( 1 ), &g ) &&
+                     convertNumber( s.at( 2 ), &b ) )
+                { return QColor( r, g, b ); }
+                else
+                {
+                    QString e( "XML: Value of element '%0' is invalid. Value: '%1'." );
+                    qDebug( e.arg( reader->name().toString(), string ).toStdString().c_str() );
+                    return QColor( Qt::transparent );
+                }
+            }
+        }
+    }
+
+    return QColor( Qt::transparent );
+}
+
+///
+///  @fn        readKeywords
+///  @author    Nicolas Kogler
+///  @date      October 7th, 2016
+///
+QStringList readKeywords( QXmlStreamReader* reader ) {
+
+    // Simplified fits our needs: Removes trailing and leading space
+    // and converts multiple spaces to a single space. We have multiple
+    // spaces as: "\n     " -> results in "\n ".
+    QString string = reader->readElementText().simplified();
+
+    // Now we just have to remove all the newlines
+    string.remove( "\n" );
+
+    // A single whitespace is our separator for the keywords,
+    // thus split the string up accordingly.
+    return string.split( ' ' ); // safe to not include empty parts
+}
+
+///
+///  @fn        readMargin
+///  @author    Nicolas Kogler
+///  @date      October 18th, 2016
+///
+QMargins readMargin( QXmlStreamReader* reader ) {
+    QString str    = reader->readElementText().simplified();
+    QStringList li = str.split( ' ' );
+    if ( li.size() != 4 )
+    {
+        QString e( "XML: Value of element '%0' is invalid. Value: '%1'." );
+        qDebug( e.arg( reader->name().toString(), str ).toStdString().c_str() );
+        return QMargins();
+    }
+
+    int l, r, t, b;
+    if ( convertNumber( li.at( 0 ), &l ) && convertNumber( li.at( 1 ), &r ) &&
+         convertNumber( li.at( 2 ), &t ) && convertNumber( li.at( 3 ), &b ) )
+    { return QMargins( l, r, t, b ); }
+    else
+    {
+        QString e( "XML: Value of element '%0' is invalid. Value: '%1'." );
+        qDebug( e.arg( reader->name().toString(), str ).toStdString().c_str() );
+        return QMargins();
+    }
+}
+
+///
+///  @fn        readSize
+///  @author    Nicolas Kogler
+///  @date      October 19th, 2016
+///
+QSize readSize( QXmlStreamReader* reader ) {
+    QString str    = reader->readElementText().simplified();
+    QStringList li = str.split( ' ' );
+    if ( li.size() != 2 )
+    {
+        QString e( "XML: Value of element '%0' is invalid. Value: '%1'." );
+        qDebug( e.arg( reader->name().toString(), str ).toStdString().c_str() );
+        return QSize();
+    }
+
+    int w, h;
+    if ( convertNumber( li.at( 0 ), &w ) && convertNumber( li.at( 1 ), &h ) )
+    { return QSize( w, h ); }
+    else
+    {
+        QString e( "XML: Value of element '%0' is invalid. Value: '%1'." );
+        qDebug( e.arg( reader->name().toString(), str ).toStdString().c_str() );
+        return QSize();
+    }
+}
+
+///
+///  @fn        readFont
+///  @author    Nicolas Kogler
+///  @date      October 19th, 2016
+///
+QFont readFont( QXmlStreamReader* reader, const QFont& def ) {
+    QString parent = reader->name().toString();
+    if ( !reader->readNextStartElement() ) { return def; }
+
+    // Determines whether default font should be used
+    QFont usedFont;
+    if ( reader->name() == "family" )
+    {
+        usedFont.setFamily( reader->readElementText() );
+        usedFont.setStyleHint( QFont::TypeWriter );
+        reader->readNextStartElement();
+    }
+    else
+    { usedFont = def; }
+
+    // Reads the font properties
+    while ( !( reader->isEndElement() && reader->name() == parent ) )
+    {
+        auto prop = reader->name();
+        if ( prop == "strikethrough" ) { usedFont.setStrikeOut( readBool( reader ) ); }
+        else if ( prop == "underline" )
+        { usedFont.setUnderline( readBool( reader ) ); }
+        else if ( prop == "italic" )
+        { usedFont.setItalic( readBool( reader ) ); }
+        else if ( prop == "bold" )
+        { usedFont.setBold( readBool( reader ) ); }
+        else if ( prop == "pointsize" )
+        { usedFont.setPointSizeF( readFloat( reader ) ); }
+        reader->readNextStartElement();
+    }
+
+    return usedFont;
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/CodeEditor/XmlHelper.hpp b/src/libRender/RadiumNBR/Gui/CodeEditor/XmlHelper.hpp
new file mode 100644
index 0000000..c50dd04
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/CodeEditor/XmlHelper.hpp
@@ -0,0 +1,71 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+//
+//  Included headers
+//
+#include <QMargins>
+#include <QXmlStreamReader>
+
+namespace RadiumNBR::Gui {
+
+///
+///  @file      XmlHelper.hpp
+///  @author    Nicolas Kogler
+///  @date      October 18th, 2016
+///  @brief     Declares several functions for parsing XML elements.
+///
+
+///
+///  @fn      readBool
+///  @brief   Reads an XML element and converts it to a boolean.
+///  @param   reader Current XML reader
+///  @returns true if element is string "true", otherwise false.
+///
+extern bool readBool( QXmlStreamReader* reader );
+
+///
+///  @fn      readColor
+///  @brief   Reads an XML element and converts it to a color.
+///  @param   reader Current XML reader
+///  @returns the color representing the inline text.
+///
+/// Supported:
+/// Hexadecimal notation (e.g. '#abcdef')
+/// Color strings (e.g. 'red')
+/// RGBA notation (e.g. 'rgba(r, g, b, a)
+///
+extern QColor readColor( QXmlStreamReader* reader );
+
+///
+///  @fn      readKeywords
+///  @brief   Reads an XML element and converts it to a list of strings.
+///  @param   reader Current XML reader
+///  @returns all the words separated by whitespace
+///
+extern QStringList readKeywords( QXmlStreamReader* reader );
+
+///
+///  @fn      readMargin
+///  @brief   Reads a margin with 4 values.
+///  @param   reader Current XML reader
+///  @returns a QMargins structure.
+///
+extern QMargins readMargin( QXmlStreamReader* reader );
+
+///
+///  @fn      readSize
+///  @brief   Reads a size with 2 values.
+///  @param   reader Current XML reader
+///  @returns a QSize structure.
+extern QSize readSize( QXmlStreamReader* reader );
+
+///
+///  @fn      readFont
+///  @brief   Reads a font structure from the XML reader.
+///  @param   reader Current XML reader
+///  @param   def Default font, in case no family specified
+///  @returns a QFont structure.
+///
+extern QFont readFont( QXmlStreamReader* reader, const QFont& def );
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/GlslEditor.cpp b/src/libRender/RadiumNBR/Gui/GlslEditor.cpp
new file mode 100644
index 0000000..e98b6c6
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/GlslEditor.cpp
@@ -0,0 +1,68 @@
+#include <RadiumNBR/Gui/GlslEditor.hpp>
+
+namespace RadiumNBR::Gui {
+
+GlslEditor::GlslEditor( QWidget* parent ) : QCodeEditor( parent ) {
+
+    // Loads the highlighting rules from a resource file
+    QCodeEditorDesign design( ":/CodeEditor/EditorDefaultDesign.xml" );
+    QList<QSyntaxRule> rules =
+        QSyntaxRules::loadFromFile( ":/CodeEditor/HighlightRules_cpp.xml", design );
+
+    // Creates a new code editor, sets the rules and design, adds it to the form
+    setDesign( design );
+    setRules( rules );
+    setKeywords( {"printf", "scanf", "atoi", "mbtoa", "strlen", "memcpy", "memset"} );
+
+    // Connects the highlighter's onMatch signal to our printMatch slot
+    connect( highlighter(),
+             SIGNAL( onMatch( QSyntaxRule, QString, QTextBlock ) ),
+             this,
+             SLOT( addMacro( QSyntaxRule, QString, QTextBlock ) ) );
+    connect( highlighter(),
+             SIGNAL( onRemove( QCodeEditorBlockData* ) ),
+             this,
+             SLOT( removeMacro( QCodeEditorBlockData* ) ) );
+}
+
+GlslEditor::~GlslEditor() {}
+
+void GlslEditor::addMacro( const QSyntaxRule& rule, QString seq, QTextBlock block ) {
+    // Add the macro, if not already existing
+    if ( rule.id() == "macro" )
+    {
+        foreach ( const QTextBlock& b, m_RuleMap.keys() )
+        {
+            if ( b.userData() != NULL && block.userData() != NULL )
+            {
+                auto* d1 = static_cast<QCodeEditorBlockData*>( block.userData() );
+                auto* d2 = static_cast<QCodeEditorBlockData*>( b.userData() );
+                if ( d1->id == d2->id ) { return; }
+            }
+        }
+
+        QString def = seq.split( ' ' ).at( 0 );
+        m_RuleMap.insert( block, rule );
+        m_MacroMap.insert( block, def );
+        addKeyword( def );
+
+        // TODO: Add highlighting rule for the new macro
+    }
+}
+
+void GlslEditor::removeMacro( QCodeEditorBlockData* data ) {
+    foreach ( const QTextBlock& b, m_RuleMap.keys() )
+    {
+        if ( b.userData() )
+        {
+            auto* d = static_cast<QCodeEditorBlockData*>( b.userData() );
+            if ( d->id == data->id )
+            {
+                removeKeyword( m_MacroMap.value( b ) );
+                m_RuleMap.remove( b );
+                m_MacroMap.remove( b );
+            }
+        }
+    }
+}
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/GlslEditor.hpp b/src/libRender/RadiumNBR/Gui/GlslEditor.hpp
new file mode 100644
index 0000000..37584f2
--- /dev/null
+++ b/src/libRender/RadiumNBR/Gui/GlslEditor.hpp
@@ -0,0 +1,54 @@
+#pragma once
+#include <RadiumNBR/NodeBasedRendererMacro.hpp>
+
+#include <QMainWindow>
+#include <QMap>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditor.hpp>
+#include <RadiumNBR/Gui/CodeEditor/CodeEditorHighlighter.hpp>
+
+namespace RadiumNBR::Gui {
+
+/**
+ * Class that allow to edit glsl code.
+ * @todo fix the syntax highligt configuration (for now, it the one for C++)
+ * @todo add the Radium glsl interface in the keywords set for auto completion
+ * @todo (not really needed) : allow to configure the style ;)
+ */
+class NodeBasedRenderer_LIBRARY_API GlslEditor : public QCodeEditor
+{
+    Q_OBJECT
+  public:
+    ///
+    ///  @fn    Default constructor
+    ///  @brief Initializes a new instance of QCodeEditor_Example.
+    ///
+    GlslEditor( QWidget* parent = 0 );
+
+    ///
+    ///  @fn    Destructor
+    ///  @brief Frees resources used by QCodeEditor_Example.
+    ///
+    ~GlslEditor();
+
+  private slots:
+
+    ///
+    ///  @fn    addMacro
+    ///  @brief Adds the given macro.
+    ///
+    void addMacro( const QSyntaxRule& rule, QString seq, QTextBlock block );
+
+    ///
+    ///  @fn    removeMacro2
+    ///  @brief Removes a macro under certain conditions.
+    ///
+    void removeMacro( QCodeEditorBlockData* data );
+
+  private:
+    //
+    //  Class members
+    //
+    QMap<QTextBlock, QSyntaxRule> m_RuleMap;
+    QMap<QTextBlock, QString> m_MacroMap;
+};
+} // namespace RadiumNBR::Gui
diff --git a/src/libRender/RadiumNBR/Gui/RendererPanel.cpp b/src/libRender/RadiumNBR/Gui/RendererPanel.cpp
index 8cd9070..20eb93d 100644
--- a/src/libRender/RadiumNBR/Gui/RendererPanel.cpp
+++ b/src/libRender/RadiumNBR/Gui/RendererPanel.cpp
@@ -1,5 +1,7 @@
 #include <RadiumNBR/Gui/RendererPanel.hpp>
 
+#include <RadiumNBR/Gui/GlslEditor.hpp>
+
 #include <QLabel>
 #include <QVBoxLayout>
 
@@ -134,6 +136,21 @@ void RendererPanel::addFileInput( const std::string& name,
     m_currentLayout->addWidget( button );
 }
 
+void RendererPanel::addFileOuput( const std::string& name,
+                                  std::function<void( std::string )> callback,
+                                  const std::string& rootDirectory,
+                                  const std::string& filters ) {
+    auto button     = new QPushButton( name.c_str(), this );
+    auto fileDialog = [this, callback, rootDirectory, filters]() {
+        auto fltrs    = QString::fromStdString( filters );
+        auto filename = QFileDialog::getSaveFileName(
+            this, "Save file", QString::fromStdString( rootDirectory ), fltrs );
+        if ( !filename.isEmpty() ) { callback( filename.toStdString() ); }
+    };
+    connect( button, &QPushButton::clicked, fileDialog );
+    m_currentLayout->addWidget( button );
+}
+
 void RendererPanel::beginLayout( QBoxLayout::Direction dir ) {
     m_layouts.push( m_currentLayout );
     m_currentLayout = new QBoxLayout( dir );
@@ -167,29 +184,33 @@ void RendererPanel::addSeparator() {
 
 void RendererPanel::addCodeEditor( const std::string& name,
                                    std::function<void( std::string )> callback,
-                                   const std::string& initialText ) {
-// @todo : get a full featured code editor
-// cf https://www.codeproject.com/Articles/1139741/QCodeEditor-Widget-for-Qt
-// (code at https://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=1139741)
-    auto button     = new QPushButton( name.c_str(), this );
+                                   std::function<std::string()> initialText ) {
+    // @todo : get a full featured code editor
+    // cf https://www.codeproject.com/Articles/1139741/QCodeEditor-Widget-for-Qt
+    // (code at https://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=1139741)
+    auto button = new QPushButton( name.c_str(), this );
+
     QDialog* dialog = nullptr;
     auto editDialog = [this, callback, initialText, dialog]() mutable {
         if ( !dialog )
         {
             dialog = new QDialog( this );
 
-            auto buttonBox = new QDialogButtonBox(
-                QDialogButtonBox::Save | QDialogButtonBox::Cancel | QDialogButtonBox::Ok );
-            auto textEditor = new QPlainTextEdit();
-            textEditor->setPlainText( QString::fromStdString( initialText ) );
+            auto buttonBox =
+                new QDialogButtonBox( QDialogButtonBox::Save | QDialogButtonBox::Close );
+            auto textEditor = new GlslEditor( dialog );
+            textEditor->setPlainText( QString::fromStdString( initialText() ) );
 
             connect( buttonBox, &QDialogButtonBox::accepted, [callback, textEditor]() {
+                std::cout << "Accepted event received" << std::endl;
                 callback( textEditor->toPlainText().toStdString() );
             } );
 
-            connect( buttonBox, &QDialogButtonBox::rejected, [callback, textEditor, initialText]() {
-                textEditor->setPlainText( QString::fromStdString( initialText ) );
-            } );
+            connect(
+                buttonBox, &QDialogButtonBox::rejected, [callback, &dialog, initialText]() mutable {
+                    delete dialog;
+                    dialog = nullptr;
+                } );
 
             QVBoxLayout* mainLayout = new QVBoxLayout;
             mainLayout->addWidget( textEditor );
@@ -201,6 +222,17 @@ void RendererPanel::addCodeEditor( const std::string& name,
         dialog->activateWindow();
     };
     connect( button, &QPushButton::clicked, editDialog );
+
+    /*
+    GlslEditor *editor{nullptr};
+    auto launchEditor= [this, callback, initialText, editor]() mutable {
+        if ( !editor ){
+            editor = new GlslEditor();
+        }
+        editor->show();
+    };
+    connect( button, &QPushButton::clicked, launchEditor );
+     */
     m_currentLayout->addWidget( button );
 }
 
diff --git a/src/libRender/RadiumNBR/Gui/RendererPanel.hpp b/src/libRender/RadiumNBR/Gui/RendererPanel.hpp
index f5c465c..59962dc 100644
--- a/src/libRender/RadiumNBR/Gui/RendererPanel.hpp
+++ b/src/libRender/RadiumNBR/Gui/RendererPanel.hpp
@@ -124,6 +124,17 @@ class NodeBasedRenderer_LIBRARY_API RendererPanel : public QFrame
                        const std::string& rootDirectory,
                        const std::string& filters );
 
+    /** Add a save file dialog to the ui.
+     * Allow the user to select a file to load according to given filters
+     * @param name The name of the file property to expose
+     * @param callback The function to call when the state changed
+     * @param rootDirectory The initial directory of the file dialog
+     * @param filters The filters to apply to filenames
+     */
+    void addFileOuput( const std::string& name,
+                       std::function<void( std::string )> callback,
+                       const std::string& rootDirectory,
+                       const std::string& filters );
     /**
      *
      * @param name
@@ -132,7 +143,7 @@ class NodeBasedRenderer_LIBRARY_API RendererPanel : public QFrame
      */
     void addCodeEditor( const std::string& name,
                         std::function<void( std::string )> callback,
-                        const std::string& initialText );
+                        std::function<std::string()> initialText );
     /**@}*/
 
   private:
diff --git a/src/libRender/RadiumNBR/Gui/VisualizationGui.cpp b/src/libRender/RadiumNBR/Gui/VisualizationGui.cpp
index 47a694a..aa98c23 100644
--- a/src/libRender/RadiumNBR/Gui/VisualizationGui.cpp
+++ b/src/libRender/RadiumNBR/Gui/VisualizationGui.cpp
@@ -2,6 +2,8 @@
 #include <RadiumNBR/NodeBasedRenderer.hpp>
 #include <RadiumNBR/Renderer/Visualization.hpp>
 
+#include <fstream>
+
 namespace RadiumNBR {
 using namespace Gui;
 
@@ -48,22 +50,73 @@ buildControllerGui( NodeBasedRenderer* renderer, const std::function<void()>& ap
         false );
     controlPanel->endLayout( true );
 
+    controlPanel->beginLayout( QBoxLayout::LeftToRight );
+    controlPanel->beginLayout( QBoxLayout::TopToBottom );
+
     auto visualizationFunction = controller.getAttribToColorFunc();
+
+    auto getAttribCode = [&controller]() { return controller.getAttribToColorFunc().first; };
+    auto getColorCode  = [&controller]() { return controller.getAttribToColorFunc().second; };
+
     controlPanel->addCodeEditor(
-        "Attribute function",
+        "Edit attribute function",
         [&controller, visualizationFunction, appUpdateCallback]( const std::string& s ) {
             controller.setAttribToColorFunc( s, visualizationFunction.second );
             appUpdateCallback();
         },
-        visualizationFunction.first );
+        getAttribCode );
 
     controlPanel->addCodeEditor(
-        "Color function",
+        "Edit Color function",
         [&controller, visualizationFunction, appUpdateCallback]( const std::string& s ) {
             controller.setAttribToColorFunc( visualizationFunction.first, s );
             appUpdateCallback();
         },
-        visualizationFunction.second );
+        getColorCode );
+    controlPanel->endLayout( false );
+
+    controlPanel->beginLayout( QBoxLayout::TopToBottom );
+    auto loadAttribFuncClbk =
+        [&controller, visualizationFunction, appUpdateCallback]( const std::string& file ) {
+            if ( file.empty() ) { return; }
+            std::cout << "Loading attrib function from file " << file << std::endl;
+            std::ifstream inFile( file );
+            std::stringstream strStream;
+            strStream << inFile.rdbuf(); // read the file
+            controller.setAttribToColorFunc( strStream.str(), visualizationFunction.second );
+            appUpdateCallback();
+        };
+    auto loadColorFuncClbk =
+        [&controller, visualizationFunction, appUpdateCallback]( const std::string& file ) {
+            if ( file.empty() ) { return; }
+            std::cout << "Loading color function from file " << file << std::endl;
+            std::ifstream inFile( file );
+            std::stringstream strStream;
+            strStream << inFile.rdbuf(); // read the file
+            controller.setAttribToColorFunc( visualizationFunction.first, strStream.str() );
+            appUpdateCallback();
+        };
+    controlPanel->addFileInput(
+        "Load attribute func", loadAttribFuncClbk, "./", "Shaders (*.glsl)" );
+    controlPanel->addFileInput( "Load color func", loadColorFuncClbk, "./", "Shaders (*.glsl)" );
+    controlPanel->endLayout( false );
+
+    controlPanel->beginLayout( QBoxLayout::TopToBottom );
+    auto saveAttribFuncClbk = [visualizationFunction,
+                               appUpdateCallback]( const std::string& file ) {
+        std::ofstream outFile( file );
+        outFile << visualizationFunction.first;
+    };
+    auto saveColorFuncClbk = [visualizationFunction, appUpdateCallback]( const std::string& file ) {
+        std::ofstream outFile( file );
+        outFile << visualizationFunction.second;
+    };
+    controlPanel->addFileOuput(
+        "Save attribute func", saveAttribFuncClbk, "./", "Shaders (*.glsl)" );
+    controlPanel->addFileOuput( "Save color func", saveColorFuncClbk, "./", "Shaders (*.glsl)" );
+    controlPanel->endLayout( false );
+
+    controlPanel->endLayout( true );
 
     return controlPanel;
 }
-- 
GitLab