# kate Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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;

This file is part of the documentation for kate Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:36:39 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003