#ifndef CODEEDITOR_H
#define CODEEDITOR_H
#include<QPlainTextEdit>
#include<QObject>
#include<QTextBlockUserData>
#include<QtGui>
class Highlighter;
class LineNumberArea;
struct folder
{
};
//--------------------------------------
class CodeEditor : public QPlainTextEdit
{
Q_OBJECT
public:
int lineNumberAreaWidth();
QCompleter* completer
() const {return mCompleter;
} Highlighter* highlighter() const {return mHighligher;}
private:
void bracingEvent();
void homePressedEvent();
void tabPressedEvent(bool shiftPressed);
int findTwinBehind( folder req );
int findTwinAhead( folder req );
QString documentCommentClean
(int start,
int end
);
void popCompleter();
void informCompleter();
private slots:
void updateLineNumberAreaWidth(int newBlockCount);
void makeExtraSelections();
void updateLineNumberArea
(const QRect &,
int);
void insertCompletion(const QString& completion);
private:
Highlighter* mHighligher;
QList<folder> folders;
};
//--------------------------------------
#endif // CODEEDITOR_H
#ifndef CODEEDITOR_H
#define CODEEDITOR_H
#include<QPlainTextEdit>
#include<QObject>
#include<QTextBlockUserData>
#include<QtGui>
class Highlighter;
class LineNumberArea;
struct folder
{
QChar open;
QChar close;
};
//--------------------------------------
class CodeEditor : public QPlainTextEdit
{
Q_OBJECT
public:
CodeEditor(QWidget* parent = 0);
void lineNumberAreaPaintEvent(QPaintEvent* event);
int lineNumberAreaWidth();
QCompleter* completer() const {return mCompleter;}
Highlighter* highlighter() const {return mHighligher;}
private:
bool event(QEvent *e);
void resizeEvent(QResizeEvent *e);
void focusInEvent(QFocusEvent *e);
void focusOutEvent(QFocusEvent *e);
void keyPressEvent(QKeyEvent *e);
void bracingEvent();
void homePressedEvent();
void tabPressedEvent(bool shiftPressed);
int findTwinBehind( folder req );
int findTwinAhead( folder req );
QString documentCommentClean(int start, int end);
QString indent();
void popCompleter();
void informCompleter();
private slots:
void updateLineNumberAreaWidth(int newBlockCount);
void makeExtraSelections();
void updateLineNumberArea(const QRect &, int);
void insertCompletion(const QString& completion);
private:
QWidget* lineNumberArea;
Highlighter* mHighligher;
QCompleter* mCompleter;
QList<folder> folders;
};
//--------------------------------------
#endif // CODEEDITOR_H
To copy to clipboard, switch view to plain text mode
#include "codeEditor.h"
#include"highlighter.h"
CodeEditor
::CodeEditor(QWidget *parent
) : QPlainTextEdit
(parent
){
completionList << "for" << "while" << "do" << "if" << "else";
lineNumberArea = new LineNumberArea(this);
mHighligher = new Highlighter(this->document());
mCompleter->setWidget(this);
mCompleter
->setCompletionMode
(QCompleter::PopupCompletion);
connect(this, SIGNAL(blockCountChanged(int)),
this, SLOT(updateLineNumberAreaWidth(int)));
connect(this,
SIGNAL(updateRequest
(const QRect &,
int)),
this,
SLOT(updateLineNumberArea
(const QRect &,
int)));
connect(this, SIGNAL(cursorPositionChanged()),
this, SLOT(makeExtraSelections()));
connect(mCompleter,
SIGNAL(activated
(QString)),
this,
SLOT(insertCompletion
(QString)));
setStyleSheet("QPlainTextEdit { selection-background-color: darkgray }");
updateLineNumberAreaWidth(0);
folder fold;
fold.open = '{';
fold.close = '}';
folders.append(fold);
fold.open = '(';
fold.close = ')';
folders.append(fold);
fold.open = '[';
fold.close = ']';
folders.append(fold);
}
// ::::::: GENERAL METHODS :::::::
//---------------------------------------------------------------------------
void CodeEditor::makeExtraSelections()
{
QList<QTextEdit::ExtraSelection> extraSelections;
// make current line glow yellow ( not related to the syntax highlighter )
//-----------------------------------------------------------
selection
->format.
setBackground(QColor(Qt
::yellow).
lighter(160));
selection
->format.
setProperty(QTextFormat::FullWidthSelection,
true);
selection->cursor = textCursor();
selection->cursor.clearSelection();
extraSelections.append(*selection);
//-----------------------------------------------------------
// highlight parenthesis under cursor and its twin (behind or ahead)
//-----------------------------------------------------------
foreach( folder cur_fold, folders )
{
if( document()->characterAt(textCursor().position()-1) ==cur_fold.close)
{
selection
= new QTextEdit::ExtraSelection() ;
selection->cursor = textCursor();
selection
->format.
setForeground(QColor(Qt
::red));
extraSelections.append(*selection);
selection
= new QTextEdit::ExtraSelection() ;
selection->cursor = textCursor();
selection->cursor.setPosition(findTwinBehind(cur_fold)+1);
selection
->format.
setForeground(QColor(Qt
::red));
extraSelections.append(*selection);
}
if( document()->characterAt(textCursor().position()-1) ==cur_fold.open)
{
selection
= new QTextEdit::ExtraSelection() ;
selection->cursor = textCursor();
selection
->format.
setForeground(QColor(Qt
::red));
extraSelections.append(*selection);
selection
= new QTextEdit::ExtraSelection() ;
selection
->format.
setForeground(QColor(Qt
::red));
selection->cursor = textCursor();
selection->cursor.setPosition(findTwinAhead(cur_fold)-1);
extraSelections.append(*selection);
}
}
//-----------------------------------------------------------
setExtraSelections(extraSelections);
}
QString CodeEditor
::documentCommentClean(int start,
int end
) {
.........
//replace comment character with '@'
..........
}
// methods for finding matching pairs of expressions (parenthesis)
int CodeEditor::findTwinBehind( folder req )
{
QString cleaned
= documentCommentClean
(0, textCursor
().
position());
int i = cleaned.size()-2;
int braceBalance = -1;
while( i>0 && braceBalance<0 )
{
if(cleaned.at(i)==req.close) braceBalance-=1;
if(cleaned.at(i)==req.open) braceBalance+=1;
i--;
}
return i;
}
int CodeEditor::findTwinAhead( folder req )
{
QString cleaned
= documentCommentClean
(textCursor
().
position(), document
()->characterCount
());
int i = 0;
int braceBalance = 1;
while( i<cleaned.size() && braceBalance>0 )
{
if(cleaned.at(i)==req.close) braceBalance-=1;
if(cleaned.at(i)==req.open) braceBalance+=1;
i++;
}
return i+textCursor().position();
}
{
setReadOnly(false);
makeExtraSelections();
QPlainTextEdit::focusInEvent(e);
}
{
setReadOnly(true);
QList<QTextEdit::ExtraSelection> extraSelections;
setExtraSelections(extraSelections);
QPlainTextEdit::focusOutEvent(e);
}
#include "codeEditor.h"
#include"highlighter.h"
CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
{
QStringList completionList;
completionList << "for" << "while" << "do" << "if" << "else";
lineNumberArea = new LineNumberArea(this);
mHighligher = new Highlighter(this->document());
mCompleter = new QCompleter(this);
mCompleter->setWidget(this);
mCompleter->setCompletionMode(QCompleter::PopupCompletion);
mCompleter->setModel(new QStringListModel(completionList,mCompleter));
connect(this, SIGNAL(blockCountChanged(int)),
this, SLOT(updateLineNumberAreaWidth(int)));
connect(this, SIGNAL(updateRequest(const QRect &, int)),
this, SLOT(updateLineNumberArea(const QRect &, int)));
connect(this, SIGNAL(cursorPositionChanged()),
this, SLOT(makeExtraSelections()));
connect(mCompleter, SIGNAL(activated(QString)),
this, SLOT(insertCompletion(QString)));
setStyleSheet("QPlainTextEdit { selection-background-color: darkgray }");
updateLineNumberAreaWidth(0);
folder fold;
fold.open = '{';
fold.close = '}';
folders.append(fold);
fold.open = '(';
fold.close = ')';
folders.append(fold);
fold.open = '[';
fold.close = ']';
folders.append(fold);
}
// ::::::: GENERAL METHODS :::::::
//---------------------------------------------------------------------------
void CodeEditor::makeExtraSelections()
{
QList<QTextEdit::ExtraSelection> extraSelections;
QTextEdit::ExtraSelection* selection;
// make current line glow yellow ( not related to the syntax highlighter )
//-----------------------------------------------------------
selection = new QTextEdit::ExtraSelection;
selection->format.setBackground(QColor(Qt::yellow).lighter(160));
selection->format.setProperty(QTextFormat::FullWidthSelection, true);
selection->cursor = textCursor();
selection->cursor.clearSelection();
extraSelections.append(*selection);
//-----------------------------------------------------------
// highlight parenthesis under cursor and its twin (behind or ahead)
//-----------------------------------------------------------
foreach( folder cur_fold, folders )
{
if( document()->characterAt(textCursor().position()-1) ==cur_fold.close)
{
selection = new QTextEdit::ExtraSelection() ;
selection->cursor = textCursor();
selection->cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, 1);
selection->format.setForeground(QColor(Qt::red));
extraSelections.append(*selection);
selection = new QTextEdit::ExtraSelection() ;
selection->cursor = textCursor();
selection->cursor.setPosition(findTwinBehind(cur_fold)+1);
selection->cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 1);
selection->format.setForeground(QColor(Qt::red));
extraSelections.append(*selection);
}
if( document()->characterAt(textCursor().position()-1) ==cur_fold.open)
{
selection = new QTextEdit::ExtraSelection() ;
selection->cursor = textCursor();
selection->cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, 1);
selection->format.setForeground(QColor(Qt::red));
extraSelections.append(*selection);
selection = new QTextEdit::ExtraSelection() ;
selection->format.setForeground(QColor(Qt::red));
selection->cursor = textCursor();
selection->cursor.setPosition(findTwinAhead(cur_fold)-1);
selection->cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 1);
extraSelections.append(*selection);
}
}
//-----------------------------------------------------------
setExtraSelections(extraSelections);
}
QString CodeEditor::documentCommentClean(int start, int end)
{
.........
//replace comment character with '@'
..........
}
// methods for finding matching pairs of expressions (parenthesis)
int CodeEditor::findTwinBehind( folder req )
{
QString cleaned = documentCommentClean(0, textCursor().position());
int i = cleaned.size()-2;
int braceBalance = -1;
while( i>0 && braceBalance<0 )
{
if(cleaned.at(i)==req.close) braceBalance-=1;
if(cleaned.at(i)==req.open) braceBalance+=1;
i--;
}
return i;
}
int CodeEditor::findTwinAhead( folder req )
{
QString cleaned = documentCommentClean(textCursor().position(), document()->characterCount());
int i = 0;
int braceBalance = 1;
while( i<cleaned.size() && braceBalance>0 )
{
if(cleaned.at(i)==req.close) braceBalance-=1;
if(cleaned.at(i)==req.open) braceBalance+=1;
i++;
}
return i+textCursor().position();
}
void CodeEditor::focusInEvent(QFocusEvent *e)
{
setReadOnly(false);
makeExtraSelections();
QPlainTextEdit::focusInEvent(e);
}
void CodeEditor::focusOutEvent(QFocusEvent *e)
{
setReadOnly(true);
QList<QTextEdit::ExtraSelection> extraSelections;
setExtraSelections(extraSelections);
QPlainTextEdit::focusOutEvent(e);
}
To copy to clipboard, switch view to plain text mode
Bookmarks