kate Library API Documentation

kateviewhelpers.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org> 00003 Copyright (C) 2001 Anders Lund <anders@alweb.dk> 00004 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2 as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 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 //BEGIN KateCmdLnWhatsThis 00057 class KateCmdLnWhatsThis : public QWhatsThis 00058 { 00059 public: 00060 KateCmdLnWhatsThis( KateCmdLine *parent ) 00061 : QWhatsThis( parent ) 00062 , m_parent( parent ) {;} 00063 00064 QString text( const QPoint & ) 00065 { 00066 QString beg = "<qt background=\"white\"><div><table width=\"100%\"><tr><td bgcolor=\"brown\"><font color=\"white\"><b>Help: <big>"; 00067 QString mid = "</big></b></font></td></tr><tr><td>"; 00068 QString end = "</td></tr></table></div><qt>"; 00069 00070 QString t = m_parent->text(); 00071 QRegExp re( "\\s*help\\s+(.*)" ); 00072 if ( re.search( t ) > -1 ) 00073 { 00074 QString s; 00075 // get help for command 00076 QString name = re.cap( 1 ); 00077 if ( name == "list" ) 00078 { 00079 return beg + i18n("Available Commands") + mid 00080 + KateCmd::self()->cmds().join(" ") 00081 + i18n("<p>For help on individual commands, do <code>'help &lt;command&gt;'</code></p>") 00082 + end; 00083 } 00084 else if ( ! name.isEmpty() ) 00085 { 00086 Kate::Command *cmd = KateCmd::self()->queryCommand( name ); 00087 if ( cmd ) 00088 { 00089 if ( cmd->help( (Kate::View*)m_parent->parentWidget(), name, s ) ) 00090 return beg + name + mid + s + end; 00091 else 00092 return beg + name + mid + i18n("No help for '%1'").arg( name ) + end; 00093 } 00094 else 00095 return beg + mid + i18n("No such command <b>%1</b>").arg(name) + end; 00096 } 00097 } 00098 00099 return beg + mid + i18n( 00100 "<p>This is the Katepart <b>command line</b>.<br>" 00101 "Syntax: <code><b>command [ arguments ]</b></code><br>" 00102 "For a list of available commands, enter <code><b>help list</b></code><br>" 00103 "For help for individual commands, enter <code><b>help &lt;command&gt;</b></code></p>") 00104 + end; 00105 } 00106 00107 private: 00108 KateCmdLine *m_parent; 00109 }; 00110 //END KateCmdLnWhatsThis 00111 00112 //BEGIN KateCmdLineFlagCompletion 00117 class KateCmdLineFlagCompletion : public KCompletion 00118 { 00119 public: 00120 KateCmdLineFlagCompletion() {;} 00121 00122 QString makeCompletion( const QString & s ) 00123 { 00124 return QString::null; 00125 } 00126 00127 }; 00128 //END KateCmdLineFlagCompletion 00129 00130 //BEGIN KateCmdLine 00131 KateCmdLine::KateCmdLine (KateView *view) 00132 : KLineEdit (view) 00133 , m_view (view) 00134 , m_msgMode (false) 00135 , m_histpos( 0 ) 00136 , m_cmdend( 0 ) 00137 , m_command( 0L ) 00138 , m_oldCompletionObject( 0L ) 00139 { 00140 connect (this, SIGNAL(returnPressed(const QString &)), 00141 this, SLOT(slotReturnPressed(const QString &))); 00142 00143 completionObject()->insertItems (KateCmd::self()->cmds()); 00144 setAutoDeleteCompletionObject( false ); 00145 m_help = new KateCmdLnWhatsThis( this ); 00146 } 00147 00148 void KateCmdLine::slotReturnPressed ( const QString& text ) 00149 { 00150 00151 // silently ignore leading space 00152 uint n = 0; 00153 while( text[n].isSpace() ) 00154 n++; 00155 00156 QString cmd = text.mid( n ); 00157 00158 // Built in help: if the command starts with "help", [try to] show some help 00159 if ( cmd.startsWith( "help" ) ) 00160 { 00161 m_help->display( m_help->text( QPoint() ), mapToGlobal(QPoint(0,0)) ); 00162 clear(); 00163 KateCmd::self()->appendHistory( cmd ); 00164 m_histpos = KateCmd::self()->historyLength(); 00165 m_oldText = QString (); 00166 return; 00167 } 00168 00169 if (cmd.length () > 0) 00170 { 00171 Kate::Command *p = KateCmd::self()->queryCommand (cmd); 00172 00173 m_oldText = cmd; 00174 m_msgMode = true; 00175 00176 if (p) 00177 { 00178 QString msg; 00179 00180 if (p->exec (m_view, cmd, msg)) 00181 { 00182 KateCmd::self()->appendHistory( cmd ); 00183 m_histpos = KateCmd::self()->historyLength(); 00184 m_oldText = QString (); 00185 00186 if (msg.length() > 0) 00187 setText (i18n ("Success: ") + msg); 00188 else 00189 setText (i18n ("Success")); 00190 } 00191 else 00192 { 00193 if (msg.length() > 0) 00194 setText (i18n ("Error: ") + msg); 00195 else 00196 setText (i18n ("Command \"%1\" failed.").arg (cmd)); 00197 KNotifyClient::beep(); 00198 } 00199 } 00200 else 00201 { 00202 setText (i18n ("No such command: \"%1\"").arg (cmd)); 00203 KNotifyClient::beep(); 00204 } 00205 } 00206 00207 // clean up 00208 if ( m_oldCompletionObject ) 00209 { 00210 KCompletion *c = completionObject(); 00211 setCompletionObject( m_oldCompletionObject ); 00212 m_oldCompletionObject = 0; 00213 delete c; 00214 c = 0; 00215 } 00216 m_command = 0; 00217 m_cmdend = 0; 00218 00219 m_view->setFocus (); 00220 QTimer::singleShot( 4000, this, SLOT(hideMe()) ); 00221 } 00222 00223 void KateCmdLine::hideMe () // unless i have focus ;) 00224 { 00225 if ( isVisibleTo(parentWidget()) && ! hasFocus() ) { 00226 m_view->toggleCmdLine (); 00227 } 00228 } 00229 00230 void KateCmdLine::focusInEvent ( QFocusEvent *ev ) 00231 { 00232 if (m_msgMode) 00233 { 00234 m_msgMode = false; 00235 setText (m_oldText); 00236 selectAll(); 00237 } 00238 00239 KLineEdit::focusInEvent (ev); 00240 } 00241 00242 void KateCmdLine::keyPressEvent( QKeyEvent *ev ) 00243 { 00244 if (ev->key() == Key_Escape) 00245 { 00246 m_view->setFocus (); 00247 hideMe(); 00248 } 00249 else if ( ev->key() == Key_Up ) 00250 fromHistory( true ); 00251 else if ( ev->key() == Key_Down ) 00252 fromHistory( false ); 00253 00254 uint cursorpos = cursorPosition(); 00255 KLineEdit::keyPressEvent (ev); 00256 00257 // during typing, let us see if we have a valid command 00258 if ( ! m_cmdend || cursorpos <= m_cmdend ) 00259 { 00260 QChar c; 00261 if ( ! ev->text().isEmpty() ) 00262 c = ev->text()[0]; 00263 00264 if ( ! m_cmdend && ! c.isNull() ) // we have no command, so lets see if we got one 00265 { 00266 if ( ! c.isLetterOrNumber() && c != '-' && c != '_' ) 00267 { 00268 m_command = KateCmd::self()->queryCommand( text().stripWhiteSpace() ); 00269 if ( m_command ) 00270 { 00271 //kdDebug(13025)<<"keypress in commandline: We have a command! "<<m_command<<". text is '"<<text()<<"'"<<endl; 00272 // if the typed character is ":", 00273 // we try if the command has flag completions 00274 m_cmdend = cursorpos; 00275 //kdDebug(13025)<<"keypress in commandline: Set m_cmdend to "<<m_cmdend<<endl; 00276 } 00277 else 00278 m_cmdend = 0; 00279 } 00280 } 00281 else // since cursor is inside the command name, we reconsider it 00282 { 00283 kdDebug(13025)<<"keypress in commandline: \\W -- text is "<<text()<<endl; 00284 m_command = KateCmd::self()->queryCommand( text().stripWhiteSpace() ); 00285 if ( m_command ) 00286 { 00287 //kdDebug(13025)<<"keypress in commandline: We have a command! "<<m_command<<endl; 00288 QString t = text(); 00289 m_cmdend = 0; 00290 bool b = false; 00291 for ( ; m_cmdend < t.length(); m_cmdend++ ) 00292 { 00293 if ( t[m_cmdend].isLetter() ) 00294 b = true; 00295 if ( b && ( ! t[m_cmdend].isLetterOrNumber() && t[m_cmdend] != '-' && t[m_cmdend] != '_' ) ) 00296 break; 00297 } 00298 00299 if ( c == ':' && cursorpos == m_cmdend ) 00300 { 00301 // check if this command wants to complete flags 00302 //kdDebug(13025)<<"keypress in commandline: Checking if flag completion is desired!"<<endl; 00303 } 00304 } 00305 else 00306 { 00307 // clean up if needed 00308 if ( m_oldCompletionObject ) 00309 { 00310 KCompletion *c = completionObject(); 00311 setCompletionObject( m_oldCompletionObject ); 00312 m_oldCompletionObject = 0; 00313 delete c; 00314 c = 0; 00315 } 00316 00317 m_cmdend = 0; 00318 } 00319 } 00320 00321 // if we got a command, check if it wants to do semething. 00322 if ( m_command ) 00323 { 00324 //kdDebug(13025)<<"Checking for CommandExtension.."<<endl; 00325 Kate::CommandExtension *ce = dynamic_cast<Kate::CommandExtension*>(m_command); 00326 if ( ce ) 00327 { 00328 KCompletion *cmpl = ce->completionObject( text().left( m_cmdend ).stripWhiteSpace(), m_view ); 00329 if ( cmpl ) 00330 { 00331 // save the old completion object and use what the command provides 00332 // instead. We also need to prepend the current command name + flag string 00333 // when completion is done 00334 //kdDebug(13025)<<"keypress in commandline: Setting completion object!"<<endl; 00335 if ( ! m_oldCompletionObject ) 00336 m_oldCompletionObject = completionObject(); 00337 00338 setCompletionObject( cmpl ); 00339 } 00340 } 00341 } 00342 } 00343 else if ( m_command )// check if we should call the commands processText() 00344 { 00345 Kate::CommandExtension *ce = dynamic_cast<Kate::CommandExtension*>( m_command ); 00346 if ( ce && ce->wantsToProcessText( text().left( m_cmdend ).stripWhiteSpace() ) 00347 && ! ( ev->text().isNull() || ev->text().isEmpty() ) ) 00348 ce->processText( m_view, text() ); 00349 } 00350 } 00351 00352 void KateCmdLine::fromHistory( bool up ) 00353 { 00354 if ( ! KateCmd::self()->historyLength() ) 00355 return; 00356 00357 QString s; 00358 00359 if ( up ) 00360 { 00361 if ( m_histpos > 0 ) 00362 { 00363 m_histpos--; 00364 s = KateCmd::self()->fromHistory( m_histpos ); 00365 } 00366 } 00367 else 00368 { 00369 if ( m_histpos < ( KateCmd::self()->historyLength() - 1 ) ) 00370 { 00371 m_histpos++; 00372 s = KateCmd::self()->fromHistory( m_histpos ); 00373 } 00374 else 00375 { 00376 m_histpos = KateCmd::self()->historyLength(); 00377 setText( m_oldText ); 00378 } 00379 } 00380 if ( ! s.isEmpty() ) 00381 { 00382 // Select the argument part of the command, so that it is easy to overwrite 00383 setText( s ); 00384 static QRegExp reCmd = QRegExp(".*[\\w\\-]+(?:[^a-zA-Z0-9_-]|:\\w+)(.*)"); 00385 if ( reCmd.search( text() ) == 0 ) 00386 setSelection( text().length() - reCmd.cap(1).length(), reCmd.cap(1).length() ); 00387 } 00388 } 00389 //END KateCmdLine 00390 00391 //BEGIN KateIconBorder 00392 using namespace KTextEditor; 00393 00394 static const char* const plus_xpm[] = { 00395 "11 11 3 1", 00396 " c None", 00397 ". c #000000", 00398 "+ c #FFFFFF", 00399 "...........", 00400 ".+++++++++.", 00401 ".+++++++++.", 00402 ".++++.++++.", 00403 ".++++.++++.", 00404 ".++.....++.", 00405 ".++++.++++.", 00406 ".++++.++++.", 00407 ".+++++++++.", 00408 ".+++++++++.", 00409 "..........."}; 00410 00411 static const char* const minus_xpm[] = { 00412 "11 11 3 1", 00413 " c None", 00414 ". c #000000", 00415 "+ c #FFFFFF", 00416 "...........", 00417 ".+++++++++.", 00418 ".+++++++++.", 00419 ".+++++++++.", 00420 ".+++++++++.", 00421 ".++.....++.", 00422 ".+++++++++.", 00423 ".+++++++++.", 00424 ".+++++++++.", 00425 ".+++++++++.", 00426 "..........."}; 00427 00428 00429 static const char* const bookmark_xpm[]={ 00430 "12 12 4 1", 00431 "b c #808080", 00432 "a c #000080", 00433 "# c #0000ff", 00434 ". c None", 00435 "........###.", 00436 ".......#...a", 00437 "......#.##.a", 00438 ".....#.#..aa", 00439 "....#.#...a.", 00440 "...#.#.a.a..", 00441 "..#.#.a.a...", 00442 ".#.#.a.a....", 00443 "#.#.a.a.....", 00444 "#.#a.a...bbb", 00445 "#...a..bbb..", 00446 ".aaa.bbb...."}; 00447 00448 const int iconPaneWidth = 16; 00449 const int halfIPW = 8; 00450 00451 static QPixmap minus_px ((const char**)minus_xpm); 00452 static QPixmap plus_px ((const char**)plus_xpm); 00453 00454 KateIconBorder::KateIconBorder ( KateViewInternal* internalView, QWidget *parent ) 00455 : QWidget(parent, "", Qt::WStaticContents | Qt::WRepaintNoErase | Qt::WResizeNoErase ) 00456 , m_view( internalView->m_view ) 00457 , m_doc( internalView->m_doc ) 00458 , m_viewInternal( internalView ) 00459 , m_iconBorderOn( false ) 00460 , m_lineNumbersOn( false ) 00461 , m_foldingMarkersOn( false ) 00462 , m_dynWrapIndicatorsOn( false ) 00463 , m_dynWrapIndicators( 0 ) 00464 , m_cachedLNWidth( 0 ) 00465 , m_maxCharWidth( 0 ) 00466 { 00467 setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ) ); 00468 00469 setBackgroundMode( NoBackground ); 00470 00471 m_doc->setDescription( MarkInterface::markType01, i18n("Bookmark") ); 00472 m_doc->setPixmap( MarkInterface::markType01, QPixmap((const char**)bookmark_xpm) ); 00473 00474 updateFont(); 00475 } 00476 00477 void KateIconBorder::setIconBorderOn( bool enable ) 00478 { 00479 if( enable == m_iconBorderOn ) 00480 return; 00481 00482 m_iconBorderOn = enable; 00483 00484 updateGeometry(); 00485 00486 QTimer::singleShot( 0, this, SLOT(update()) ); 00487 } 00488 00489 void KateIconBorder::setLineNumbersOn( bool enable ) 00490 { 00491 if( enable == m_lineNumbersOn ) 00492 return; 00493 00494 m_lineNumbersOn = enable; 00495 m_dynWrapIndicatorsOn = (m_dynWrapIndicators == 1) ? enable : m_dynWrapIndicators; 00496 00497 updateGeometry(); 00498 00499 QTimer::singleShot( 0, this, SLOT(update()) ); 00500 } 00501 00502 void KateIconBorder::setDynWrapIndicators( int state ) 00503 { 00504 if (state == m_dynWrapIndicators ) 00505 return; 00506 00507 m_dynWrapIndicators = state; 00508 m_dynWrapIndicatorsOn = (state == 1) ? m_lineNumbersOn : state; 00509 00510 updateGeometry (); 00511 00512 QTimer::singleShot( 0, this, SLOT(update()) ); 00513 } 00514 00515 void KateIconBorder::setFoldingMarkersOn( bool enable ) 00516 { 00517 if( enable == m_foldingMarkersOn ) 00518 return; 00519 00520 m_foldingMarkersOn = enable; 00521 00522 updateGeometry(); 00523 00524 QTimer::singleShot( 0, this, SLOT(update()) ); 00525 } 00526 00527 QSize KateIconBorder::sizeHint() const 00528 { 00529 int w = 0; 00530 00531 if (m_iconBorderOn) 00532 w += iconPaneWidth + 1; 00533 00534 if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) { 00535 w += lineNumberWidth(); 00536 } 00537 00538 if (m_foldingMarkersOn) 00539 w += iconPaneWidth; 00540 00541 w += 4; 00542 00543 return QSize( w, 0 ); 00544 } 00545 00546 // This function (re)calculates the maximum width of any of the digit characters (0 -> 9) 00547 // for graceful handling of variable-width fonts as the linenumber font. 00548 void KateIconBorder::updateFont() 00549 { 00550 const QFontMetrics *fm = m_view->renderer()->config()->fontMetrics(); 00551 m_maxCharWidth = 0; 00552 // Loop to determine the widest numeric character in the current font. 00553 // 48 is ascii '0' 00554 for (int i = 48; i < 58; i++) { 00555 int charWidth = fm->width( QChar(i) ); 00556 m_maxCharWidth = QMAX(m_maxCharWidth, charWidth); 00557 } 00558 } 00559 00560 int KateIconBorder::lineNumberWidth() const 00561 { 00562 int width = m_lineNumbersOn ? ((int)log10((double)(m_view->doc()->numLines())) + 1) * m_maxCharWidth + 4 : 0; 00563 00564 if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) { 00565 width = QMAX(style().scrollBarExtent().width() + 4, width); 00566 00567 if (m_cachedLNWidth != width || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) { 00568 int w = style().scrollBarExtent().width(); 00569 int h = m_view->renderer()->config()->fontMetrics()->height(); 00570 00571 QSize newSize(w, h); 00572 if ((m_arrow.size() != newSize || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) && !newSize.isEmpty()) { 00573 m_arrow.resize(newSize); 00574 00575 QPainter p(&m_arrow); 00576 p.fillRect( 0, 0, w, h, m_view->renderer()->config()->iconBarColor() ); 00577 00578 h = m_view->renderer()->config()->fontMetrics()->ascent(); 00579 00580 p.setPen(m_view->renderer()->attribute(0)->textColor()); 00581 p.drawLine(w/2, h/2, w/2, 0); 00582 #if 1 00583 p.lineTo(w/4, h/4); 00584 p.lineTo(0, 0); 00585 p.lineTo(0, h/2); 00586 p.lineTo(w/2, h-1); 00587 p.lineTo(w*3/4, h-1); 00588 p.lineTo(w-1, h*3/4); 00589 p.lineTo(w*3/4, h/2); 00590 p.lineTo(0, h/2); 00591 #else 00592 p.lineTo(w*3/4, h/4); 00593 p.lineTo(w-1,0); 00594 p.lineTo(w-1, h/2); 00595 p.lineTo(w/2, h-1); 00596 p.lineTo(w/4,h-1); 00597 p.lineTo(0, h*3/4); 00598 p.lineTo(w/4, h/2); 00599 p.lineTo(w-1, h/2); 00600 #endif 00601 } 00602 } 00603 } 00604 00605 return width; 00606 } 00607 00608 void KateIconBorder::paintEvent(QPaintEvent* e) 00609 { 00610 paintBorder(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height()); 00611 } 00612 00613 void KateIconBorder::paintBorder (int /*x*/, int y, int /*width*/, int height) 00614 { 00615 uint h = m_view->renderer()->config()->fontStruct()->fontHeight; 00616 uint startz = (y / h); 00617 uint endz = startz + 1 + (height / h); 00618 uint lineRangesSize = m_viewInternal->lineRanges.size(); 00619 00620 // center the folding boxes 00621 int m_px = (h - 11) / 2; 00622 if (m_px < 0) 00623 m_px = 0; 00624 00625 int lnWidth( 0 ); 00626 if ( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) // avoid calculating unless needed ;-) 00627 { 00628 lnWidth = lineNumberWidth(); 00629 if ( lnWidth != m_cachedLNWidth || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor() ) 00630 { 00631 // we went from n0 ->n9 lines or vice verca 00632 // this causes an extra updateGeometry() first time the line numbers 00633 // are displayed, but sizeHint() is supposed to be const so we can't set 00634 // the cached value there. 00635 m_cachedLNWidth = lnWidth; 00636 m_oldBackgroundColor = m_view->renderer()->config()->iconBarColor(); 00637 updateGeometry(); 00638 update (); 00639 return; 00640 } 00641 } 00642 00643 int w( this->width() ); // sane value/calc only once 00644 00645 QPainter p ( this ); 00646 p.setFont ( *m_view->renderer()->config()->font() ); // for line numbers 00647 // the line number color is for the line numbers, vertical separator lines 00648 // and for for the code folding lines. 00649 p.setPen ( m_view->renderer()->config()->lineNumberColor() ); 00650 00651 KateLineInfo oldInfo; 00652 if (startz < lineRangesSize) 00653 { 00654 if ((m_viewInternal->lineRanges[startz].line-1) < 0) 00655 oldInfo.topLevel = true; 00656 else 00657 m_doc->lineInfo(&oldInfo,m_viewInternal->lineRanges[startz].line-1); 00658 } 00659 00660 for (uint z=startz; z <= endz; z++) 00661 { 00662 int y = h * z; 00663 int realLine = -1; 00664 00665 if (z < lineRangesSize) 00666 realLine = m_viewInternal->lineRanges[z].line; 00667 00668 int lnX ( 0 ); 00669 00670 p.fillRect( 0, y, w-4, h, m_view->renderer()->config()->iconBarColor() ); 00671 p.fillRect( w-4, y, 4, h, m_view->renderer()->config()->backgroundColor() ); 00672 00673 // icon pane 00674 if( m_iconBorderOn ) 00675 { 00676 p.drawLine(lnX+iconPaneWidth, y, lnX+iconPaneWidth, y+h); 00677 00678 if( (realLine > -1) && (m_viewInternal->lineRanges[z].startCol == 0) ) 00679 { 00680 uint mrk ( m_doc->mark( realLine ) ); // call only once 00681 00682 if ( mrk ) 00683 { 00684 for( uint bit = 0; bit < 32; bit++ ) 00685 { 00686 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit); 00687 if( mrk & markType ) 00688 { 00689 QPixmap *px_mark (m_doc->markPixmap( markType )); 00690 00691 if (px_mark) 00692 { 00693 // center the mark pixmap 00694 int x_px = (iconPaneWidth - px_mark->width()) / 2; 00695 if (x_px < 0) 00696 x_px = 0; 00697 00698 int y_px = (h - px_mark->height()) / 2; 00699 if (y_px < 0) 00700 y_px = 0; 00701 00702 p.drawPixmap( lnX+x_px, y+y_px, *px_mark); 00703 } 00704 } 00705 } 00706 } 00707 } 00708 00709 lnX += iconPaneWidth + 1; 00710 } 00711 00712 // line number 00713 if( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) 00714 { 00715 lnX +=2; 00716 00717 if (realLine > -1) 00718 if (m_viewInternal->lineRanges[z].startCol == 0) { 00719 if (m_lineNumbersOn) 00720 p.drawText( lnX + 1, y, lnWidth-4, h, Qt::AlignRight|Qt::AlignVCenter, QString("%1").arg( realLine + 1 ) ); 00721 } else if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) { 00722 p.drawPixmap(lnX + lnWidth - m_arrow.width() - 4, y, m_arrow); 00723 } 00724 00725 lnX += lnWidth; 00726 } 00727 00728 // folding markers 00729 if( m_foldingMarkersOn ) 00730 { 00731 if( realLine > -1 ) 00732 { 00733 KateLineInfo info; 00734 m_doc->lineInfo(&info,realLine); 00735 00736 if (!info.topLevel) 00737 { 00738 if (info.startsVisibleBlock && (m_viewInternal->lineRanges[z].startCol == 0)) 00739 { 00740 if (oldInfo.topLevel) 00741 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1); 00742 else 00743 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 00744 00745 p.drawPixmap(lnX+3,y+m_px,minus_px); 00746 } 00747 else if (info.startsInVisibleBlock) 00748 { 00749 if (m_viewInternal->lineRanges[z].startCol == 0) 00750 { 00751 if (oldInfo.topLevel) 00752 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1); 00753 else 00754 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 00755 00756 p.drawPixmap(lnX+3,y+m_px,plus_px); 00757 } 00758 else 00759 { 00760 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 00761 } 00762 00763 if (!m_viewInternal->lineRanges[z].wrap) 00764 p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1); 00765 } 00766 else 00767 { 00768 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 00769 00770 if (info.endsBlock && !m_viewInternal->lineRanges[z].wrap) 00771 p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1); 00772 } 00773 } 00774 00775 oldInfo = info; 00776 } 00777 00778 lnX += iconPaneWidth; 00779 } 00780 } 00781 } 00782 00783 KateIconBorder::BorderArea KateIconBorder::positionToArea( const QPoint& p ) const 00784 { 00785 int x = 0; 00786 if( m_iconBorderOn ) { 00787 x += iconPaneWidth; 00788 if( p.x() <= x ) 00789 return IconBorder; 00790 } 00791 if( m_lineNumbersOn || m_dynWrapIndicators ) { 00792 x += lineNumberWidth(); 00793 if( p.x() <= x ) 00794 return LineNumbers; 00795 } 00796 if( m_foldingMarkersOn ) { 00797 x += iconPaneWidth; 00798 if( p.x() <= x ) 00799 return FoldingMarkers; 00800 } 00801 return None; 00802 } 00803 00804 void KateIconBorder::mousePressEvent( QMouseEvent* e ) 00805 { 00806 m_lastClickedLine = m_viewInternal->yToKateLineRange(e->y()).line; 00807 00808 if ( positionToArea( e->pos() ) != IconBorder ) 00809 { 00810 QMouseEvent forward( QEvent::MouseButtonPress, 00811 QPoint( 0, e->y() ), e->button(), e->state() ); 00812 m_viewInternal->mousePressEvent( &forward ); 00813 } 00814 e->accept(); 00815 } 00816 00817 void KateIconBorder::mouseMoveEvent( QMouseEvent* e ) 00818 { 00819 if ( positionToArea( e->pos() ) != IconBorder ) 00820 { 00821 QMouseEvent forward( QEvent::MouseMove, 00822 QPoint( 0, e->y() ), e->button(), e->state() ); 00823 m_viewInternal->mouseMoveEvent( &forward ); 00824 } 00825 } 00826 00827 void KateIconBorder::mouseReleaseEvent( QMouseEvent* e ) 00828 { 00829 uint cursorOnLine = m_viewInternal->yToKateLineRange(e->y()).line; 00830 00831 if (cursorOnLine == m_lastClickedLine && 00832 cursorOnLine <= m_doc->lastLine() ) 00833 { 00834 BorderArea area = positionToArea( e->pos() ); 00835 if( area == IconBorder) { 00836 if (e->button() == LeftButton) { 00837 if( m_doc->editableMarks() & KateViewConfig::global()->defaultMarkType() ) { 00838 if( m_doc->mark( cursorOnLine ) & KateViewConfig::global()->defaultMarkType() ) 00839 m_doc->removeMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() ); 00840 else 00841 m_doc->addMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() ); 00842 } else { 00843 showMarkMenu( cursorOnLine, QCursor::pos() ); 00844 } 00845 } 00846 else 00847 if (e->button() == RightButton) { 00848 showMarkMenu( cursorOnLine, QCursor::pos() ); 00849 } 00850 } 00851 00852 if ( area == FoldingMarkers) { 00853 KateLineInfo info; 00854 m_doc->lineInfo(&info,cursorOnLine); 00855 if ((info.startsVisibleBlock) || (info.startsInVisibleBlock)) { 00856 emit toggleRegionVisibility(cursorOnLine); 00857 } 00858 } 00859 } 00860 00861 QMouseEvent forward( QEvent::MouseButtonRelease, 00862 QPoint( 0, e->y() ), e->button(), e->state() ); 00863 m_viewInternal->mouseReleaseEvent( &forward ); 00864 } 00865 00866 void KateIconBorder::mouseDoubleClickEvent( QMouseEvent* e ) 00867 { 00868 QMouseEvent forward( QEvent::MouseButtonDblClick, 00869 QPoint( 0, e->y() ), e->button(), e->state() ); 00870 m_viewInternal->mouseDoubleClickEvent( &forward ); 00871 } 00872 00873 void KateIconBorder::showMarkMenu( uint line, const QPoint& pos ) 00874 { 00875 QPopupMenu markMenu; 00876 QPopupMenu selectDefaultMark; 00877 00878 typedef QValueVector<int> MarkTypeVector; 00879 MarkTypeVector vec( 33 ); 00880 int i=1; 00881 00882 for( uint bit = 0; bit < 32; bit++ ) { 00883 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit); 00884 if( !(m_doc->editableMarks() & markType) ) 00885 continue; 00886 00887 if( !m_doc->markDescription( markType ).isEmpty() ) { 00888 markMenu.insertItem( m_doc->markDescription( markType ), i ); 00889 selectDefaultMark.insertItem( m_doc->markDescription( markType ), i+100); 00890 } else { 00891 markMenu.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i ); 00892 selectDefaultMark.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i+100); 00893 } 00894 00895 if( m_doc->mark( line ) & markType ) 00896 markMenu.setItemChecked( i, true ); 00897 00898 if( markType & KateViewConfig::global()->defaultMarkType() ) 00899 selectDefaultMark.setItemChecked( i+100, true ); 00900 00901 vec[i++] = markType; 00902 } 00903 00904 if( markMenu.count() == 0 ) 00905 return; 00906 00907 if( markMenu.count() > 1 ) 00908 markMenu.insertItem( i18n("Set Default Mark Type" ), &selectDefaultMark); 00909 00910 int result = markMenu.exec( pos ); 00911 if( result <= 0 ) 00912 return; 00913 00914 if ( result > 100) 00915 { 00916 KateViewConfig::global()->setDefaultMarkType (vec[result-100]); 00917 // flush config, otherwise it isn't nessecarily done 00918 KConfig *config = kapp->config(); 00919 config->setGroup("Kate View Defaults"); 00920 KateViewConfig::global()->writeConfig( config ); 00921 } 00922 else 00923 { 00924 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes) vec[result]; 00925 if( m_doc->mark( line ) & markType ) { 00926 m_doc->removeMark( line, markType ); 00927 } else { 00928 m_doc->addMark( line, markType ); 00929 } 00930 } 00931 } 00932 //END KateIconBorder 00933 00934 KateViewEncodingAction::KateViewEncodingAction(KateDocument *_doc, KateView *_view, const QString& text, QObject* parent, const char* name) 00935 : KActionMenu (text, parent, name), doc(_doc), view (_view) 00936 { 00937 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow())); 00938 } 00939 00940 void KateViewEncodingAction::slotAboutToShow() 00941 { 00942 QStringList modes (KGlobal::charsets()->descriptiveEncodingNames()); 00943 00944 popupMenu()->clear (); 00945 for (uint z=0; z<modes.size(); ++z) 00946 { 00947 popupMenu()->insertItem ( modes[z], this, SLOT(setMode(int)), 0, z); 00948 00949 bool found = false; 00950 QTextCodec *codecForEnc = KGlobal::charsets()->codecForName(KGlobal::charsets()->encodingForName(modes[z]), found); 00951 00952 if (found && codecForEnc) 00953 { 00954 if (codecForEnc->name() == doc->config()->codec()->name()) 00955 popupMenu()->setItemChecked (z, true); 00956 } 00957 } 00958 } 00959 00960 void KateViewEncodingAction::setMode (int mode) 00961 { 00962 QStringList modes (KGlobal::charsets()->descriptiveEncodingNames()); 00963 doc->setEncoding( KGlobal::charsets()->encodingForName( modes[mode] ) ); 00964 view->reloadFile(); 00965 } 00966 00967 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:40:03 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003