00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kateviewhelpers.h"
00022 #include "kateviewhelpers.moc"
00023
00024 #include "kateview.h"
00025 #include "kateviewinternal.h"
00026 #include "katedocument.h"
00027 #include "katecodefoldinghelpers.h"
00028 #include "katerenderer.h"
00029 #include "kateattribute.h"
00030 #include "kateconfig.h"
00031
00032 #include <kglobalsettings.h>
00033 #include <klocale.h>
00034
00035 #include <qpainter.h>
00036 #include <qpopupmenu.h>
00037 #include <qcursor.h>
00038 #include <qstyle.h>
00039 #include <qtimer.h>
00040
00041 #include <math.h>
00042
00043 #include "kateview.h"
00044 #include "katefactory.h"
00045
00046 #include "../interfaces/katecmd.h"
00047 #include "../interfaces/document.h"
00048
00049 #include <klocale.h>
00050
00051 #include <qtimer.h>
00052
00053 KateCmdLine::KateCmdLine (KateView *view)
00054 : KLineEdit (view)
00055 , m_view (view)
00056 , m_msgMode (false)
00057 {
00058 connect (this, SIGNAL(returnPressed(const QString &)),
00059 this, SLOT(slotReturnPressed(const QString &)));
00060
00061 completionObject()->insertItems (KateCmd::self()->cmds());
00062 }
00063
00064 KateCmdLine::~KateCmdLine ()
00065 {
00066 }
00067
00068 void KateCmdLine::slotReturnPressed ( const QString& cmd )
00069 {
00070 if (cmd.length () > 0)
00071 {
00072 Kate::Command *p = KateCmd::self()->queryCommand (cmd);
00073
00074 m_oldText = cmd;
00075 m_msgMode = true;
00076
00077 if (p)
00078 {
00079 QString msg;
00080
00081 if (p->exec (m_view, cmd, msg))
00082 {
00083 completionObject()->addItem (cmd);
00084 m_oldText = QString ();
00085
00086 if (msg.length() > 0)
00087 setText (i18n ("Success: ") + msg);
00088 else
00089 setText (i18n ("Success"));
00090 }
00091 else
00092 {
00093 if (msg.length() > 0)
00094 setText (i18n ("Error: ") + msg);
00095 else
00096 setText (i18n ("Command \"%1\" failed.").arg (cmd));
00097 }
00098 }
00099 else
00100 setText (i18n ("No such command: \"%1\"").arg (cmd));
00101 }
00102
00103 m_view->setFocus ();
00104 QTimer::singleShot( 4000, this, SLOT(hideMe()) );
00105 }
00106
00107 void KateCmdLine::hideMe ()
00108 {
00109 m_view->showCmdLine (false);
00110 }
00111
00112 void KateCmdLine::focusInEvent ( QFocusEvent *ev )
00113 {
00114 if (m_msgMode)
00115 {
00116 m_msgMode = false;
00117 setText (m_oldText);
00118 }
00119
00120 KLineEdit::focusInEvent (ev);
00121 }
00122
00123 void KateCmdLine::keyPressEvent( QKeyEvent *ev )
00124 {
00125 if (ev->key() == Key_Escape)
00126 {
00127 m_view->setFocus ();
00128 m_view->showCmdLine (false);
00129 }
00130
00131 return KLineEdit::keyPressEvent (ev);
00132 }
00133
00134 using namespace KTextEditor;
00135
00136 static const char* const plus_xpm[] = {
00137 "11 11 3 1",
00138 " c None",
00139 ". c #000000",
00140 "+ c #FFFFFF",
00141 "...........",
00142 ".+++++++++.",
00143 ".+++++++++.",
00144 ".++++.++++.",
00145 ".++++.++++.",
00146 ".++.....++.",
00147 ".++++.++++.",
00148 ".++++.++++.",
00149 ".+++++++++.",
00150 ".+++++++++.",
00151 "..........."};
00152
00153 static const char* const minus_xpm[] = {
00154 "11 11 3 1",
00155 " c None",
00156 ". c #000000",
00157 "+ c #FFFFFF",
00158 "...........",
00159 ".+++++++++.",
00160 ".+++++++++.",
00161 ".+++++++++.",
00162 ".+++++++++.",
00163 ".++.....++.",
00164 ".+++++++++.",
00165 ".+++++++++.",
00166 ".+++++++++.",
00167 ".+++++++++.",
00168 "..........."};
00169
00170
00171 static const char* const bookmark_xpm[]={
00172 "12 12 4 1",
00173 "b c #808080",
00174 "a c #000080",
00175 "# c #0000ff",
00176 ". c None",
00177 "........###.",
00178 ".......#...a",
00179 "......#.##.a",
00180 ".....#.#..aa",
00181 "....#.#...a.",
00182 "...#.#.a.a..",
00183 "..#.#.a.a...",
00184 ".#.#.a.a....",
00185 "#.#.a.a.....",
00186 "#.#a.a...bbb",
00187 "#...a..bbb..",
00188 ".aaa.bbb...."};
00189
00190 const int iconPaneWidth = 16;
00191 const int halfIPW = 8;
00192
00193 static QPixmap minus_px ((const char**)minus_xpm);
00194 static QPixmap plus_px ((const char**)plus_xpm);
00195
00196 KateIconBorder::KateIconBorder ( KateViewInternal* internalView, QWidget *parent )
00197 : QWidget(parent, "", Qt::WStaticContents | Qt::WRepaintNoErase | Qt::WResizeNoErase )
00198 , m_view( internalView->m_view )
00199 , m_doc( internalView->m_doc )
00200 , m_viewInternal( internalView )
00201 , m_iconBorderOn( false )
00202 , m_lineNumbersOn( false )
00203 , m_foldingMarkersOn( false )
00204 , m_dynWrapIndicatorsOn( false )
00205 , m_dynWrapIndicators( 0 )
00206 , m_cachedLNWidth( 0 )
00207 , m_maxCharWidth( 0 )
00208 {
00209 setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ) );
00210
00211 setBackgroundMode( NoBackground );
00212
00213 m_doc->setDescription( MarkInterface::markType01, i18n("Bookmark") );
00214 m_doc->setPixmap( MarkInterface::markType01, QPixmap((const char**)bookmark_xpm) );
00215
00216 updateFont();
00217 }
00218
00219 void KateIconBorder::setIconBorderOn( bool enable )
00220 {
00221 if( enable == m_iconBorderOn )
00222 return;
00223
00224 m_iconBorderOn = enable;
00225
00226 updateGeometry();
00227
00228 QTimer::singleShot( 0, this, SLOT(update()) );
00229 }
00230
00231 void KateIconBorder::setLineNumbersOn( bool enable )
00232 {
00233 if( enable == m_lineNumbersOn )
00234 return;
00235
00236 m_lineNumbersOn = enable;
00237 m_dynWrapIndicatorsOn = (m_dynWrapIndicators == 1) ? enable : m_dynWrapIndicators;
00238
00239 updateGeometry();
00240
00241 QTimer::singleShot( 0, this, SLOT(update()) );
00242 }
00243
00244 void KateIconBorder::setDynWrapIndicators( int state )
00245 {
00246 if (state == m_dynWrapIndicators )
00247 return;
00248
00249 m_dynWrapIndicators = state;
00250 m_dynWrapIndicatorsOn = (state == 1) ? m_lineNumbersOn : state;
00251
00252 updateGeometry ();
00253
00254 QTimer::singleShot( 0, this, SLOT(update()) );
00255 }
00256
00257 void KateIconBorder::setFoldingMarkersOn( bool enable )
00258 {
00259 if( enable == m_foldingMarkersOn )
00260 return;
00261
00262 m_foldingMarkersOn = enable;
00263
00264 updateGeometry();
00265
00266 QTimer::singleShot( 0, this, SLOT(update()) );
00267 }
00268
00269 QSize KateIconBorder::sizeHint() const
00270 {
00271 int w = 0;
00272
00273 if (m_iconBorderOn)
00274 w += iconPaneWidth + 1;
00275
00276 if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) {
00277 w += lineNumberWidth();
00278 }
00279
00280 if (m_foldingMarkersOn)
00281 w += iconPaneWidth;
00282
00283 w += 4;
00284
00285 return QSize( w, 0 );
00286 }
00287
00288
00289
00290 void KateIconBorder::updateFont()
00291 {
00292 const QFontMetrics *fm = m_view->renderer()->config()->fontMetrics();
00293 m_maxCharWidth = 0;
00294
00295
00296 for (int i = 48; i < 58; i++) {
00297 int charWidth = fm->width( QChar(i) );
00298 m_maxCharWidth = QMAX(m_maxCharWidth, charWidth);
00299 }
00300 }
00301
00302 int KateIconBorder::lineNumberWidth() const
00303 {
00304 int width = m_lineNumbersOn ? ((int)log10((double)(m_view->doc()->numLines())) + 1) * m_maxCharWidth + 4 : 0;
00305
00306 if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
00307 width = QMAX(style().scrollBarExtent().width() + 4, width);
00308
00309 if (m_cachedLNWidth != width || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor()) {
00310 int w = style().scrollBarExtent().width();
00311 int h = m_view->renderer()->config()->fontMetrics()->height();
00312
00313 QSize newSize(w, h);
00314 if ((m_arrow.size() != newSize || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor()) && !newSize.isEmpty()) {
00315 m_arrow.resize(newSize);
00316
00317 QPainter p(&m_arrow);
00318 p.fillRect( 0, 0, w, h, *m_view->renderer()->config()->iconBarColor() );
00319
00320 h = m_view->renderer()->config()->fontMetrics()->ascent();
00321
00322 p.setPen(m_view->renderer()->attribute(0)->textColor());
00323 p.drawLine(w/2, h/2, w/2, 0);
00324 #if 1
00325 p.lineTo(w/4, h/4);
00326 p.lineTo(0, 0);
00327 p.lineTo(0, h/2);
00328 p.lineTo(w/2, h-1);
00329 p.lineTo(w*3/4, h-1);
00330 p.lineTo(w-1, h*3/4);
00331 p.lineTo(w*3/4, h/2);
00332 p.lineTo(0, h/2);
00333 #else
00334 p.lineTo(w*3/4, h/4);
00335 p.lineTo(w-1,0);
00336 p.lineTo(w-1, h/2);
00337 p.lineTo(w/2, h-1);
00338 p.lineTo(w/4,h-1);
00339 p.lineTo(0, h*3/4);
00340 p.lineTo(w/4, h/2);
00341 p.lineTo(w-1, h/2);
00342 #endif
00343 }
00344 }
00345 }
00346
00347 return width;
00348 }
00349
00350 void KateIconBorder::paintEvent(QPaintEvent* e)
00351 {
00352 paintBorder(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
00353 }
00354
00355 void KateIconBorder::paintBorder (int , int y, int , int height)
00356 {
00357 uint h = m_view->renderer()->config()->fontStruct()->fontHeight;
00358 uint startz = (y / h);
00359 uint endz = startz + 1 + (height / h);
00360 uint lineRangesSize = m_viewInternal->lineRanges.size();
00361
00362
00363 int m_px = (h - 11) / 2;
00364 if (m_px < 0)
00365 m_px = 0;
00366
00367 int lnWidth( 0 );
00368 if ( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) )
00369 {
00370 lnWidth = lineNumberWidth();
00371 if ( lnWidth != m_cachedLNWidth || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor() )
00372 {
00373
00374
00375
00376
00377 m_cachedLNWidth = lnWidth;
00378 m_oldBackgroundColor = *m_view->renderer()->config()->iconBarColor();
00379 updateGeometry();
00380 update ();
00381 return;
00382 }
00383 }
00384
00385 int w( this->width() );
00386
00387 QPainter p ( this );
00388 p.setFont ( *m_view->renderer()->config()->font() );
00389 p.setPen ( m_view->renderer()->attribute(0)->textColor() );
00390
00391 KateLineInfo oldInfo;
00392 if (startz < lineRangesSize)
00393 {
00394 if ((m_viewInternal->lineRanges[startz].line-1) < 0)
00395 oldInfo.topLevel = true;
00396 else
00397 m_doc->lineInfo(&oldInfo,m_viewInternal->lineRanges[startz].line-1);
00398 }
00399
00400 for (uint z=startz; z <= endz; z++)
00401 {
00402 int y = h * z;
00403 int realLine = -1;
00404
00405 if (z < lineRangesSize)
00406 realLine = m_viewInternal->lineRanges[z].line;
00407
00408 int lnX ( 0 );
00409
00410 p.fillRect( 0, y, w-4, h, *m_view->renderer()->config()->iconBarColor() );
00411 p.fillRect( w-4, y, 4, h, *m_view->renderer()->config()->backgroundColor() );
00412
00413
00414 if( m_iconBorderOn )
00415 {
00416 p.drawLine(lnX+iconPaneWidth, y, lnX+iconPaneWidth, y+h);
00417
00418 if( (realLine > -1) && (m_viewInternal->lineRanges[z].startCol == 0) )
00419 {
00420 uint mrk ( m_doc->mark( realLine ) );
00421
00422 if ( mrk )
00423 {
00424 for( uint bit = 0; bit < 32; bit++ )
00425 {
00426 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
00427 if( mrk & markType )
00428 {
00429 QPixmap *px_mark (m_doc->markPixmap( markType ));
00430
00431 if (px_mark)
00432 {
00433
00434 int x_px = (iconPaneWidth - px_mark->width()) / 2;
00435 if (x_px < 0)
00436 x_px = 0;
00437
00438 int y_px = (h - px_mark->height()) / 2;
00439 if (y_px < 0)
00440 y_px = 0;
00441
00442 p.drawPixmap( lnX+x_px, y+y_px, *px_mark);
00443 }
00444 }
00445 }
00446 }
00447 }
00448
00449 lnX += iconPaneWidth + 1;
00450 }
00451
00452
00453 if( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) )
00454 {
00455 lnX +=2;
00456
00457 if (realLine > -1)
00458 if (m_viewInternal->lineRanges[z].startCol == 0) {
00459 if (m_lineNumbersOn)
00460 p.drawText( lnX + 1, y, lnWidth-4, h, Qt::AlignRight|Qt::AlignVCenter, QString("%1").arg( realLine + 1 ) );
00461 } else if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
00462 p.drawPixmap(lnX + lnWidth - m_arrow.width() - 4, y, m_arrow);
00463 }
00464
00465 lnX += lnWidth;
00466 }
00467
00468
00469 if( m_foldingMarkersOn )
00470 {
00471 if( realLine > -1 )
00472 {
00473 KateLineInfo info;
00474 m_doc->lineInfo(&info,realLine);
00475
00476 if (!info.topLevel)
00477 {
00478 if (info.startsVisibleBlock && (m_viewInternal->lineRanges[z].startCol == 0))
00479 {
00480 if (oldInfo.topLevel)
00481 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1);
00482 else
00483 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00484
00485 p.drawPixmap(lnX+3,y+m_px,minus_px);
00486 }
00487 else if (info.startsInVisibleBlock)
00488 {
00489 if (m_viewInternal->lineRanges[z].startCol == 0)
00490 {
00491 if (oldInfo.topLevel)
00492 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1);
00493 else
00494 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00495
00496 p.drawPixmap(lnX+3,y+m_px,plus_px);
00497 }
00498 else
00499 {
00500 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00501 }
00502
00503 if (!m_viewInternal->lineRanges[z].wrap)
00504 p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
00505 }
00506 else
00507 {
00508 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00509
00510 if (info.endsBlock && !m_viewInternal->lineRanges[z].wrap)
00511 p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
00512 }
00513 }
00514
00515 oldInfo = info;
00516 }
00517
00518 lnX += iconPaneWidth;
00519 }
00520 }
00521 }
00522
00523 KateIconBorder::BorderArea KateIconBorder::positionToArea( const QPoint& p ) const
00524 {
00525 int x = 0;
00526
00527 if( m_iconBorderOn ) {
00528 x += iconPaneWidth;
00529 if( p.x() <= x )
00530 return IconBorder;
00531 }
00532 if( m_lineNumbersOn || m_dynWrapIndicators ) {
00533 x += lineNumberWidth();
00534 if( p.x() <= x )
00535 return LineNumbers;
00536 }
00537 if( m_foldingMarkersOn ) {
00538 x += iconPaneWidth;
00539 if( p.x() <= x )
00540 return FoldingMarkers;
00541 }
00542 return None;
00543 }
00544
00545 void KateIconBorder::mousePressEvent( QMouseEvent* e )
00546 {
00547 m_lastClickedLine = m_viewInternal->yToLineRange(e->y()).line;
00548
00549 if ( positionToArea( e->pos() ) != IconBorder )
00550 {
00551 QMouseEvent forward( QEvent::MouseButtonPress,
00552 QPoint( 0, e->y() ), e->button(), e->state() );
00553 m_viewInternal->mousePressEvent( &forward );
00554 }
00555 e->accept();
00556 }
00557
00558 void KateIconBorder::mouseMoveEvent( QMouseEvent* e )
00559 {
00560 QMouseEvent forward( QEvent::MouseMove,
00561 QPoint( 0, e->y() ), e->button(), e->state() );
00562 m_viewInternal->mouseMoveEvent( &forward );
00563 }
00564
00565 void KateIconBorder::mouseReleaseEvent( QMouseEvent* e )
00566 {
00567 uint cursorOnLine = m_viewInternal->yToLineRange(e->y()).line;
00568
00569 if (cursorOnLine == m_lastClickedLine &&
00570 cursorOnLine <= m_doc->lastLine() )
00571 {
00572 BorderArea area = positionToArea( e->pos() );
00573 if( area == IconBorder) {
00574 if (e->button() == LeftButton) {
00575 if( m_doc->editableMarks() & KateViewConfig::global()->defaultMarkType() ) {
00576 if( m_doc->mark( cursorOnLine ) & KateViewConfig::global()->defaultMarkType() )
00577 m_doc->removeMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
00578 else
00579 m_doc->addMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
00580 } else {
00581 showMarkMenu( cursorOnLine, QCursor::pos() );
00582 }
00583 }
00584 else
00585 if (e->button() == RightButton) {
00586 showMarkMenu( cursorOnLine, QCursor::pos() );
00587 }
00588 }
00589
00590 if ( area == FoldingMarkers) {
00591 KateLineInfo info;
00592 m_doc->lineInfo(&info,cursorOnLine);
00593 if ((info.startsVisibleBlock) || (info.startsInVisibleBlock)) {
00594 emit toggleRegionVisibility(cursorOnLine);
00595 }
00596 }
00597 }
00598
00599 QMouseEvent forward( QEvent::MouseButtonRelease,
00600 QPoint( 0, e->y() ), e->button(), e->state() );
00601 m_viewInternal->mouseReleaseEvent( &forward );
00602 }
00603
00604 void KateIconBorder::mouseDoubleClickEvent( QMouseEvent* e )
00605 {
00606 QMouseEvent forward( QEvent::MouseButtonDblClick,
00607 QPoint( 0, e->y() ), e->button(), e->state() );
00608 m_viewInternal->mouseDoubleClickEvent( &forward );
00609 }
00610
00611 void KateIconBorder::showMarkMenu( uint line, const QPoint& pos )
00612 {
00613 QPopupMenu markMenu;
00614 QPopupMenu selectDefaultMark;
00615
00616 typedef QValueVector<int> MarkTypeVector;
00617 MarkTypeVector vec( 33 );
00618 int i=1;
00619
00620 for( uint bit = 0; bit < 32; bit++ ) {
00621 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
00622 if( !(m_doc->editableMarks() & markType) )
00623 continue;
00624
00625 if( !m_doc->markDescription( markType ).isEmpty() ) {
00626 markMenu.insertItem( m_doc->markDescription( markType ), i );
00627 selectDefaultMark.insertItem( m_doc->markDescription( markType ), i+100);
00628 } else {
00629 markMenu.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i );
00630 selectDefaultMark.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i+100);
00631 }
00632
00633 if( m_doc->mark( line ) & markType )
00634 markMenu.setItemChecked( i, true );
00635
00636 if( markType & KateViewConfig::global()->defaultMarkType() )
00637 selectDefaultMark.setItemChecked( i+100, true );
00638
00639 vec[i++] = markType;
00640 }
00641
00642 if( markMenu.count() == 0 )
00643 return;
00644
00645 if( markMenu.count() > 1 )
00646 markMenu.insertItem( i18n("Set Default Mark Type" ), &selectDefaultMark);
00647
00648 int result = markMenu.exec( pos );
00649 if( result <= 0 )
00650 return;
00651
00652 if ( result > 100)
00653 KateViewConfig::global()->setDefaultMarkType (vec[result-100]);
00654 else
00655 {
00656 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes) vec[result];
00657 if( m_doc->mark( line ) & markType ) {
00658 m_doc->removeMark( line, markType );
00659 } else {
00660 m_doc->addMark( line, markType );
00661 }
00662 }
00663 }
00664
00665