24 #include <QtCore/QLocale>
25 #include <QTextDocument>
26 #include <QTextCursor>
27 #include <QGraphicsTextItem>
28 #include <kcolorscheme.h>
29 #include <kglobalsettings.h>
33 using namespace Cantor;
35 struct HighlightingRule
38 QTextCharFormat format;
41 bool operator==(
const HighlightingRule& rule1,
const HighlightingRule& rule2)
43 return rule1.regExp == rule2.regExp;
47 PairOpener() : position(-1), type(-1) { }
48 PairOpener(
int p,
int t) : position(p), type(t) { }
55 class Cantor::DefaultHighlighterPrivate
61 QTextCharFormat functionFormat;
62 QTextCharFormat variableFormat;
63 QTextCharFormat objectFormat;
64 QTextCharFormat keywordFormat;
65 QTextCharFormat numberFormat;
66 QTextCharFormat operatorFormat;
67 QTextCharFormat errorFormat;
68 QTextCharFormat commentFormat;
69 QTextCharFormat stringFormat;
70 QTextCharFormat matchingPairFormat;
71 QTextCharFormat mismatchingPairFormat;
78 QList<HighlightingRule> regExpRules;
79 QHash<QString, QTextCharFormat> wordRules;
84 d(new DefaultHighlighterPrivate)
86 d->cursor = QTextCursor();
87 d->lastBlockNumber=-1;
95 connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
this, SLOT(updateFormats()));
105 d->cursor = item->textCursor();
106 setDocument(item->document());
111 connect(item, SIGNAL(cursorPositionChanged(QTextCursor)),
114 d->lastBlockNumber = -1;
115 d->lastPosition = -1;
120 return text.isEmpty();
126 const QTextCursor& cursor = d->cursor;
127 d->lastBlockNumber = cursor.blockNumber();
139 Q_ASSERT(!d->pairs.contains(openSymbol));
140 Q_ASSERT(!d->pairs.contains(closeSymbol));
141 d->pairs << openSymbol << closeSymbol;
147 const QTextCursor& cursor = d->cursor;
149 if (cursor.blockNumber() == currentBlock().blockNumber() ) {
150 cursorPos = cursor.position() - currentBlock().position();
153 d->lastPosition = cursor.position();
156 QStack<PairOpener> opened;
158 for (
int i = 0; i < text.size(); ++i) {
159 int idx = d->pairs.indexOf(text[i]);
163 opened.push(PairOpener(i, idx));
164 }
else if (opened.isEmpty()) {
166 }
else if (opened.top().type == idx - 1) {
167 int openPos = opened.pop().position;
168 if (cursorPos != -1 &&
169 (openPos == cursorPos || openPos == cursorPos - 1 ||
170 i == cursorPos || i == cursorPos - 1)) {
175 int openPos = opened.pop().position;
182 while (!opened.isEmpty()) {
183 int position = opened.pop().position;
193 const QStringList& words = text.split(QRegExp(
"\\b"), QString::SkipEmptyParts);
197 const int n = words.size();
198 for (
int i = 0; i < n; ++i)
200 count = words[i].size();
201 QString word = words[i];
211 for(
int j = i - 1; j >= 0; j--)
214 const QString& w = words[j];
217 int idx = w.indexOf(QRegExp(exp));
218 const QString& s = w.mid(idx);
232 word = word.trimmed();
236 if (d->wordRules.contains(word))
238 setFormat(pos, count, d->wordRules[word]);
247 foreach (
const HighlightingRule& rule, d->regExpRules)
249 int index = rule.regExp.indexIn(text);
251 int length = rule.regExp.matchedLength();
252 setFormat(index, length, rule.format);
253 index = rule.regExp.indexIn(text, index + length);
260 return d->functionFormat;
265 return d->variableFormat;
270 return d->objectFormat;
275 return d->keywordFormat;
280 return d->numberFormat;
285 return d->operatorFormat;
290 return d->errorFormat;
295 return d->commentFormat;
300 return d->stringFormat;
305 return d->matchingPairFormat;
310 return d->mismatchingPairFormat;
313 void DefaultHighlighter::updateFormats()
316 KColorScheme scheme(QPalette::Active);
318 d->functionFormat.setForeground(scheme.foreground(KColorScheme::LinkText));
319 d->functionFormat.setFontWeight(QFont::DemiBold);
321 d->variableFormat.setForeground(scheme.foreground(KColorScheme::ActiveText));
323 d->objectFormat.setForeground(scheme.foreground(KColorScheme::NormalText));
324 d->objectFormat.setFontWeight(QFont::Bold);
326 d->keywordFormat.setForeground(scheme.foreground(KColorScheme::NeutralText));
327 d->keywordFormat.setFontWeight(QFont::Bold);
329 d->numberFormat.setForeground(scheme.foreground(KColorScheme::NeutralText));
331 d->operatorFormat.setForeground(scheme.foreground(KColorScheme::NormalText));
332 d->operatorFormat.setFontWeight(QFont::Bold);
334 d->errorFormat.setForeground(scheme.foreground(KColorScheme::NormalText));
335 d->errorFormat.setUnderlineColor(scheme.foreground(KColorScheme::NegativeText).color());
336 d->errorFormat.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
338 d->commentFormat.setForeground(scheme.foreground(KColorScheme::InactiveText));
340 d->stringFormat.setForeground(scheme.foreground(KColorScheme::PositiveText));
342 d->matchingPairFormat.setForeground(scheme.foreground(KColorScheme::NeutralText));
343 d->matchingPairFormat.setBackground(scheme.background(KColorScheme::NeutralBackground));
345 d->mismatchingPairFormat.setForeground(scheme.foreground(KColorScheme::NegativeText));
346 d->mismatchingPairFormat.setBackground(scheme.background(KColorScheme::NegativeBackground));
352 if (!cursor.isNull() && cursor.document() != document())
358 if ( (cursor.isNull() || cursor.blockNumber() != d->lastBlockNumber) &&
359 d->lastBlockNumber >= 0 ) {
361 rehighlightBlock(document()->findBlockByNumber(d->lastBlockNumber));
364 if (cursor.isNull()) {
365 d->lastBlockNumber = -1;
366 d->lastPosition = -1;
370 d->lastBlockNumber = cursor.blockNumber();
372 if ( d->lastPosition == cursor.position() ) {
376 rehighlightBlock(cursor.block());
377 d->lastPosition = cursor.position();
382 d->wordRules[word] = format;
388 HighlightingRule rule = { regexp, format };
389 d->regExpRules.removeAll(rule);
390 d->regExpRules.append(rule);
397 d->wordRules.remove(word);
404 HighlightingRule rule = { regexp, QTextCharFormat() };
405 d->regExpRules.removeAll(rule);
415 #include "defaulthighlighter.moc"
QTextCharFormat keywordFormat() const
void addPair(const QChar &openSymbol, const QChar &closeSymbol)
Call this to add a pair of symbols for highlighting.
QTextCharFormat stringFormat() const
QTextCharFormat mismatchingPairFormat() const
void highlightWords(const QString &text)
Highlights words added with addRule()
QTextCharFormat matchingPairFormat() const
QTextCharFormat variableFormat() const
QTextCharFormat numberFormat() const
QTextCharFormat operatorFormat() const
virtual QString nonSeparatingCharacters() const
Returns a string that contains a regular expression that matches for characters thar are allowed insi...
void setTextItem(QGraphicsTextItem *item)
Change the item beeing highlighted.
QTextCharFormat commentFormat() const
QTextCharFormat errorFormat() const
bool operator==(const Cantor::DefaultVariableModel::Variable &one, const Cantor::DefaultVariableModel::Variable &other)
virtual void highlightBlock(const QString &text)
This method is called by Cantor's KTextEdit and is where all the highlighting must take place...
QTextCharFormat functionFormat() const
void positionChanged(QTextCursor)
Called when the cursor moved.
void addRule(const QString &word, const QTextCharFormat &format)
Highlights all instances of the word in the text with the specified format.
bool skipHighlighting(const QString &text)
void highlightRegExps(const QString &text)
Highlights all matches from regular expressions added with addRule()
DefaultHighlighter(QObject *parent)
void highlightPairs(const QString &text)
Highlight pairs added with addPair()
QTextCharFormat objectFormat() const
void removeRule(const QString &word)
Removes any rules previously added for the word word.