00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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;
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
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
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
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
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
00171 numbers = new NumberBar( this );
00172 numbers->setTextEdit( view );
00173
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
00279 }
00280
00281 return false;
00282 }
00283
00284 #include "numberedtextview.moc"