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 Fri Apr 22 16:09:22 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003