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 "../interfaces/document.h"
00025 #include "../interfaces/katecmd.h"
00026 #include "kateattribute.h"
00027 #include "katecodefoldinghelpers.h"
00028 #include "kateconfig.h"
00029 #include "katedocument.h"
00030 #include "katefactory.h"
00031 #include "katerenderer.h"
00032 #include "kateview.h"
00033 #include "kateviewinternal.h"
00034
00035 #include <kapplication.h>
00036 #include <kglobalsettings.h>
00037 #include <klocale.h>
00038 #include <knotifyclient.h>
00039 #include <kglobal.h>
00040 #include <kcharsets.h>
00041 #include <kpopupmenu.h>
00042
00043 #include <qcursor.h>
00044 #include <qpainter.h>
00045 #include <qpopupmenu.h>
00046 #include <qstyle.h>
00047 #include <qtimer.h>
00048 #include <qwhatsthis.h>
00049 #include <qregexp.h>
00050 #include <qtextcodec.h>
00051
00052 #include <math.h>
00053
00054 #include <kdebug.h>
00055
00056
00057 KateScrollBar::KateScrollBar (Orientation orientation, KateViewInternal* parent, const char* name)
00058 : QScrollBar (orientation, parent->m_view, name)
00059 , m_middleMouseDown (false)
00060 , m_view(parent->m_view)
00061 , m_doc(parent->m_doc)
00062 , m_viewInternal(parent)
00063 , m_topMargin(-1)
00064 , m_bottomMargin(-1)
00065 , m_savVisibleLines(0)
00066 , m_showMarks(false)
00067 {
00068 connect(this, SIGNAL(valueChanged(int)), SLOT(sliderMaybeMoved(int)));
00069 connect(m_doc, SIGNAL(marksChanged()), this, SLOT(marksChanged()));
00070
00071 m_lines.setAutoDelete(true);
00072 }
00073
00074 void KateScrollBar::mousePressEvent(QMouseEvent* e)
00075 {
00076 if (e->button() == MidButton)
00077 m_middleMouseDown = true;
00078
00079 QScrollBar::mousePressEvent(e);
00080
00081 redrawMarks();
00082 }
00083
00084 void KateScrollBar::mouseReleaseEvent(QMouseEvent* e)
00085 {
00086 QScrollBar::mouseReleaseEvent(e);
00087
00088 m_middleMouseDown = false;
00089
00090 redrawMarks();
00091 }
00092
00093 void KateScrollBar::mouseMoveEvent(QMouseEvent* e)
00094 {
00095 QScrollBar::mouseMoveEvent(e);
00096
00097 if (e->state() | LeftButton)
00098 redrawMarks();
00099 }
00100
00101 void KateScrollBar::paintEvent(QPaintEvent *e)
00102 {
00103 QScrollBar::paintEvent(e);
00104 redrawMarks();
00105 }
00106
00107 void KateScrollBar::resizeEvent(QResizeEvent *e)
00108 {
00109 QScrollBar::resizeEvent(e);
00110 recomputeMarksPositions();
00111 }
00112
00113 void KateScrollBar::styleChange(QStyle &s)
00114 {
00115 QScrollBar::styleChange(s);
00116 m_topMargin = -1;
00117 recomputeMarksPositions();
00118 }
00119
00120 void KateScrollBar::valueChange()
00121 {
00122 QScrollBar::valueChange();
00123 redrawMarks();
00124 }
00125
00126 void KateScrollBar::rangeChange()
00127 {
00128 QScrollBar::rangeChange();
00129 recomputeMarksPositions();
00130 }
00131
00132 void KateScrollBar::marksChanged()
00133 {
00134 recomputeMarksPositions(true);
00135 }
00136
00137 void KateScrollBar::redrawMarks()
00138 {
00139 if (!m_showMarks)
00140 return;
00141
00142 QPainter painter(this);
00143 QRect rect = sliderRect();
00144 for (QIntDictIterator<QColor> it(m_lines); it.current(); ++it)
00145 {
00146 if (it.currentKey() < rect.top() || it.currentKey() > rect.bottom())
00147 {
00148 painter.setPen(*it.current());
00149 painter.drawLine(0, it.currentKey(), width(), it.currentKey());
00150 }
00151 }
00152 }
00153
00154 void KateScrollBar::recomputeMarksPositions(bool forceFullUpdate)
00155 {
00156 if (m_topMargin == -1)
00157 watchScrollBarSize();
00158
00159 m_lines.clear();
00160 m_savVisibleLines = m_doc->visibleLines();
00161
00162 int realHeight = frameGeometry().height() - m_topMargin - m_bottomMargin;
00163
00164 QPtrList<KTextEditor::Mark> marks = m_doc->marks();
00165 KateCodeFoldingTree *tree = m_doc->foldingTree();
00166
00167 for (KTextEditor::Mark *mark = marks.first(); mark; mark = marks.next())
00168 {
00169 uint line = mark->line;
00170
00171 if (tree)
00172 {
00173 KateCodeFoldingNode *node = tree->findNodeForLine(line);
00174
00175 while (node)
00176 {
00177 if (!node->isVisible())
00178 line = tree->getStartLine(node);
00179 node = node->getParentNode();
00180 }
00181 }
00182
00183 line = m_doc->getVirtualLine(line);
00184
00185 double d = (double)line / (m_savVisibleLines - 1);
00186 m_lines.insert(m_topMargin + (int)(d * realHeight),
00187 new QColor(KateRendererConfig::global()->lineMarkerColor((KTextEditor::MarkInterface::MarkTypes)mark->type)));
00188 }
00189
00190 if (forceFullUpdate)
00191 update();
00192 else
00193 redrawMarks();
00194 }
00195
00196 void KateScrollBar::watchScrollBarSize()
00197 {
00198 int savMax = maxValue();
00199 setMaxValue(0);
00200 QRect rect = sliderRect();
00201 setMaxValue(savMax);
00202
00203 m_topMargin = rect.top();
00204 m_bottomMargin = frameGeometry().height() - rect.bottom();
00205 }
00206
00207 void KateScrollBar::sliderMaybeMoved(int value)
00208 {
00209 if (m_middleMouseDown)
00210 emit sliderMMBMoved(value);
00211 }
00212
00213
00214
00215 class KateCmdLnWhatsThis : public QWhatsThis
00216 {
00217 public:
00218 KateCmdLnWhatsThis( KateCmdLine *parent )
00219 : QWhatsThis( parent )
00220 , m_parent( parent ) {;}
00221
00222 QString text( const QPoint & )
00223 {
00224 QString beg = "<qt background=\"white\"><div><table width=\"100%\"><tr><td bgcolor=\"brown\"><font color=\"white\"><b>Help: <big>";
00225 QString mid = "</big></b></font></td></tr><tr><td>";
00226 QString end = "</td></tr></table></div><qt>";
00227
00228 QString t = m_parent->text();
00229 QRegExp re( "\\s*help\\s+(.*)" );
00230 if ( re.search( t ) > -1 )
00231 {
00232 QString s;
00233
00234 QString name = re.cap( 1 );
00235 if ( name == "list" )
00236 {
00237 return beg + i18n("Available Commands") + mid
00238 + KateCmd::self()->cmds().join(" ")
00239 + i18n("<p>For help on individual commands, do <code>'help <command>'</code></p>")
00240 + end;
00241 }
00242 else if ( ! name.isEmpty() )
00243 {
00244 Kate::Command *cmd = KateCmd::self()->queryCommand( name );
00245 if ( cmd )
00246 {
00247 if ( cmd->help( (Kate::View*)m_parent->parentWidget(), name, s ) )
00248 return beg + name + mid + s + end;
00249 else
00250 return beg + name + mid + i18n("No help for '%1'").arg( name ) + end;
00251 }
00252 else
00253 return beg + mid + i18n("No such command <b>%1</b>").arg(name) + end;
00254 }
00255 }
00256
00257 return beg + mid + i18n(
00258 "<p>This is the Katepart <b>command line</b>.<br>"
00259 "Syntax: <code><b>command [ arguments ]</b></code><br>"
00260 "For a list of available commands, enter <code><b>help list</b></code><br>"
00261 "For help for individual commands, enter <code><b>help <command></b></code></p>")
00262 + end;
00263 }
00264
00265 private:
00266 KateCmdLine *m_parent;
00267 };
00268
00269
00270
00275 class KateCmdLineFlagCompletion : public KCompletion
00276 {
00277 public:
00278 KateCmdLineFlagCompletion() {;}
00279
00280 QString makeCompletion( const QString & string )
00281 {
00282 return QString::null;
00283 }
00284
00285 };
00286
00287
00288
00289 KateCmdLine::KateCmdLine (KateView *view)
00290 : KLineEdit (view)
00291 , m_view (view)
00292 , m_msgMode (false)
00293 , m_histpos( 0 )
00294 , m_cmdend( 0 )
00295 , m_command( 0L )
00296 , m_oldCompletionObject( 0L )
00297 {
00298 connect (this, SIGNAL(returnPressed(const QString &)),
00299 this, SLOT(slotReturnPressed(const QString &)));
00300
00301 completionObject()->insertItems (KateCmd::self()->cmds());
00302 setAutoDeleteCompletionObject( false );
00303 m_help = new KateCmdLnWhatsThis( this );
00304 }
00305
00306 void KateCmdLine::slotReturnPressed ( const QString& text )
00307 {
00308
00309
00310 uint n = 0;
00311 while( text[n].isSpace() )
00312 n++;
00313
00314 QString cmd = text.mid( n );
00315
00316
00317 if ( cmd.startsWith( "help" ) )
00318 {
00319 m_help->display( m_help->text( QPoint() ), mapToGlobal(QPoint(0,0)) );
00320 clear();
00321 KateCmd::self()->appendHistory( cmd );
00322 m_histpos = KateCmd::self()->historyLength();
00323 m_oldText = QString ();
00324 return;
00325 }
00326
00327 if (cmd.length () > 0)
00328 {
00329 Kate::Command *p = KateCmd::self()->queryCommand (cmd);
00330
00331 m_oldText = cmd;
00332 m_msgMode = true;
00333
00334 if (p)
00335 {
00336 QString msg;
00337
00338 if (p->exec (m_view, cmd, msg))
00339 {
00340 KateCmd::self()->appendHistory( cmd );
00341 m_histpos = KateCmd::self()->historyLength();
00342 m_oldText = QString ();
00343
00344 if (msg.length() > 0)
00345 setText (i18n ("Success: ") + msg);
00346 else
00347 setText (i18n ("Success"));
00348 }
00349 else
00350 {
00351 if (msg.length() > 0)
00352 setText (i18n ("Error: ") + msg);
00353 else
00354 setText (i18n ("Command \"%1\" failed.").arg (cmd));
00355 KNotifyClient::beep();
00356 }
00357 }
00358 else
00359 {
00360 setText (i18n ("No such command: \"%1\"").arg (cmd));
00361 KNotifyClient::beep();
00362 }
00363 }
00364
00365
00366 if ( m_oldCompletionObject )
00367 {
00368 KCompletion *c = completionObject();
00369 setCompletionObject( m_oldCompletionObject );
00370 m_oldCompletionObject = 0;
00371 delete c;
00372 c = 0;
00373 }
00374 m_command = 0;
00375 m_cmdend = 0;
00376
00377 m_view->setFocus ();
00378 QTimer::singleShot( 4000, this, SLOT(hideMe()) );
00379 }
00380
00381 void KateCmdLine::hideMe ()
00382 {
00383 if ( isVisibleTo(parentWidget()) && ! hasFocus() ) {
00384 m_view->toggleCmdLine ();
00385 }
00386 }
00387
00388 void KateCmdLine::focusInEvent ( QFocusEvent *ev )
00389 {
00390 if (m_msgMode)
00391 {
00392 m_msgMode = false;
00393 setText (m_oldText);
00394 selectAll();
00395 }
00396
00397 KLineEdit::focusInEvent (ev);
00398 }
00399
00400 void KateCmdLine::keyPressEvent( QKeyEvent *ev )
00401 {
00402 if (ev->key() == Key_Escape)
00403 {
00404 m_view->setFocus ();
00405 hideMe();
00406 }
00407 else if ( ev->key() == Key_Up )
00408 fromHistory( true );
00409 else if ( ev->key() == Key_Down )
00410 fromHistory( false );
00411
00412 uint cursorpos = cursorPosition();
00413 KLineEdit::keyPressEvent (ev);
00414
00415
00416 if ( ! m_cmdend || cursorpos <= m_cmdend )
00417 {
00418 QChar c;
00419 if ( ! ev->text().isEmpty() )
00420 c = ev->text()[0];
00421
00422 if ( ! m_cmdend && ! c.isNull() )
00423 {
00424 if ( ! c.isLetterOrNumber() && c != '-' && c != '_' )
00425 {
00426 m_command = KateCmd::self()->queryCommand( text().stripWhiteSpace() );
00427 if ( m_command )
00428 {
00429
00430
00431
00432 m_cmdend = cursorpos;
00433
00434 }
00435 else
00436 m_cmdend = 0;
00437 }
00438 }
00439 else
00440 {
00441 kdDebug(13025)<<"keypress in commandline: \\W -- text is "<<text()<<endl;
00442 m_command = KateCmd::self()->queryCommand( text().stripWhiteSpace() );
00443 if ( m_command )
00444 {
00445
00446 QString t = text();
00447 m_cmdend = 0;
00448 bool b = false;
00449 for ( ; m_cmdend < t.length(); m_cmdend++ )
00450 {
00451 if ( t[m_cmdend].isLetter() )
00452 b = true;
00453 if ( b && ( ! t[m_cmdend].isLetterOrNumber() && t[m_cmdend] != '-' && t[m_cmdend] != '_' ) )
00454 break;
00455 }
00456
00457 if ( c == ':' && cursorpos == m_cmdend )
00458 {
00459
00460
00461 }
00462 }
00463 else
00464 {
00465
00466 if ( m_oldCompletionObject )
00467 {
00468 KCompletion *c = completionObject();
00469 setCompletionObject( m_oldCompletionObject );
00470 m_oldCompletionObject = 0;
00471 delete c;
00472 c = 0;
00473 }
00474
00475 m_cmdend = 0;
00476 }
00477 }
00478
00479
00480 if ( m_command )
00481 {
00482
00483 Kate::CommandExtension *ce = dynamic_cast<Kate::CommandExtension*>(m_command);
00484 if ( ce )
00485 {
00486 KCompletion *cmpl = ce->completionObject( text().left( m_cmdend ).stripWhiteSpace(), m_view );
00487 if ( cmpl )
00488 {
00489
00490
00491
00492
00493 if ( ! m_oldCompletionObject )
00494 m_oldCompletionObject = completionObject();
00495
00496 setCompletionObject( cmpl );
00497 }
00498 }
00499 }
00500 }
00501 else if ( m_command )
00502 {
00503 Kate::CommandExtension *ce = dynamic_cast<Kate::CommandExtension*>( m_command );
00504 if ( ce && ce->wantsToProcessText( text().left( m_cmdend ).stripWhiteSpace() )
00505 && ! ( ev->text().isNull() || ev->text().isEmpty() ) )
00506 ce->processText( m_view, text() );
00507 }
00508 }
00509
00510 void KateCmdLine::fromHistory( bool up )
00511 {
00512 if ( ! KateCmd::self()->historyLength() )
00513 return;
00514
00515 QString s;
00516
00517 if ( up )
00518 {
00519 if ( m_histpos > 0 )
00520 {
00521 m_histpos--;
00522 s = KateCmd::self()->fromHistory( m_histpos );
00523 }
00524 }
00525 else
00526 {
00527 if ( m_histpos < ( KateCmd::self()->historyLength() - 1 ) )
00528 {
00529 m_histpos++;
00530 s = KateCmd::self()->fromHistory( m_histpos );
00531 }
00532 else
00533 {
00534 m_histpos = KateCmd::self()->historyLength();
00535 setText( m_oldText );
00536 }
00537 }
00538 if ( ! s.isEmpty() )
00539 {
00540
00541 setText( s );
00542 static QRegExp reCmd = QRegExp(".*[\\w\\-]+(?:[^a-zA-Z0-9_-]|:\\w+)(.*)");
00543 if ( reCmd.search( text() ) == 0 )
00544 setSelection( text().length() - reCmd.cap(1).length(), reCmd.cap(1).length() );
00545 }
00546 }
00547
00548
00549
00550 using namespace KTextEditor;
00551
00552 static const char* const plus_xpm[] = {
00553 "11 11 3 1",
00554 " c None",
00555 ". c #000000",
00556 "+ c #FFFFFF",
00557 "...........",
00558 ".+++++++++.",
00559 ".+++++++++.",
00560 ".++++.++++.",
00561 ".++++.++++.",
00562 ".++.....++.",
00563 ".++++.++++.",
00564 ".++++.++++.",
00565 ".+++++++++.",
00566 ".+++++++++.",
00567 "..........."};
00568
00569 static const char* const minus_xpm[] = {
00570 "11 11 3 1",
00571 " c None",
00572 ". c #000000",
00573 "+ c #FFFFFF",
00574 "...........",
00575 ".+++++++++.",
00576 ".+++++++++.",
00577 ".+++++++++.",
00578 ".+++++++++.",
00579 ".++.....++.",
00580 ".+++++++++.",
00581 ".+++++++++.",
00582 ".+++++++++.",
00583 ".+++++++++.",
00584 "..........."};
00585
00586 static const char * const bookmark_xpm[] = {
00587 "14 13 82 1",
00588 " c None",
00589 ". c #F27D01",
00590 "+ c #EF7901",
00591 "@ c #F3940F",
00592 "# c #EE8F12",
00593 "$ c #F9C834",
00594 "% c #F5C33A",
00595 "& c #F09110",
00596 "* c #FCEE3E",
00597 "= c #FBEB3F",
00598 "- c #E68614",
00599 "; c #FA8700",
00600 "> c #F78703",
00601 ", c #F4920E",
00602 "' c #F19113",
00603 ") c #F6C434",
00604 "! c #FDF938",
00605 "~ c #FDF839",
00606 "{ c #F1BC3A",
00607 "] c #E18017",
00608 "^ c #DA7210",
00609 "/ c #D5680B",
00610 "( c #CA5404",
00611 "_ c #FD8F06",
00612 ": c #FCB62D",
00613 "< c #FDE049",
00614 "[ c #FCE340",
00615 "} c #FBE334",
00616 "| c #FDF035",
00617 "1 c #FEF834",
00618 "2 c #FCEF36",
00619 "3 c #F8DF32",
00620 "4 c #F7DC3D",
00621 "5 c #F5CE3E",
00622 "6 c #DE861B",
00623 "7 c #C64C03",
00624 "8 c #F78C07",
00625 "9 c #F8B019",
00626 "0 c #FDE12D",
00627 "a c #FEE528",
00628 "b c #FEE229",
00629 "c c #FBD029",
00630 "d c #E18814",
00631 "e c #CB5605",
00632 "f c #EF8306",
00633 "g c #F3A00E",
00634 "h c #FBC718",
00635 "i c #FED31C",
00636 "j c #FED11D",
00637 "k c #F8B91C",
00638 "l c #E07D0D",
00639 "m c #CB5301",
00640 "n c #ED8A0E",
00641 "o c #F7A90D",
00642 "p c #FEC113",
00643 "q c #FEC013",
00644 "r c #F09B0E",
00645 "s c #D35E03",
00646 "t c #EF9213",
00647 "u c #F9A208",
00648 "v c #FEAA0C",
00649 "w c #FCA10B",
00650 "x c #FCA70B",
00651 "y c #FEAF0B",
00652 "z c #F39609",
00653 "A c #D86203",
00654 "B c #F08C0D",
00655 "C c #FA9004",
00656 "D c #F17F04",
00657 "E c #E36D04",
00658 "F c #E16F03",
00659 "G c #EE8304",
00660 "H c #F88C04",
00661 "I c #DC6202",
00662 "J c #E87204",
00663 "K c #E66A01",
00664 "L c #DC6001",
00665 "M c #D15601",
00666 "N c #DA5D01",
00667 "O c #D25200",
00668 "P c #DA5F00",
00669 "Q c #BC3C00",
00670 " .+ ",
00671 " @# ",
00672 " $% ",
00673 " &*=- ",
00674 " ;>,')!~{]^/( ",
00675 "_:<[}|11234567",
00676 " 890aaaaabcde ",
00677 " fghiiijklm ",
00678 " nopqpqrs ",
00679 " tuvwxyzA ",
00680 " BCDEFGHI ",
00681 " JKL MNO ",
00682 " P Q "};
00683
00684 const int iconPaneWidth = 16;
00685 const int halfIPW = 8;
00686
00687 KateIconBorder::KateIconBorder ( KateViewInternal* internalView, QWidget *parent )
00688 : QWidget(parent, "", Qt::WStaticContents | Qt::WRepaintNoErase | Qt::WResizeNoErase )
00689 , m_view( internalView->m_view )
00690 , m_doc( internalView->m_doc )
00691 , m_viewInternal( internalView )
00692 , m_iconBorderOn( false )
00693 , m_lineNumbersOn( false )
00694 , m_foldingMarkersOn( false )
00695 , m_dynWrapIndicatorsOn( false )
00696 , m_dynWrapIndicators( 0 )
00697 , m_cachedLNWidth( 0 )
00698 , m_maxCharWidth( 0 )
00699 {
00700 setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ) );
00701
00702 setBackgroundMode( NoBackground );
00703
00704 m_doc->setDescription( MarkInterface::markType01, i18n("Bookmark") );
00705 m_doc->setPixmap( MarkInterface::markType01, QPixmap((const char**)bookmark_xpm) );
00706
00707 updateFont();
00708 }
00709
00710 void KateIconBorder::setIconBorderOn( bool enable )
00711 {
00712 if( enable == m_iconBorderOn )
00713 return;
00714
00715 m_iconBorderOn = enable;
00716
00717 updateGeometry();
00718
00719 QTimer::singleShot( 0, this, SLOT(update()) );
00720 }
00721
00722 void KateIconBorder::setLineNumbersOn( bool enable )
00723 {
00724 if( enable == m_lineNumbersOn )
00725 return;
00726
00727 m_lineNumbersOn = enable;
00728 m_dynWrapIndicatorsOn = (m_dynWrapIndicators == 1) ? enable : m_dynWrapIndicators;
00729
00730 updateGeometry();
00731
00732 QTimer::singleShot( 0, this, SLOT(update()) );
00733 }
00734
00735 void KateIconBorder::setDynWrapIndicators( int state )
00736 {
00737 if (state == m_dynWrapIndicators )
00738 return;
00739
00740 m_dynWrapIndicators = state;
00741 m_dynWrapIndicatorsOn = (state == 1) ? m_lineNumbersOn : state;
00742
00743 updateGeometry ();
00744
00745 QTimer::singleShot( 0, this, SLOT(update()) );
00746 }
00747
00748 void KateIconBorder::setFoldingMarkersOn( bool enable )
00749 {
00750 if( enable == m_foldingMarkersOn )
00751 return;
00752
00753 m_foldingMarkersOn = enable;
00754
00755 updateGeometry();
00756
00757 QTimer::singleShot( 0, this, SLOT(update()) );
00758 }
00759
00760 QSize KateIconBorder::sizeHint() const
00761 {
00762 int w = 0;
00763
00764 if (m_iconBorderOn)
00765 w += iconPaneWidth + 1;
00766
00767 if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) {
00768 w += lineNumberWidth();
00769 }
00770
00771 if (m_foldingMarkersOn)
00772 w += iconPaneWidth;
00773
00774 w += 4;
00775
00776 return QSize( w, 0 );
00777 }
00778
00779
00780
00781 void KateIconBorder::updateFont()
00782 {
00783 const QFontMetrics *fm = m_view->renderer()->config()->fontMetrics();
00784 m_maxCharWidth = 0;
00785
00786
00787 for (int i = 48; i < 58; i++) {
00788 int charWidth = fm->width( QChar(i) );
00789 m_maxCharWidth = kMax(m_maxCharWidth, charWidth);
00790 }
00791 }
00792
00793 int KateIconBorder::lineNumberWidth() const
00794 {
00795 int width = m_lineNumbersOn ? ((int)log10((double)(m_view->doc()->numLines())) + 1) * m_maxCharWidth + 4 : 0;
00796
00797 if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
00798 width = kMax(style().scrollBarExtent().width() + 4, width);
00799
00800 if (m_cachedLNWidth != width || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) {
00801 int w = style().scrollBarExtent().width();
00802 int h = m_view->renderer()->config()->fontMetrics()->height();
00803
00804 QSize newSize(w, h);
00805 if ((m_arrow.size() != newSize || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) && !newSize.isEmpty()) {
00806 m_arrow.resize(newSize);
00807
00808 QPainter p(&m_arrow);
00809 p.fillRect( 0, 0, w, h, m_view->renderer()->config()->iconBarColor() );
00810
00811 h = m_view->renderer()->config()->fontMetrics()->ascent();
00812
00813 p.setPen(m_view->renderer()->attribute(0)->textColor());
00814 p.drawLine(w/2, h/2, w/2, 0);
00815 #if 1
00816 p.lineTo(w/4, h/4);
00817 p.lineTo(0, 0);
00818 p.lineTo(0, h/2);
00819 p.lineTo(w/2, h-1);
00820 p.lineTo(w*3/4, h-1);
00821 p.lineTo(w-1, h*3/4);
00822 p.lineTo(w*3/4, h/2);
00823 p.lineTo(0, h/2);
00824 #else
00825 p.lineTo(w*3/4, h/4);
00826 p.lineTo(w-1,0);
00827 p.lineTo(w-1, h/2);
00828 p.lineTo(w/2, h-1);
00829 p.lineTo(w/4,h-1);
00830 p.lineTo(0, h*3/4);
00831 p.lineTo(w/4, h/2);
00832 p.lineTo(w-1, h/2);
00833 #endif
00834 }
00835 }
00836 }
00837
00838 return width;
00839 }
00840
00841 void KateIconBorder::paintEvent(QPaintEvent* e)
00842 {
00843 paintBorder(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
00844 }
00845
00846 void KateIconBorder::paintBorder (int , int y, int , int height)
00847 {
00848 static QPixmap minus_px ((const char**)minus_xpm);
00849 static QPixmap plus_px ((const char**)plus_xpm);
00850
00851 uint h = m_view->renderer()->config()->fontStruct()->fontHeight;
00852 uint startz = (y / h);
00853 uint endz = startz + 1 + (height / h);
00854 uint lineRangesSize = m_viewInternal->lineRanges.size();
00855
00856
00857 int m_px = (h - 11) / 2;
00858 if (m_px < 0)
00859 m_px = 0;
00860
00861 int lnWidth( 0 );
00862 if ( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) )
00863 {
00864 lnWidth = lineNumberWidth();
00865 if ( lnWidth != m_cachedLNWidth || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor() )
00866 {
00867
00868
00869
00870
00871 m_cachedLNWidth = lnWidth;
00872 m_oldBackgroundColor = m_view->renderer()->config()->iconBarColor();
00873 updateGeometry();
00874 update ();
00875 return;
00876 }
00877 }
00878
00879 int w( this->width() );
00880
00881 QPainter p ( this );
00882 p.setFont ( *m_view->renderer()->config()->font() );
00883
00884
00885 p.setPen ( m_view->renderer()->config()->lineNumberColor() );
00886
00887 KateLineInfo oldInfo;
00888 if (startz < lineRangesSize)
00889 {
00890 if ((m_viewInternal->lineRanges[startz].line-1) < 0)
00891 oldInfo.topLevel = true;
00892 else
00893 m_doc->lineInfo(&oldInfo,m_viewInternal->lineRanges[startz].line-1);
00894 }
00895
00896 for (uint z=startz; z <= endz; z++)
00897 {
00898 int y = h * z;
00899 int realLine = -1;
00900
00901 if (z < lineRangesSize)
00902 realLine = m_viewInternal->lineRanges[z].line;
00903
00904 int lnX ( 0 );
00905
00906 p.fillRect( 0, y, w-4, h, m_view->renderer()->config()->iconBarColor() );
00907 p.fillRect( w-4, y, 4, h, m_view->renderer()->config()->backgroundColor() );
00908
00909
00910 if( m_iconBorderOn )
00911 {
00912 p.drawLine(lnX+iconPaneWidth, y, lnX+iconPaneWidth, y+h);
00913
00914 if( (realLine > -1) && (m_viewInternal->lineRanges[z].startCol == 0) )
00915 {
00916 uint mrk ( m_doc->mark( realLine ) );
00917
00918 if ( mrk )
00919 {
00920 for( uint bit = 0; bit < 32; bit++ )
00921 {
00922 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
00923 if( mrk & markType )
00924 {
00925 QPixmap *px_mark (m_doc->markPixmap( markType ));
00926
00927 if (px_mark)
00928 {
00929
00930 int x_px = (iconPaneWidth - px_mark->width()) / 2;
00931 if (x_px < 0)
00932 x_px = 0;
00933
00934 int y_px = (h - px_mark->height()) / 2;
00935 if (y_px < 0)
00936 y_px = 0;
00937
00938 p.drawPixmap( lnX+x_px, y+y_px, *px_mark);
00939 }
00940 }
00941 }
00942 }
00943 }
00944
00945 lnX += iconPaneWidth + 1;
00946 }
00947
00948
00949 if( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) )
00950 {
00951 lnX +=2;
00952
00953 if (realLine > -1)
00954 if (m_viewInternal->lineRanges[z].startCol == 0) {
00955 if (m_lineNumbersOn)
00956 p.drawText( lnX + 1, y, lnWidth-4, h, Qt::AlignRight|Qt::AlignVCenter, QString("%1").arg( realLine + 1 ) );
00957 } else if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
00958 p.drawPixmap(lnX + lnWidth - m_arrow.width() - 4, y, m_arrow);
00959 }
00960
00961 lnX += lnWidth;
00962 }
00963
00964
00965 if( m_foldingMarkersOn )
00966 {
00967 if( realLine > -1 )
00968 {
00969 KateLineInfo info;
00970 m_doc->lineInfo(&info,realLine);
00971
00972 if (!info.topLevel)
00973 {
00974 if (info.startsVisibleBlock && (m_viewInternal->lineRanges[z].startCol == 0))
00975 {
00976 if (oldInfo.topLevel)
00977 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1);
00978 else
00979 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00980
00981 p.drawPixmap(lnX+3,y+m_px,minus_px);
00982 }
00983 else if (info.startsInVisibleBlock)
00984 {
00985 if (m_viewInternal->lineRanges[z].startCol == 0)
00986 {
00987 if (oldInfo.topLevel)
00988 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1);
00989 else
00990 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00991
00992 p.drawPixmap(lnX+3,y+m_px,plus_px);
00993 }
00994 else
00995 {
00996 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
00997 }
00998
00999 if (!m_viewInternal->lineRanges[z].wrap)
01000 p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
01001 }
01002 else
01003 {
01004 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
01005
01006 if (info.endsBlock && !m_viewInternal->lineRanges[z].wrap)
01007 p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
01008 }
01009 }
01010
01011 oldInfo = info;
01012 }
01013
01014 lnX += iconPaneWidth;
01015 }
01016 }
01017 }
01018
01019 KateIconBorder::BorderArea KateIconBorder::positionToArea( const QPoint& p ) const
01020 {
01021 int x = 0;
01022 if( m_iconBorderOn ) {
01023 x += iconPaneWidth;
01024 if( p.x() <= x )
01025 return IconBorder;
01026 }
01027 if( m_lineNumbersOn || m_dynWrapIndicators ) {
01028 x += lineNumberWidth();
01029 if( p.x() <= x )
01030 return LineNumbers;
01031 }
01032 if( m_foldingMarkersOn ) {
01033 x += iconPaneWidth;
01034 if( p.x() <= x )
01035 return FoldingMarkers;
01036 }
01037 return None;
01038 }
01039
01040 void KateIconBorder::mousePressEvent( QMouseEvent* e )
01041 {
01042 m_lastClickedLine = m_viewInternal->yToKateLineRange(e->y()).line;
01043
01044 if ( positionToArea( e->pos() ) != IconBorder )
01045 {
01046 QMouseEvent forward( QEvent::MouseButtonPress,
01047 QPoint( 0, e->y() ), e->button(), e->state() );
01048 m_viewInternal->mousePressEvent( &forward );
01049 }
01050 e->accept();
01051 }
01052
01053 void KateIconBorder::mouseMoveEvent( QMouseEvent* e )
01054 {
01055 if ( positionToArea( e->pos() ) != IconBorder )
01056 {
01057 QMouseEvent forward( QEvent::MouseMove,
01058 QPoint( 0, e->y() ), e->button(), e->state() );
01059 m_viewInternal->mouseMoveEvent( &forward );
01060 }
01061 }
01062
01063 void KateIconBorder::mouseReleaseEvent( QMouseEvent* e )
01064 {
01065 uint cursorOnLine = m_viewInternal->yToKateLineRange(e->y()).line;
01066
01067 if (cursorOnLine == m_lastClickedLine &&
01068 cursorOnLine <= m_doc->lastLine() )
01069 {
01070 BorderArea area = positionToArea( e->pos() );
01071 if( area == IconBorder) {
01072 if (e->button() == LeftButton) {
01073 if( m_doc->editableMarks() & KateViewConfig::global()->defaultMarkType() ) {
01074 if( m_doc->mark( cursorOnLine ) & KateViewConfig::global()->defaultMarkType() )
01075 m_doc->removeMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
01076 else
01077 m_doc->addMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
01078 } else {
01079 showMarkMenu( cursorOnLine, QCursor::pos() );
01080 }
01081 }
01082 else
01083 if (e->button() == RightButton) {
01084 showMarkMenu( cursorOnLine, QCursor::pos() );
01085 }
01086 }
01087
01088 if ( area == FoldingMarkers) {
01089 KateLineInfo info;
01090 m_doc->lineInfo(&info,cursorOnLine);
01091 if ((info.startsVisibleBlock) || (info.startsInVisibleBlock)) {
01092 emit toggleRegionVisibility(cursorOnLine);
01093 }
01094 }
01095 }
01096
01097 QMouseEvent forward( QEvent::MouseButtonRelease,
01098 QPoint( 0, e->y() ), e->button(), e->state() );
01099 m_viewInternal->mouseReleaseEvent( &forward );
01100 }
01101
01102 void KateIconBorder::mouseDoubleClickEvent( QMouseEvent* e )
01103 {
01104 QMouseEvent forward( QEvent::MouseButtonDblClick,
01105 QPoint( 0, e->y() ), e->button(), e->state() );
01106 m_viewInternal->mouseDoubleClickEvent( &forward );
01107 }
01108
01109 void KateIconBorder::showMarkMenu( uint line, const QPoint& pos )
01110 {
01111 QPopupMenu markMenu;
01112 QPopupMenu selectDefaultMark;
01113
01114 typedef QValueVector<int> MarkTypeVector;
01115 MarkTypeVector vec( 33 );
01116 int i=1;
01117
01118 for( uint bit = 0; bit < 32; bit++ ) {
01119 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
01120 if( !(m_doc->editableMarks() & markType) )
01121 continue;
01122
01123 if( !m_doc->markDescription( markType ).isEmpty() ) {
01124 markMenu.insertItem( m_doc->markDescription( markType ), i );
01125 selectDefaultMark.insertItem( m_doc->markDescription( markType ), i+100);
01126 } else {
01127 markMenu.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i );
01128 selectDefaultMark.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i+100);
01129 }
01130
01131 if( m_doc->mark( line ) & markType )
01132 markMenu.setItemChecked( i, true );
01133
01134 if( markType & KateViewConfig::global()->defaultMarkType() )
01135 selectDefaultMark.setItemChecked( i+100, true );
01136
01137 vec[i++] = markType;
01138 }
01139
01140 if( markMenu.count() == 0 )
01141 return;
01142
01143 if( markMenu.count() > 1 )
01144 markMenu.insertItem( i18n("Set Default Mark Type" ), &selectDefaultMark);
01145
01146 int result = markMenu.exec( pos );
01147 if( result <= 0 )
01148 return;
01149
01150 if ( result > 100)
01151 {
01152 KateViewConfig::global()->setDefaultMarkType (vec[result-100]);
01153
01154 KConfig *config = kapp->config();
01155 config->setGroup("Kate View Defaults");
01156 KateViewConfig::global()->writeConfig( config );
01157 }
01158 else
01159 {
01160 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes) vec[result];
01161 if( m_doc->mark( line ) & markType ) {
01162 m_doc->removeMark( line, markType );
01163 } else {
01164 m_doc->addMark( line, markType );
01165 }
01166 }
01167 }
01168
01169
01170 KateViewEncodingAction::KateViewEncodingAction(KateDocument *_doc, KateView *_view, const QString& text, QObject* parent, const char* name)
01171 : KActionMenu (text, parent, name), doc(_doc), view (_view)
01172 {
01173 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow()));
01174 }
01175
01176 void KateViewEncodingAction::slotAboutToShow()
01177 {
01178 QStringList modes (KGlobal::charsets()->descriptiveEncodingNames());
01179
01180 popupMenu()->clear ();
01181 for (uint z=0; z<modes.size(); ++z)
01182 {
01183 popupMenu()->insertItem ( modes[z], this, SLOT(setMode(int)), 0, z);
01184
01185 bool found = false;
01186 QTextCodec *codecForEnc = KGlobal::charsets()->codecForName(KGlobal::charsets()->encodingForName(modes[z]), found);
01187
01188 if (found && codecForEnc)
01189 {
01190 if (codecForEnc->name() == doc->config()->codec()->name())
01191 popupMenu()->setItemChecked (z, true);
01192 }
01193 }
01194 }
01195
01196 void KateViewEncodingAction::setMode (int mode)
01197 {
01198 QStringList modes (KGlobal::charsets()->descriptiveEncodingNames());
01199 doc->config()->setEncoding( KGlobal::charsets()->encodingForName( modes[mode] ) );
01200
01201 doc->setEncodingSticky( true );
01202 doc->reloadFile();
01203 }
01204
01205