29 #include <QTextDocumentFragment> 30 #include <QTextCursor> 40 :
QTextEdit(parent), mMainWin(NULL), pHeightHintLines(-1)
45 mSyntaxHighlighter, SLOT(refreshAll()));
47 setContextMenuPolicy(Qt::DefaultContextMenu);
66 cur.
select(QTextCursor::Document);
74 QSize superSizeHint = QTextEdit::sizeHint();
75 if (pHeightHintLines >= 0) {
83 pHeightHintLines = lines;
104 static const struct {
const char * instext;
int charsback;
const char * iconsymb; } delimList[] = {
105 {
"\\frac{}{}", 3,
"\\frac{a}{b}" },
106 {
"\\sqrt{}", 1,
"\\sqrt{xyz}" },
107 {
"\\sqrt[]{}", 3,
"\\sqrt[n]{xyz}" },
108 {
"\\textrm{}", 1,
"\\textrm{A}" },
109 {
"\\textit{}", 1,
"\\textit{A}" },
110 {
"\\textsl{}", 1,
"\\textsl{A}" },
111 {
"\\textbf{}", 1,
"\\textbf{A}" },
112 {
"\\mathrm{}", 1,
"\\mathrm{A}" },
113 {
"\\mathit{}", 1,
"\\mathit{A}" },
119 for (k = 0; delimList[k].instext != NULL; ++k) {
121 a->setText(delimList[k].instext);
123 v[
"delim"] = QVariant::fromValue<QString>(
QLatin1String(delimList[k].instext));
124 v[
"charsBack"] = QVariant::fromValue<int>(delimList[k].charsback);
128 connect(a, SIGNAL(triggered()),
this, SLOT(slotInsertFromActionSender()));
132 delimaction->
setMenu(delimmenu);
137 if (actionList.
size()) {
139 for (k = 0; k < actionList.
size(); ++k) {
144 menu->
popup(mapToGlobal(pos));
152 if (mMainWin != NULL)
162 bool openerfound =
false;
164 if (mMainWin != NULL)
165 if (mMainWin->
openData(data, &openerfound))
172 klfDbg(
"mMainWin="<<mMainWin<<
" did not handle the paste, doing it ourselves.") ;
191 c1.
movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, charsBack);
199 void KLFLatexEdit::slotInsertFromActionSender()
202 if (obj == NULL || !obj->
inherits(
"QAction")) {
203 qWarning()<<
KLF_FUNC_NAME<<
": sender object is not a QAction: "<<obj;
207 QVariantMap vdata = v.
toMap();
208 insertDelimiter(vdata[
"delim"].toString(), vdata[
"charsBack"].toInt());
229 _caretpos = position;
237 void KLFLatexSyntaxHighlighter::parseEverything()
243 std::stack<ParenItem> parens;
247 _rulestoapply.
clear();
259 static QRegExp bsleft(
"^\\\\left(?!\\w)");
260 static QRegExp bsright(
"^\\\\right(?!\\w)");
263 while ( i < text.
length() ) {
264 if (text[i] ==
'%') {
266 while (i+k < text.
length() && text[i+k] !=
'\n')
268 _rulestoapply.
append(FormatRule(blockpos+i, k, FComment));
273 text[i] ==
'{' || text[i] ==
'(' || text[i] ==
'[') {
274 bool l = (text.
mid(i, 5) ==
"\\left");
279 if (text.
mid(i,2) ==
"\\{")
281 parens.push(ParenItem(blockpos+i, (_caretpos == blockpos+i), text[i].toAscii(), l));
282 if (i > 0 && text[i-1] ==
'\\') {
286 if (bsright.
indexIn(text.
mid(i)) != -1 || text[i] ==
'}' || text[i] ==
')' || text[i] ==
']') {
288 if (!parens.empty()) {
292 p = ParenItem(0,
false,
'!');
294 _rulestoapply.
append(FormatRule(blockpos+i, 1, FLonelyParen));
296 Format col = FParenMatch;
297 bool l = ( text.
mid(i, 6) ==
"\\right" );
302 if (text.
mid(i,2) ==
"\\}")
304 if ( (l && text[i] ==
'.' && p.
left) || (l && p.ch ==
'.' && p.left) ) {
307 }
else if ((text[i] ==
'}' && p.ch !=
'{') ||
308 (text[i] ==
')' && p.ch !=
'(') ||
309 (text[i] ==
']' && p.ch !=
'[') ||
311 col = FParenMismatch;
314 if (p.highlight || (_caretpos == blockpos+i+1)) {
316 _rulestoapply.
append(FormatRule(p.pos, blockpos+i+1-p.pos, col,
true));
319 _rulestoapply.
append(FormatRule(p.pos, 1, col));
320 _rulestoapply.
append(FormatRule(blockpos+i, 1, col,
true));
323 if (i > 0 && text[i-1] ==
'\\') {
328 if (text[i] ==
'\\') {
333 while (i+k < text.
length() && ( (text[i+k] >=
'a' && text[i+k] <=
'z') ||
334 (text[i+k] >=
'A' && text[i+k] <=
'Z') ))
336 if (k == 0 && i+1 < text.
length())
338 _rulestoapply.
append(FormatRule(blockpos+i-1, k+1, FKeyWord));
340 if (symbol.
size() > 1) {
341 klfDbg(
"symbol="<<symbol<<
" i="<<i<<
" k="<<k<<
" caretpos="<<_caretpos<<
" blockpos="<<blockpos);
342 if ( (_caretpos < blockpos+i ||_caretpos >= blockpos+i+k+1) &&
344 klfDbg(
"newSymbolTyped() about to be emitted for : "<<symbol);
346 pTypedSymbols.append(symbol);
356 block = block.
next();
361 while ( ! parens.empty() ) {
363 ParenItem p = parens.top();
365 if (_caretpos == p.pos) {
367 _rulestoapply.
append(FormatRule(p.pos, 1, FParenMismatch,
true));
370 FParenMismatch,
true));
373 _rulestoapply.
append(FormatRule(p.pos, 1, FLonelyParen));
429 blockfmtrules.
append(FormatRule(0, text.
length(), FNormal));
432 for (k = 0; k < _rulestoapply.
size(); ++k) {
433 int start = _rulestoapply[k].pos - block.
position();
434 int len = _rulestoapply[k].len;
440 if (start > text.
length())
442 if (len > text.
length() - start)
443 len = text.
length() - start;
445 blockfmtrules.
append(FormatRule(start, len, _rulestoapply[k].
format, _rulestoapply[k].onlyIfFocus));
448 bool hasfocus = _textedit->hasFocus();
449 for (k = 0; k < blockfmtrules.
size(); ++k) {
450 for (j = blockfmtrules[k].pos; j < blockfmtrules[k].
end(); ++j) {
451 if ( ! blockfmtrules[k].onlyIfFocus || hasfocus )
452 charformats[j].merge(charfmtForFormat(blockfmtrules[k].
format));
455 for (j = 0; j < charformats.
size(); ++j) {
void insertDelimiter(const QString &delim, int charsBack=1)
QTextCharFormat fmtComment
KLFLatexEdit(QWidget *mainwin)
virtual bool canInsertFromMimeData(const QMimeData *source) const
createStandardContextMenu()
cursorForPosition(const QPoint &pos)
static KLFLatexSymbolsCache * theCache()
bool openData(const QMimeData *mimeData, bool *openerFound=NULL)
canInsertFromMimeData(const QMimeData *source)
contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive)
#define klfDbg(streamableItems)
virtual ~KLFLatexSyntaxHighlighter()
movePosition(MoveOperation operation, MoveMode mode=MoveAnchor, int n=1)
select(SelectionType selection)
KLFLatexSyntaxHighlighter(QTextEdit *textedit, QObject *parent)
QTextCharFormat fmtKeyword
indexIn(const QString &str, int offset=0, CaretMode caretMode=CaretAtZero)
QTextCharFormat fmtParenMismatch
inherits(const char *className)
virtual QSize sizeHint() const
insertText(const QString &text)
QTextCharFormat fmtParenMatch
bool canOpenData(const QByteArray &data)
void insertContextMenuActions(const QPoint &pos, QList< QAction * > *actionList)
setTextCursor(const QTextCursor &cursor)
setData(const QVariant &userData)
insertFromMimeData(const QMimeData *source)
struct KLFConfig::@2 SyntaxHighlighter
virtual void insertFromMimeData(const QMimeData *source)
mid(int position, int n=-1)
void setLatex(const QString &latex)
void newSymbolTyped(const QString &symbolName)
setDocument(QTextDocument *doc)
void setCaretPos(int position)
virtual void contextMenuEvent(QContextMenuEvent *event)
insert(int position, const QString &str)
QTextCharFormat fmtLonelyParen
virtual void highlightBlock(const QString &text)
void setHeightHintLines(int lines)