kjsembed
numberedtextview.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2005, 2006 Ian Reinhart Geiser <geiseri@kde.org> 00003 Copyright (C) 2005, 2006 Matt Broadstone <mbroadst@gmail.com> 00004 Copyright (C) 2005, 2006 Richard J. Moore <rich@kde.org> 00005 Copyright (C) 2005, 2006 Erik L. Bunce <kde@bunce.us> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include "numberedtextview.h" 00024 00025 #include <QtGui/QTextDocument> 00026 #include <QtGui/QTextBlock> 00027 #include <QtGui/QTextEdit> 00028 #include <QtGui/QBoxLayout> 00029 #include <QtGui/QScrollBar> 00030 #include <QtGui/QPainter> 00031 #include <QtGui/QTextObjectInterface> 00032 #include <QtGui/QToolTip> 00033 #include <QtCore/QDebug> 00034 00035 NumberBar::NumberBar( QWidget *parent ) 00036 : QWidget( parent ), edit(0), m_stopLine(-1), m_currentLine(-1), m_bugLine(-1) 00037 { 00038 setFixedWidth( fontMetrics().width( QString("0000") + 10 + 32 ) ); 00039 stopMarker = QPixmap( ":/images/no.png" ); 00040 currentMarker = QPixmap( ":/images/next.png" ); 00041 bugMarker = QPixmap( ":/images/bug.png" ); 00042 } 00043 00044 NumberBar::~NumberBar() 00045 { 00046 } 00047 00048 void NumberBar::setCurrentLine( int lineno ) 00049 { 00050 m_currentLine = lineno; 00051 } 00052 00053 void NumberBar::setStopLine( int lineno ) 00054 { 00055 m_stopLine = lineno; 00056 } 00057 00058 void NumberBar::setBugLine( int lineno ) 00059 { 00060 m_bugLine = lineno; 00061 } 00062 00063 int NumberBar::currentLine() const 00064 { 00065 return m_currentLine; 00066 } 00067 00068 int NumberBar::stopLine() const 00069 { 00070 return m_stopLine; 00071 } 00072 00073 int NumberBar::bugLine() const 00074 { 00075 return m_bugLine; 00076 } 00077 00078 void NumberBar::setTextEdit( QTextEdit *edit ) 00079 { 00080 this->edit = edit; 00081 connect( edit->document()->documentLayout(), SIGNAL( update(const QRectF &) ), 00082 this, SLOT( update() ) ); 00083 connect( edit->verticalScrollBar(), SIGNAL(valueChanged(int) ), 00084 this, SLOT( update() ) ); 00085 } 00086 00087 void NumberBar::paintEvent( QPaintEvent * ) 00088 { 00089 QAbstractTextDocumentLayout *layout = edit->document()->documentLayout(); 00090 int contentsY = edit->verticalScrollBar()->value(); 00091 qreal pageBottom = contentsY + edit->viewport()->height(); 00092 const QFontMetrics fm = fontMetrics(); 00093 const int ascent = fontMetrics().ascent() + 1; // height = ascent + descent + 1 00094 int lineCount = 1; 00095 00096 QPainter p(this); 00097 00098 bugRect = QRect(); 00099 stopRect = QRect(); 00100 currentRect = QRect(); 00101 00102 for ( QTextBlock block = edit->document()->begin(); 00103 block.isValid(); block = block.next(), ++lineCount ) { 00104 00105 const QRectF boundingRect = layout->blockBoundingRect( block ); 00106 00107 QPointF position = boundingRect.topLeft(); 00108 if ( position.y() + boundingRect.height() < contentsY ) 00109 continue; 00110 if ( position.y() > pageBottom ) 00111 break; 00112 00113 const QString txt = QString::number( lineCount ); 00114 p.drawText( width() - fm.width(txt), qRound( position.y() ) - contentsY + ascent, txt ); 00115 00116 // Bug marker 00117 if ( m_bugLine == lineCount ) { 00118 p.drawPixmap( 1, qRound( position.y() ) - contentsY, bugMarker ); 00119 bugRect = QRect( 1, qRound( position.y() ) - contentsY, bugMarker.width(), bugMarker.height() ); 00120 } 00121 00122 // Stop marker 00123 if ( m_stopLine == lineCount ) { 00124 p.drawPixmap( 1, qRound( position.y() ) - contentsY, stopMarker ); 00125 stopRect = QRect( 1, qRound( position.y() ) - contentsY, stopMarker.width(), stopMarker.height() ); 00126 } 00127 00128 // Current line marker 00129 if ( m_currentLine == lineCount ) { 00130 p.drawPixmap( 1, qRound( position.y() ) - contentsY, currentMarker ); 00131 currentRect = QRect( 1, qRound( position.y() ) - contentsY, currentMarker.width(), currentMarker.height() ); 00132 } 00133 } 00134 } 00135 00136 bool NumberBar::event( QEvent *event ) 00137 { 00138 if ( event->type() == QEvent::ToolTip ) { 00139 QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event); 00140 00141 if ( stopRect.contains( helpEvent->pos() ) ) { 00142 QToolTip::showText( helpEvent->globalPos(), "Stop Here" ); 00143 } 00144 else if ( currentRect.contains( helpEvent->pos() ) ) { 00145 QToolTip::showText( helpEvent->globalPos(), "Current Line" ); 00146 } 00147 else if ( bugRect.contains( helpEvent->pos() ) ) { 00148 QToolTip::showText( helpEvent->globalPos(), "Error Line" ); 00149 } 00150 } 00151 00152 return QWidget::event(event); 00153 } 00154 00155 NumberedTextView::NumberedTextView( QWidget *parent ) 00156 : QFrame( parent ) 00157 { 00158 setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); 00159 setLineWidth( 2 ); 00160 00161 // Setup the main view 00162 view = new QTextEdit( this ); 00163 view->setFontFamily( "Monospace" ); 00164 view->setLineWrapMode( QTextEdit::NoWrap ); 00165 view->setFrameStyle( QFrame::NoFrame ); 00166 view->installEventFilter( this ); 00167 00168 connect( view->document(), SIGNAL(contentsChange(int,int,int)), this, SLOT(textChanged(int,int,int)) ); 00169 00170 // Setup the line number pane 00171 numbers = new NumberBar( this ); 00172 numbers->setTextEdit( view ); 00173 // Testing... 00174 numbers->setStopLine( 3 ); 00175 numbers->setBugLine( 1 ); 00176 setCurrentLine( 5 ); 00177 00178 box = new QHBoxLayout( this ); 00179 box->setSpacing( 0 ); 00180 box->setMargin( 0 ); 00181 box->addWidget( numbers ); 00182 box->addWidget( view ); 00183 } 00184 00185 NumberedTextView::~NumberedTextView() 00186 { 00187 } 00188 00189 void NumberedTextView::setCurrentLine( int lineno ) 00190 { 00191 numbers->setCurrentLine( lineno ); 00192 textChanged( 0, 0, 1 ); 00193 } 00194 00195 void NumberedTextView::setStopLine( int lineno ) 00196 { 00197 numbers->setStopLine( lineno ); 00198 } 00199 00200 void NumberedTextView::setBugLine( int lineno ) 00201 { 00202 numbers->setBugLine( lineno ); 00203 } 00204 00205 int NumberedTextView::currentLine() const 00206 { 00207 return numbers->currentLine(); 00208 } 00209 00210 int NumberedTextView::stopLine() const 00211 { 00212 return numbers->stopLine(); 00213 } 00214 00215 int NumberedTextView::bugLine() const 00216 { 00217 return numbers->bugLine(); 00218 } 00219 00220 QString NumberedTextView::text() const 00221 { 00222 return view->toPlainText (); 00223 } 00224 00225 void NumberedTextView::setText( const QString &text ) 00226 { 00227 view->setPlainText(text); 00228 } 00229 00230 00231 void NumberedTextView::textChanged( int pos, int removed, int added ) 00232 { 00233 Q_UNUSED( pos ); 00234 00235 if ( removed == 0 && added == 0 ) 00236 return; 00237 00238 QTextBlock block = highlight.block(); 00239 QTextBlockFormat fmt = block.blockFormat(); 00240 QColor bg = view->palette().base().color(); 00241 fmt.setBackground( bg ); 00242 highlight.setBlockFormat( fmt ); 00243 00244 int lineCount = 1; 00245 for ( QTextBlock block = view->document()->begin(); 00246 block.isValid(); block = block.next(), ++lineCount ) { 00247 00248 if ( lineCount == numbers->currentLine() ) { 00249 fmt = block.blockFormat(); 00250 QColor bg = view->palette().color(QPalette::Highlight).light( 175 ); 00251 fmt.setBackground( bg ); 00252 00253 highlight = QTextCursor( block ); 00254 highlight.movePosition( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor ); 00255 highlight.setBlockFormat( fmt ); 00256 00257 break; 00258 } 00259 } 00260 } 00261 00262 bool NumberedTextView::eventFilter( QObject *obj, QEvent *event ) 00263 { 00264 if ( obj != view ) 00265 return QFrame::eventFilter(obj, event); 00266 00267 if ( event->type() == QEvent::ToolTip ) { 00268 QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event); 00269 00270 QTextCursor cursor = view->cursorForPosition( helpEvent->pos() ); 00271 cursor.movePosition( QTextCursor::StartOfWord, QTextCursor::MoveAnchor ); 00272 cursor.movePosition( QTextCursor::EndOfWord, QTextCursor::KeepAnchor ); 00273 00274 QString word = cursor.selectedText(); 00275 emit mouseHover( word ); 00276 emit mouseHover( helpEvent->pos(), word ); 00277 00278 // QToolTip::showText( helpEvent->globalPos(), word ); // For testing 00279 } 00280 00281 return false; 00282 } 00283 00284 #include "numberedtextview.moc"
KDE 4.6 API Reference