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