wgtcodeeditor.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "wgtcodeeditor.h"
  2. #include <QPainter>
  3. #include <QTextBlock>
  4. #include "wgtlinenumberarea.h"
  5. #include "syntaxhighlighter.h"
  6. WgtCodeEditor::WgtCodeEditor(QWidget *parent)
  7. : QPlainTextEdit(parent)
  8. {
  9. QFont font;
  10. font.setFamily("Courier");
  11. font.setStyleHint(QFont::Monospace);
  12. font.setFixedPitch(true);
  13. font.setPointSize(10);
  14. setFont(font);
  15. const int tabStop = 4; // 4 characters
  16. QFontMetrics metrics(font);
  17. setTabStopWidth(tabStop * metrics.width(' '));
  18. lineNumberArea = new WgtLineNumberArea(this);
  19. new SyntaxHighlighter(document());
  20. connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
  21. connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
  22. connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
  23. updateLineNumberAreaWidth(0);
  24. highlightCurrentLine();
  25. }
  26. int WgtCodeEditor::lineNumberAreaWidth()
  27. {
  28. int digits = 1;
  29. int max = qMax(1, blockCount());
  30. while (max >= 10) {
  31. max /= 10;
  32. ++digits;
  33. }
  34. int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
  35. return space;
  36. }
  37. void WgtCodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
  38. {
  39. setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
  40. }
  41. void WgtCodeEditor::updateLineNumberArea(const QRect &rect, int dy)
  42. {
  43. if (dy)
  44. lineNumberArea->scroll(0, dy);
  45. else
  46. lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
  47. if (rect.contains(viewport()->rect()))
  48. updateLineNumberAreaWidth(0);
  49. }
  50. void WgtCodeEditor::resizeEvent(QResizeEvent *e)
  51. {
  52. QPlainTextEdit::resizeEvent(e);
  53. QRect cr = contentsRect();
  54. lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
  55. }
  56. void WgtCodeEditor::highlightCurrentLine()
  57. {
  58. QList<QTextEdit::ExtraSelection> extraSelections;
  59. if (!isReadOnly()) {
  60. QTextEdit::ExtraSelection selection;
  61. selection.format.setBackground(palette().alternateBase());
  62. selection.format.setProperty(QTextFormat::FullWidthSelection, true);
  63. selection.cursor = textCursor();
  64. selection.cursor.clearSelection();
  65. extraSelections.append(selection);
  66. }
  67. setExtraSelections(extraSelections);
  68. }
  69. void WgtCodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
  70. {
  71. QPainter painter(lineNumberArea);
  72. painter.fillRect(event->rect(), palette().alternateBase());
  73. QTextBlock block = firstVisibleBlock();
  74. int blockNumber = block.blockNumber();
  75. int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
  76. int bottom = top + (int) blockBoundingRect(block).height();
  77. while (block.isValid() && top <= event->rect().bottom()) {
  78. if (block.isVisible() && bottom >= event->rect().top()) {
  79. QString number = QString::number(blockNumber + 1);
  80. painter.setPen(Qt::black);
  81. painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
  82. Qt::AlignRight, number);
  83. }
  84. block = block.next();
  85. top = bottom;
  86. bottom = top + (int) blockBoundingRect(block).height();
  87. ++blockNumber;
  88. }
  89. }