codeeditor.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation ([email protected])
  6. **
  7. ** This file is part of the examples of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:BSD$
  10. ** You may use this file under the terms of the BSD license as follows:
  11. **
  12. ** "Redistribution and use in source and binary forms, with or without
  13. ** modification, are permitted provided that the following conditions are
  14. ** met:
  15. ** * Redistributions of source code must retain the above copyright
  16. ** notice, this list of conditions and the following disclaimer.
  17. ** * Redistributions in binary form must reproduce the above copyright
  18. ** notice, this list of conditions and the following disclaimer in
  19. ** the documentation and/or other materials provided with the
  20. ** distribution.
  21. ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
  22. ** the names of its contributors may be used to endorse or promote
  23. ** products derived from this software without specific prior written
  24. ** permission.
  25. **
  26. ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27. ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28. ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  29. ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  30. ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  31. ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  32. ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  33. ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  34. ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  35. ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  36. ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  37. ** $QT_END_LICENSE$
  38. **
  39. ****************************************************************************/
  40. #include <QtGui>
  41. #include "codeeditor.h"
  42. CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
  43. {
  44. lineNumberArea = new LineNumberArea(this);
  45. connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
  46. connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
  47. connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
  48. updateLineNumberAreaWidth(0);
  49. highlightCurrentLine();
  50. }
  51. int CodeEditor::lineNumberAreaWidth()
  52. {
  53. int digits = 1;
  54. int max = qMax(1, blockCount());
  55. while (max >= 10) {
  56. max /= 10;
  57. ++digits;
  58. }
  59. int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
  60. return space;
  61. }
  62. void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
  63. {
  64. setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
  65. }
  66. void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
  67. {
  68. if (dy)
  69. lineNumberArea->scroll(0, dy);
  70. else
  71. lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
  72. if (rect.contains(viewport()->rect()))
  73. updateLineNumberAreaWidth(0);
  74. }
  75. void CodeEditor::resizeEvent(QResizeEvent *e)
  76. {
  77. QPlainTextEdit::resizeEvent(e);
  78. QRect cr = contentsRect();
  79. lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
  80. }
  81. void CodeEditor::highlightCurrentLine()
  82. {
  83. QList<QTextEdit::ExtraSelection> extraSelections;
  84. if (!isReadOnly()) {
  85. QTextEdit::ExtraSelection selection;
  86. QColor lineColor = QColor(Qt::yellow).lighter(160);
  87. selection.format.setBackground(lineColor);
  88. selection.format.setProperty(QTextFormat::FullWidthSelection, true);
  89. selection.cursor = textCursor();
  90. selection.cursor.clearSelection();
  91. extraSelections.append(selection);
  92. }
  93. setExtraSelections(extraSelections);
  94. }
  95. void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
  96. {
  97. QPainter painter(lineNumberArea);
  98. painter.fillRect(event->rect(), Qt::lightGray);
  99. QTextBlock block = firstVisibleBlock();
  100. int blockNumber = block.blockNumber();
  101. int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
  102. int bottom = top + (int) blockBoundingRect(block).height();
  103. while (block.isValid() && top <= event->rect().bottom()) {
  104. if (block.isVisible() && bottom >= event->rect().top()) {
  105. QString number = QString::number(blockNumber + 1);
  106. painter.setPen(Qt::black);
  107. painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
  108. Qt::AlignRight, number);
  109. }
  110. block = block.next();
  111. top = bottom;
  112. bottom = top + (int) blockBoundingRect(block).height();
  113. ++blockNumber;
  114. }
  115. }
  116. #include "codeeditor.moc"