codeeditor.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  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)
  43. : QPlainTextEdit(parent)
  44. {
  45. lineNumberArea = new LineNumberArea(this);
  46. connect(this, SIGNAL(blockCountChanged(int)), this,
  47. SLOT(updateLineNumberAreaWidth(int)));
  48. connect(this, SIGNAL(updateRequest(QRect, int)), this,
  49. SLOT(updateLineNumberArea(QRect, int)));
  50. connect(this, SIGNAL(cursorPositionChanged()), this,
  51. SLOT(highlightCurrentLine()));
  52. updateLineNumberAreaWidth(0);
  53. highlightCurrentLine();
  54. }
  55. int CodeEditor::lineNumberAreaWidth()
  56. {
  57. int digits = 1;
  58. int max = qMax(1, blockCount());
  59. while (max >= 10) {
  60. max /= 10;
  61. ++digits;
  62. }
  63. int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
  64. return space;
  65. }
  66. void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
  67. {
  68. setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
  69. }
  70. void CodeEditor::updateLineNumberArea(const QRect& rect, int dy)
  71. {
  72. if (dy)
  73. lineNumberArea->scroll(0, dy);
  74. else
  75. lineNumberArea->update(0, rect.y(), lineNumberArea->width(),
  76. rect.height());
  77. if (rect.contains(viewport()->rect()))
  78. updateLineNumberAreaWidth(0);
  79. }
  80. void CodeEditor::resizeEvent(QResizeEvent* e)
  81. {
  82. QPlainTextEdit::resizeEvent(e);
  83. QRect cr = contentsRect();
  84. lineNumberArea->setGeometry(
  85. QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
  86. }
  87. void CodeEditor::highlightCurrentLine()
  88. {
  89. QList<QTextEdit::ExtraSelection> extraSelections;
  90. if (!isReadOnly()) {
  91. QTextEdit::ExtraSelection selection;
  92. QColor lineColor = QColor(Qt::yellow).lighter(160);
  93. selection.format.setBackground(lineColor);
  94. selection.format.setProperty(QTextFormat::FullWidthSelection, true);
  95. selection.cursor = textCursor();
  96. selection.cursor.clearSelection();
  97. extraSelections.append(selection);
  98. }
  99. setExtraSelections(extraSelections);
  100. }
  101. void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent* event)
  102. {
  103. QPainter painter(lineNumberArea);
  104. painter.fillRect(event->rect(), Qt::lightGray);
  105. QTextBlock block = firstVisibleBlock();
  106. int blockNumber = block.blockNumber();
  107. int top =
  108. (int)blockBoundingGeometry(block).translated(contentOffset()).top();
  109. int bottom = top + (int)blockBoundingRect(block).height();
  110. while (block.isValid() && top <= event->rect().bottom()) {
  111. if (block.isVisible() && bottom >= event->rect().top()) {
  112. QString number = QString::number(blockNumber + 1);
  113. painter.setPen(Qt::black);
  114. painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
  115. Qt::AlignRight, number);
  116. }
  117. block = block.next();
  118. top = bottom;
  119. bottom = top + (int)blockBoundingRect(block).height();
  120. ++blockNumber;
  121. }
  122. }
  123. #include "codeeditor.moc"