• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Kate

kateviewhelpers.cpp

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

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal