• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • 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) 2007 Mirko Stocker <me@misto.ch>
00003    Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
00004    Copyright (C) 2001 Anders Lund <anders@alweb.dk>
00005    Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License version 2 as published by the Free Software Foundation.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "kateviewhelpers.h"
00023 #include "kateviewhelpers.moc"
00024 
00025 #include "katecmd.h"
00026 #include <ktexteditor/attribute.h>
00027 #include <ktexteditor/annotationinterface.h>
00028 #include <ktexteditor/rangefeedback.h>
00029 #include "katecodefolding.h"
00030 #include "kateconfig.h"
00031 #include "katedocument.h"
00032 #include "katerenderer.h"
00033 #include "kateview.h"
00034 #include "kateviewinternal.h"
00035 #include "katelayoutcache.h"
00036 #include "katetextlayout.h"
00037 #include "katesmartrange.h"
00038 
00039 #include <kapplication.h>
00040 #include <kglobalsettings.h>
00041 #include <klocale.h>
00042 #include <knotification.h>
00043 #include <kglobal.h>
00044 #include <kmenu.h>
00045 #include <kiconloader.h>
00046 #include <kconfiggroup.h>
00047 
00048 #include <QtGui/QCursor>
00049 #include <QtGui/QPainter>
00050 #include <QtGui/QStyle>
00051 #include <QtCore/QTimer>
00052 #include <QtCore/QRegExp>
00053 #include <QtCore/QTextCodec>
00054 #include <QtGui/QKeyEvent>
00055 #include <QtGui/QPainterPath>
00056 #include <QtGui/QStyleOption>
00057 #include <QtGui/QPalette>
00058 #include <QtGui/QPen>
00059 #include <QtGui/QBoxLayout>
00060 #include <QtGui/QToolButton>
00061 #include <QtGui/QToolTip>
00062 #include <QtGui/QAction>
00063 
00064 #include <math.h>
00065 
00066 #include <kdebug.h>
00067 
00068 #include <QtGui/QWhatsThis>
00069 
00070 //BEGIN KateScrollBar
00071 KateScrollBar::KateScrollBar (Qt::Orientation orientation, KateViewInternal* parent)
00072   : QScrollBar (orientation, parent->m_view)
00073   , m_middleMouseDown (false)
00074   , m_view(parent->m_view)
00075   , m_doc(parent->m_doc)
00076   , m_viewInternal(parent)
00077   , m_topMargin(0)
00078   , m_bottomMargin(0)
00079   , m_savVisibleLines(0)
00080   , m_showMarks(false)
00081 {
00082   connect(this, SIGNAL(valueChanged(int)), this, SLOT(sliderMaybeMoved(int)));
00083   connect(m_doc, SIGNAL(marksChanged(KTextEditor::Document*)), this, SLOT(marksChanged()));
00084 
00085   styleChange(*style());
00086 }
00087 
00088 void KateScrollBar::mousePressEvent(QMouseEvent* e)
00089 {
00090   if (e->button() == Qt::MidButton)
00091     m_middleMouseDown = true;
00092 
00093   QScrollBar::mousePressEvent(e);
00094 
00095   redrawMarks();
00096 }
00097 
00098 void KateScrollBar::mouseReleaseEvent(QMouseEvent* e)
00099 {
00100   QScrollBar::mouseReleaseEvent(e);
00101 
00102   m_middleMouseDown = false;
00103 
00104   redrawMarks();
00105 }
00106 
00107 void KateScrollBar::mouseMoveEvent(QMouseEvent* e)
00108 {
00109   QScrollBar::mouseMoveEvent(e);
00110 
00111   if (e->buttons() | Qt::LeftButton)
00112     redrawMarks();
00113 }
00114 
00115 void KateScrollBar::paintEvent(QPaintEvent *e)
00116 {
00117   QScrollBar::paintEvent(e);
00118 
00119   QPainter painter(this);
00120 
00121   QStyleOptionSlider opt;
00122   opt.init(this);
00123   opt.subControls = QStyle::SC_None;
00124   opt.activeSubControls = QStyle::SC_None;
00125   opt.orientation = orientation();
00126   opt.minimum = minimum();
00127   opt.maximum = maximum();
00128   opt.sliderPosition = sliderPosition();
00129   opt.sliderValue = value();
00130   opt.singleStep = singleStep();
00131   opt.pageStep = pageStep();
00132 
00133   QRect rect = style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSlider, this);
00134 
00135   QHashIterator<int, QColor> it = m_lines;
00136   while (it.hasNext())
00137   {
00138     it.next();
00139     if (it.key() < rect.top() || it.key() > rect.bottom())
00140     {
00141       painter.setPen(it.value());
00142       painter.drawLine(0, it.key(), width(), it.key());
00143     }
00144   }
00145 }
00146 
00147 void KateScrollBar::resizeEvent(QResizeEvent *e)
00148 {
00149   QScrollBar::resizeEvent(e);
00150   recomputeMarksPositions();
00151 }
00152 
00153 void KateScrollBar::styleChange(QStyle &s)
00154 {
00155   QScrollBar::styleChange(s);
00156 
00157   // Calculate height of buttons
00158   QStyleOptionSlider opt;
00159   opt.init(this);
00160   opt.subControls = QStyle::SC_None;
00161   opt.activeSubControls = QStyle::SC_None;
00162   opt.orientation = this->orientation();
00163   opt.minimum = minimum();
00164   opt.maximum = maximum();
00165   opt.sliderPosition = sliderPosition();
00166   opt.sliderValue = value();
00167   opt.singleStep = singleStep();
00168   opt.pageStep = pageStep();
00169 
00170   m_topMargin = style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSubLine, this).height() + 2;
00171   m_bottomMargin = m_topMargin + style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarAddLine, this).height() + 1;
00172 
00173   recomputeMarksPositions();
00174 }
00175 
00176 void KateScrollBar::sliderChange ( SliderChange change )
00177 {
00178   // call parents implementation
00179   QScrollBar::sliderChange (change);
00180 
00181   if (change == QAbstractSlider::SliderValueChange)
00182   {
00183     redrawMarks();
00184   }
00185   else if (change == QAbstractSlider::SliderRangeChange)
00186   {
00187     recomputeMarksPositions();
00188   }
00189 }
00190 
00191 void KateScrollBar::marksChanged()
00192 {
00193   recomputeMarksPositions();
00194 }
00195 
00196 void KateScrollBar::redrawMarks()
00197 {
00198   if (!m_showMarks)
00199     return;
00200 
00201   update();
00202 }
00203 
00204 void KateScrollBar::recomputeMarksPositions()
00205 {
00206   m_lines.clear();
00207   m_savVisibleLines = m_doc->visibleLines();
00208 
00209   int realHeight = frameGeometry().height() - m_topMargin - m_bottomMargin;
00210 
00211   const QHash<int, KTextEditor::Mark*> &marks = m_doc->marks();
00212   KateCodeFoldingTree *tree = m_doc->foldingTree();
00213 
00214   for (QHash<int, KTextEditor::Mark*>::const_iterator i = marks.constBegin(); i != marks.constEnd(); ++i)
00215   {
00216     KTextEditor::Mark *mark = i.value();
00217 
00218     uint line = mark->line;
00219 
00220     if (tree)
00221     {
00222       KateCodeFoldingNode *node = tree->findNodeForLine(line);
00223 
00224       while (node)
00225       {
00226         if (!node->isVisible())
00227           line = tree->getStartLine(node);
00228         node = node->getParentNode();
00229       }
00230     }
00231 
00232     line = m_doc->getVirtualLine(line);
00233 
00234     double d = (double)line / (m_savVisibleLines - 1);
00235     m_lines.insert(m_topMargin + (int)(d * realHeight),
00236                    QColor(KateRendererConfig::global()->lineMarkerColor((KTextEditor::MarkInterface::MarkTypes)mark->type)));
00237   }
00238 
00239   // with Qt4 we don't have the luxury of painting outside a paint event
00240   // and a paint event wipes the widget... so just update
00241   update();
00242 }
00243 
00244 void KateScrollBar::sliderMaybeMoved(int value)
00245 {
00246   if (m_middleMouseDown) {
00247     // we only need to emit this signal once, as for the following slider
00248     // movements the signal sliderMoved() is already emitted.
00249     // Thus, set m_middleMouseDown to false right away.
00250     m_middleMouseDown = false;
00251     emit sliderMMBMoved(value);
00252   }
00253 }
00254 //END
00255 
00256 
00257 //BEGIN KateCmdLineEditFlagCompletion
00262 class KateCmdLineEditFlagCompletion : public KCompletion
00263 {
00264   public:
00265     KateCmdLineEditFlagCompletion() {;}
00266 
00267     QString makeCompletion( const QString & /*s*/ )
00268     {
00269       return QString();
00270     }
00271 
00272 };
00273 //END KateCmdLineEditFlagCompletion
00274 
00275 //BEGIN KateCmdLineEdit
00276 KateCmdLine::KateCmdLine (KateView *view, KateViewBar *viewBar)
00277     : KateViewBarWidget (viewBar)
00278 {
00279     QVBoxLayout *topLayout = new QVBoxLayout ();
00280     centralWidget()->setLayout(topLayout);
00281     topLayout->setMargin(0);
00282     m_lineEdit = new KateCmdLineEdit (this, view);
00283     topLayout->addWidget (m_lineEdit);
00284 
00285     setFocusProxy (m_lineEdit);
00286 }
00287 
00288 KateCmdLine::~KateCmdLine()
00289 {
00290 }
00291 
00292 KateCmdLineEdit::KateCmdLineEdit (KateCmdLine *bar, KateView *view)
00293   : KLineEdit ()
00294   , m_view (view)
00295   , m_bar (bar)
00296   , m_msgMode (false)
00297   , m_histpos( 0 )
00298   , m_cmdend( 0 )
00299   , m_command( 0L )
00300   , m_oldCompletionObject( 0L )
00301 {
00302   connect (this, SIGNAL(returnPressed(const QString &)),
00303            this, SLOT(slotReturnPressed(const QString &)));
00304 
00305   completionObject()->insertItems (KateCmd::self()->commandList());
00306   setAutoDeleteCompletionObject( false );
00307 }
00308 
00309 
00310 QString KateCmdLineEdit::helptext( const QPoint & ) const
00311     {
00312       QString beg = "<qt background=\"white\"><div><table width=\"100%\"><tr><td bgcolor=\"brown\"><font color=\"white\"><b>Help: <big>";
00313       QString mid = "</big></b></font></td></tr><tr><td>";
00314       QString end = "</td></tr></table></div><qt>";
00315 
00316       QString t = text();
00317       QRegExp re( "\\s*help\\s+(.*)" );
00318       if ( re.indexIn( t ) > -1 )
00319       {
00320         QString s;
00321         // get help for command
00322         QString name = re.cap( 1 );
00323         if ( name == "list" )
00324         {
00325           return beg + i18n("Available Commands") + mid
00326               + KateCmd::self()->commandList().join(" ")
00327               + i18n("<p>For help on individual commands, do <code>'help &lt;command&gt;'</code></p>")
00328               + end;
00329         }
00330         else if ( ! name.isEmpty() )
00331         {
00332           KTextEditor::Command *cmd = KateCmd::self()->queryCommand( name );
00333           if ( cmd )
00334           {
00335             if ( cmd->help( (KTextEditor::View*)parentWidget(), name, s ) )
00336               return beg + name + mid + s + end;
00337             else
00338               return beg + name + mid + i18n("No help for '%1'",  name ) + end;
00339           }
00340           else
00341             return beg + mid + i18n("No such command <b>%1</b>", name) + end;
00342         }
00343       }
00344 
00345       return beg + mid + i18n(
00346           "<p>This is the Katepart <b>command line</b>.<br />"
00347           "Syntax: <code><b>command [ arguments ]</b></code><br />"
00348           "For a list of available commands, enter <code><b>help list</b></code><br />"
00349           "For help for individual commands, enter <code><b>help &lt;command&gt;</b></code></p>")
00350           + end;
00351     }
00352 
00353 
00354 
00355 bool KateCmdLineEdit::event(QEvent *e) {
00356     if (e->type()==QEvent::WhatsThis)
00357         setWhatsThis(helptext(QPoint()));
00358     return KLineEdit::event(e);
00359 }
00360 
00361 void KateCmdLineEdit::slotReturnPressed ( const QString& text )
00362 {
00363   if (text.isEmpty()) return;
00364   // silently ignore leading space
00365   uint n = 0;
00366   const uint textlen=text.length();
00367   while( (n<textlen) &&text[n].isSpace() )
00368     n++;
00369 
00370   if (n>=textlen) return;
00371 
00372   QString cmd = text.mid( n );
00373 
00374   // Built in help: if the command starts with "help", [try to] show some help
00375   if ( cmd.startsWith( "help" ) )
00376   {
00377     QWhatsThis::showText(mapToGlobal(QPoint(0,0)), helptext( QPoint() ) );
00378     clear();
00379     KateCmd::self()->appendHistory( cmd );
00380     m_histpos = KateCmd::self()->historyLength();
00381     m_oldText = QString ();
00382     return;
00383   }
00384 
00385   if (cmd.length () > 0)
00386   {
00387     KTextEditor::Command *p = KateCmd::self()->queryCommand (cmd);
00388 
00389     m_oldText = cmd;
00390     m_msgMode = true;
00391 
00392     if (p)
00393     {
00394       QString msg;
00395 
00396       if (p->exec (m_view, cmd, msg))
00397       {
00398         KateCmd::self()->appendHistory( cmd );
00399         m_histpos = KateCmd::self()->historyLength();
00400         m_oldText = QString ();
00401 
00402         if (msg.length() > 0)
00403           setText (i18n ("Success: ") + msg);
00404         else
00405           setText (i18n ("Success"));
00406       }
00407       else
00408       {
00409         if (msg.length() > 0)
00410           setText (i18n ("Error: ") + msg);
00411         else
00412           setText (i18n ("Command \"%1\" failed.",  cmd));
00413         KNotification::beep();
00414       }
00415     }
00416     else
00417     {
00418       setText (i18n ("No such command: \"%1\"",  cmd));
00419       KNotification::beep();
00420     }
00421   }
00422 
00423   // clean up
00424   if ( m_oldCompletionObject )
00425   {
00426     KCompletion *c = completionObject();
00427     setCompletionObject( m_oldCompletionObject );
00428     m_oldCompletionObject = 0;
00429     delete c;
00430     c = 0;
00431   }
00432   m_command = 0;
00433   m_cmdend = 0;
00434 
00435   m_view->setFocus ();
00436   QTimer::singleShot( 4000, this, SLOT(hideBar()) );
00437 }
00438 
00439 void KateCmdLineEdit::hideBar () // unless i have focus ;)
00440 {
00441   if ( ! hasFocus() ) {
00442      m_bar->hideBar ();
00443   }
00444 }
00445 
00446 void KateCmdLineEdit::focusInEvent ( QFocusEvent *ev )
00447 {
00448   if (m_msgMode)
00449   {
00450     m_msgMode = false;
00451     setText (m_oldText);
00452     selectAll();
00453   }
00454 
00455   KLineEdit::focusInEvent (ev);
00456 }
00457 
00458 void KateCmdLineEdit::keyPressEvent( QKeyEvent *ev )
00459 {
00460   if (ev->key() == Qt::Key_Escape)
00461   {
00462     m_view->setFocus ();
00463     hideBar();
00464   }
00465   else if ( ev->key() == Qt::Key_Up )
00466     fromHistory( true );
00467   else if ( ev->key() == Qt::Key_Down )
00468     fromHistory( false );
00469 
00470   uint cursorpos = cursorPosition();
00471   KLineEdit::keyPressEvent (ev);
00472 
00473   // during typing, let us see if we have a valid command
00474   if ( ! m_cmdend || cursorpos <= m_cmdend  )
00475   {
00476     QChar c;
00477     if ( ! ev->text().isEmpty() )
00478       c = ev->text()[0];
00479 
00480     if ( ! m_cmdend && ! c.isNull() ) // we have no command, so lets see if we got one
00481     {
00482       if ( ! c.isLetterOrNumber() && c != '-' && c != '_' )
00483       {
00484         m_command = KateCmd::self()->queryCommand( text().trimmed() );
00485         if ( m_command )
00486         {
00487           //kDebug(13025)<<"keypress in commandline: We have a command! "<<m_command<<". text is '"<<text()<<"'";
00488           // if the typed character is ":",
00489           // we try if the command has flag completions
00490           m_cmdend = cursorpos;
00491           //kDebug(13025)<<"keypress in commandline: Set m_cmdend to "<<m_cmdend;
00492         }
00493         else
00494           m_cmdend = 0;
00495       }
00496     }
00497     else // since cursor is inside the command name, we reconsider it
00498     {
00499       kDebug(13025)<<"keypress in commandline: \\W -- text is "<<text();
00500       m_command = KateCmd::self()->queryCommand( text().trimmed() );
00501       if ( m_command )
00502       {
00503         //kDebug(13025)<<"keypress in commandline: We have a command! "<<m_command;
00504         QString t = text();
00505         m_cmdend = 0;
00506         bool b = false;
00507         for ( ; (int)m_cmdend < t.length(); m_cmdend++ )
00508         {
00509           if ( t[m_cmdend].isLetter() )
00510             b = true;
00511           if ( b && ( ! t[m_cmdend].isLetterOrNumber() && t[m_cmdend] != '-' && t[m_cmdend] != '_' ) )
00512             break;
00513         }
00514 
00515         if ( c == ':' && cursorpos == m_cmdend )
00516         {
00517           // check if this command wants to complete flags
00518           //kDebug(13025)<<"keypress in commandline: Checking if flag completion is desired!";
00519         }
00520       }
00521       else
00522       {
00523         // clean up if needed
00524         if ( m_oldCompletionObject )
00525         {
00526           KCompletion *c = completionObject();
00527           setCompletionObject( m_oldCompletionObject );
00528           m_oldCompletionObject = 0;
00529           delete c;
00530           c = 0;
00531         }
00532 
00533         m_cmdend = 0;
00534       }
00535     }
00536 
00537     // if we got a command, check if it wants to do semething.
00538     if ( m_command )
00539     {
00540       //kDebug(13025)<<"Checking for CommandExtension..";
00541       KTextEditor::CommandExtension *ce = dynamic_cast<KTextEditor::CommandExtension*>(m_command);
00542       if ( ce )
00543       {
00544         KCompletion *cmpl = ce->completionObject( m_view, text().left( m_cmdend ).trimmed() );
00545         if ( cmpl )
00546         {
00547         // save the old completion object and use what the command provides
00548         // instead. We also need to prepend the current command name + flag string
00549         // when completion is done
00550           //kDebug(13025)<<"keypress in commandline: Setting completion object!";
00551           if ( ! m_oldCompletionObject )
00552             m_oldCompletionObject = completionObject();
00553 
00554           setCompletionObject( cmpl );
00555         }
00556       }
00557     }
00558   }
00559   else if ( m_command )// check if we should call the commands processText()
00560   {
00561     KTextEditor::CommandExtension *ce = dynamic_cast<KTextEditor::CommandExtension*>( m_command );
00562     if ( ce && ce->wantsToProcessText( text().left( m_cmdend ).trimmed() )
00563          && ! ( ev->text().isNull() || ev->text().isEmpty() ) )
00564       ce->processText( m_view, text() );
00565   }
00566 }
00567 
00568 void KateCmdLineEdit::fromHistory( bool up )
00569 {
00570   if ( ! KateCmd::self()->historyLength() )
00571     return;
00572 
00573   QString s;
00574 
00575   if ( up )
00576   {
00577     if ( m_histpos > 0 )
00578     {
00579       m_histpos--;
00580       s = KateCmd::self()->fromHistory( m_histpos );
00581     }
00582   }
00583   else
00584   {
00585     if ( m_histpos < ( KateCmd::self()->historyLength() - 1 ) )
00586     {
00587       m_histpos++;
00588       s = KateCmd::self()->fromHistory( m_histpos );
00589     }
00590     else
00591     {
00592       m_histpos = KateCmd::self()->historyLength();
00593       setText( m_oldText );
00594     }
00595   }
00596   if ( ! s.isEmpty() )
00597   {
00598     // Select the argument part of the command, so that it is easy to overwrite
00599     setText( s );
00600     static QRegExp reCmd = QRegExp(".*[\\w\\-]+(?:[^a-zA-Z0-9_-]|:\\w+)(.*)");
00601     if ( reCmd.indexIn( text() ) == 0 )
00602       setSelection( text().length() - reCmd.cap(1).length(), reCmd.cap(1).length() );
00603   }
00604 }
00605 //END KateCmdLineEdit
00606 
00607 //BEGIN KateIconBorder
00608 using namespace KTextEditor;
00609 
00610 const int halfIPW = 8;
00611 
00612 KateIconBorder::KateIconBorder ( KateViewInternal* internalView, QWidget *parent )
00613   : QWidget(parent)
00614   , m_view( internalView->m_view )
00615   , m_doc( internalView->m_doc )
00616   , m_viewInternal( internalView )
00617   , m_iconBorderOn( false )
00618   , m_lineNumbersOn( false )
00619   , m_foldingMarkersOn( false )
00620   , m_dynWrapIndicatorsOn( false )
00621   , m_annotationBorderOn( false )
00622   , m_dynWrapIndicators( 0 )
00623   , m_cachedLNWidth( 0 )
00624   , m_maxCharWidth( 0 )
00625   , iconPaneWidth (16)
00626   , m_annotationBorderWidth (6)
00627   , m_foldingRange(0)
00628   , m_lastBlockLine(-1)
00629 {
00630 
00631         for (int i=0;i<MAXFOLDINGCOLORS;i++) {
00632           int r,g,b;
00633   /*
00634           if (info.depth<16) {
00635             r=0xff;
00636             g=0xff;
00637             b=0xff-0x10*info.depth;
00638           } else if (info.depth<32) {
00639             r=0xff-0x10*(info.depth-16); g=0xff;b=0;
00640           } else if (info.depth<48) {
00641             //r=0;g=0xff;b=0x10*(info.depth-32);
00642             r=0;g=0xff-0x10*(info.depth-32);b=0;
00643           } else {
00644             //r=0;g=0xff;b=0xff;
00645             r=0;g=0;b=0;
00646           }
00647   */
00648           if (i==0) {
00649             r=0xff;
00650             g=0xff;
00651             b=0xff;
00652           } else
00653           if (i<3) {
00654             r=0xff;
00655             g=0xff;
00656             b=0xff-0x40-0x40*i;
00657           } else if (i<7) {
00658             r=0xff-0x40*(i-3); g=0xff;b=0;
00659           } else if (i<15) {
00660             //r=0;g=0xff;b=0x10*(info.depth-32);
00661             //r=0;g=0xff-0x40*(i-7);b=0;    // 0x40 creates negative values!
00662             r=0;g=0xff-0x10*(i-7);b=0;
00663           } else {
00664             //r=0;g=0xff;b=0xff;
00665             r=0;g=0;b=0;
00666           }
00667           m_foldingColors[i]=QBrush(QColor(r,g,b,0x88),Qt::SolidPattern /*Qt::Dense4Pattern*/);
00668           m_foldingColorsSolid[i]=QBrush(QColor(r,g,b),Qt::SolidPattern);
00669        }
00670 
00671   setAttribute( Qt::WA_StaticContents );
00672   setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum );
00673   setMouseTracking(true);
00674   m_doc->setMarkDescription( MarkInterface::markType01, i18n("Bookmark") );
00675   m_doc->setMarkPixmap( MarkInterface::markType01, KIcon("bookmarks").pixmap(16, 16) );
00676 
00677   updateFont();
00678 }
00679 
00680 KateIconBorder::~KateIconBorder() {delete m_foldingRange;}
00681 
00682 void KateIconBorder::setIconBorderOn( bool enable )
00683 {
00684   if( enable == m_iconBorderOn )
00685     return;
00686 
00687   m_iconBorderOn = enable;
00688 
00689   updateGeometry();
00690 
00691   QTimer::singleShot( 0, this, SLOT(update()) );
00692 }
00693 
00694 void KateIconBorder::setAnnotationBorderOn( bool enable )
00695 {
00696   if( enable == m_annotationBorderOn )
00697     return;
00698 
00699   m_annotationBorderOn = enable;
00700 
00701   emit m_view->annotationBorderVisibilityChanged(m_view, enable);
00702 
00703   updateGeometry();
00704 }
00705 
00706 void KateIconBorder::removeAnnotationHovering()
00707 {
00708   // remove hovering if it's still there
00709   if (m_annotationBorderOn && !m_hoveredAnnotationText.isEmpty())
00710   {
00711     m_hoveredAnnotationText = QString();
00712     hideAnnotationTooltip();
00713     QTimer::singleShot( 0, this, SLOT(update()) );
00714   }
00715 }
00716 
00717 void KateIconBorder::setLineNumbersOn( bool enable )
00718 {
00719   if( enable == m_lineNumbersOn )
00720     return;
00721 
00722   m_lineNumbersOn = enable;
00723   m_dynWrapIndicatorsOn = (m_dynWrapIndicators == 1) ? enable : m_dynWrapIndicators;
00724 
00725   updateGeometry();
00726 
00727   QTimer::singleShot( 0, this, SLOT(update()) );
00728 }
00729 
00730 void KateIconBorder::setDynWrapIndicators( int state )
00731 {
00732   if (state == m_dynWrapIndicators )
00733     return;
00734 
00735   m_dynWrapIndicators = state;
00736   m_dynWrapIndicatorsOn = (state == 1) ? m_lineNumbersOn : state;
00737 
00738   updateGeometry ();
00739 
00740   QTimer::singleShot( 0, this, SLOT(update()) );
00741 }
00742 
00743 void KateIconBorder::setFoldingMarkersOn( bool enable )
00744 {
00745   if( enable == m_foldingMarkersOn )
00746     return;
00747 
00748   m_foldingMarkersOn = enable;
00749 
00750   updateGeometry();
00751 
00752   QTimer::singleShot( 0, this, SLOT(update()) );
00753 }
00754 
00755 QSize KateIconBorder::sizeHint() const
00756 {
00757   int w = 0;
00758 
00759   if (m_iconBorderOn)
00760     w += iconPaneWidth + 1;
00761 
00762   if (m_annotationBorderOn)
00763   {
00764     w += m_annotationBorderWidth + 1;
00765   }
00766 
00767   if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) {
00768     w += lineNumberWidth() + 1;
00769   }
00770 
00771   if (m_foldingMarkersOn)
00772     w += iconPaneWidth + 1;
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   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 = qMax(m_maxCharWidth, charWidth);
00790   }
00791 
00792   // the icon pane scales with the font...
00793   iconPaneWidth = fm.height();
00794 
00795   updateGeometry();
00796 
00797   QTimer::singleShot( 0, this, SLOT(update()) );
00798 }
00799 
00800 int KateIconBorder::lineNumberWidth() const
00801 {
00802   int width = m_lineNumbersOn ? ((int)log10((double)(m_view->doc()->lines())) + 1) * m_maxCharWidth + 4 : 0;
00803 
00804   if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
00805     // HACK: 16 == style().scrollBarExtent().width()
00806     width = qMax(16 + 4, width);
00807 
00808     if (m_cachedLNWidth != width || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) {
00809       int w = 16;// HACK: 16 == style().scrollBarExtent().width() style().scrollBarExtent().width();
00810       int h = m_view->renderer()->config()->fontMetrics().height();
00811 
00812       QSize newSize(w, h);
00813       if ((m_arrow.size() != newSize || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) && !newSize.isEmpty()) {
00814         m_arrow = QPixmap(newSize);
00815 
00816         QPainter p(&m_arrow);
00817         p.fillRect( 0, 0, w, h, m_view->renderer()->config()->iconBarColor() );
00818 
00819         h = m_view->renderer()->config()->fontMetrics().ascent();
00820 
00821         p.setPen(m_view->renderer()->config()->lineNumberColor());
00822 
00823         QPainterPath path;
00824         path.moveTo(w/2, h/2);
00825         path.lineTo(w/2, 0);
00826         path.lineTo(w/4, h/4);
00827         path.lineTo(0, 0);
00828         path.lineTo(0, h/2);
00829         path.lineTo(w/2, h-1);
00830         path.lineTo(w*3/4, h-1);
00831         path.lineTo(w-1, h*3/4);
00832         path.lineTo(w*3/4, h/2);
00833         path.lineTo(0, h/2);
00834         p.drawPath(path);
00835       }
00836     }
00837   }
00838 
00839   return width;
00840 }
00841 
00842 const QBrush& KateIconBorder::foldingColor(KateLineInfo *info,int realLine, bool solid) {
00843   int depth;
00844   if (info!=0) {
00845     depth=info->depth;
00846   } else {
00847     KateLineInfo tmp;
00848     m_doc->lineInfo(&tmp,realLine);
00849     depth=tmp.depth;
00850   }
00851 
00852   if (solid) {
00853     if (depth<MAXFOLDINGCOLORS)
00854       return m_foldingColorsSolid[depth];
00855     else
00856       return m_foldingColorsSolid[MAXFOLDINGCOLORS-1];
00857   } else {
00858     if (depth<MAXFOLDINGCOLORS)
00859       return m_foldingColors[depth];
00860     else
00861       return m_foldingColors[MAXFOLDINGCOLORS-1];
00862   }
00863 
00864 }
00865 
00866 void KateIconBorder::paintEvent(QPaintEvent* e)
00867 {
00868   paintBorder(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
00869 }
00870 
00871 static void paintTriangle (QPainter &painter, const QColor &baseColor, int xOffset, int yOffset, int width, int height, bool open)
00872 {
00873   painter.setRenderHint(QPainter::Antialiasing);
00874 
00875   qreal size = qMin (width, height);
00876 
00877   QColor c = baseColor.dark ();
00878 
00879   // just test if that worked, else use light..., black on black is evil...
00880   if (c == baseColor)
00881     c = baseColor.light ();
00882 
00883   QPen pen;
00884   pen.setJoinStyle (Qt::RoundJoin);
00885   pen.setColor (c);
00886   pen.setWidthF (1.5);
00887   painter.setPen ( pen );
00888 
00889   painter.setBrush ( c );
00890 
00891   // let some border, if possible
00892   size *= 0.6;
00893 
00894   qreal halfSize = size / 2;
00895   qreal halfSizeP = halfSize * 0.6;
00896   QPointF middle (xOffset + (qreal)width / 2, yOffset + (qreal)height / 2);
00897 
00898   if (open)
00899   {
00900     QPointF points[3] = { middle+QPointF(-halfSize, -halfSizeP), middle+QPointF(halfSize, -halfSizeP), middle+QPointF(0, halfSizeP) };
00901     painter.drawConvexPolygon(points, 3);
00902   }
00903   else
00904   {
00905     QPointF points[3] = { middle+QPointF(-halfSizeP, -halfSize), middle+QPointF(-halfSizeP, halfSize), middle+QPointF(halfSizeP, 0) };
00906     painter.drawConvexPolygon(points, 3);
00907   }
00908 
00909   painter.setRenderHint(QPainter::Antialiasing, false);
00910 }
00911 
00912 void KateIconBorder::paintBorder (int /*x*/, int y, int /*width*/, int height)
00913 {
00914   uint h = m_view->renderer()->config()->fontMetrics().height();
00915   uint startz = (y / h);
00916   uint endz = startz + 1 + (height / h);
00917   uint lineRangesSize = m_viewInternal->cache()->viewCacheLineCount();
00918 
00919   // center the folding boxes
00920   int m_px = (h - 11) / 2;
00921   if (m_px < 0)
00922     m_px = 0;
00923 
00924   int lnWidth( 0 );
00925   if ( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) // avoid calculating unless needed ;-)
00926   {
00927     lnWidth = lineNumberWidth();
00928     if ( lnWidth != m_cachedLNWidth || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor() )
00929     {
00930       // we went from n0 ->n9 lines or vice verca
00931       // this causes an extra updateGeometry() first time the line numbers
00932       // are displayed, but sizeHint() is supposed to be const so we can't set
00933       // the cached value there.
00934       m_cachedLNWidth = lnWidth;
00935       m_oldBackgroundColor = m_view->renderer()->config()->iconBarColor();
00936       updateGeometry();
00937       update ();
00938       return;
00939     }
00940   }
00941 
00942   int w( this->width() );                     // sane value/calc only once
00943 
00944   QPainter p ( this );
00945   p.setRenderHints (QPainter::TextAntialiasing);
00946   p.setFont ( m_view->renderer()->config()->font() ); // for line numbers
00947   // the line number color is for the line numbers, vertical separator lines
00948   // and for for the code folding lines.
00949   p.setPen ( m_view->renderer()->config()->lineNumberColor() );
00950   p.setBrush ( m_view->renderer()->config()->lineNumberColor() );
00951 
00952   KateLineInfo oldInfo;
00953   if (startz < lineRangesSize)
00954   {
00955     if ((m_viewInternal->cache()->viewLine(startz).line()-1) < 0)
00956       oldInfo.topLevel = true;
00957     else
00958       m_doc->lineInfo(&oldInfo,m_viewInternal->cache()->viewLine(startz).line()-1);
00959   }
00960 
00961   KTextEditor::AnnotationModel *model = m_view->annotationModel() ?
00962       m_view->annotationModel() : m_doc->annotationModel();
00963 
00964   for (uint z=startz; z <= endz; z++)
00965   {
00966     int y = h * z;
00967     int realLine = -1;
00968 
00969     if (z < lineRangesSize)
00970       realLine = m_viewInternal->cache()->viewLine(z).line();
00971 
00972     int lnX = 0;
00973 
00974     p.fillRect( 0, y, w-4, h, m_view->renderer()->config()->iconBarColor() );
00975     p.fillRect( w-4, y, 4, h, m_view->renderer()->config()->backgroundColor() );
00976 
00977     // icon pane
00978     if( m_iconBorderOn )
00979     {
00980       p.setPen ( m_view->renderer()->config()->lineNumberColor() );
00981       p.setBrush ( m_view->renderer()->config()->lineNumberColor() );
00982       p.drawLine(lnX+iconPaneWidth+1, y, lnX+iconPaneWidth+1, y+h);
00983 
00984       if( (realLine > -1) && (m_viewInternal->cache()->viewLine(z).startCol() == 0) )
00985       {
00986         uint mrk ( m_doc->mark( realLine ) ); // call only once
00987 
00988         if ( mrk )
00989         {
00990           for( uint bit = 0; bit < 32; bit++ )
00991           {
00992             MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
00993             if( mrk & markType )
00994             {
00995               QPixmap px_mark (m_doc->markPixmap( markType ));
00996 
00997               if (!px_mark.isNull())
00998               {
00999                 // center the mark pixmap
01000                 int x_px = (iconPaneWidth - px_mark.width()) / 2;
01001                 if (x_px < 0)
01002                   x_px = 0;
01003 
01004                 int y_px = (h - px_mark.height()) / 2;
01005                 if (y_px < 0)
01006                   y_px = 0;
01007 
01008                 p.drawPixmap( lnX+x_px, y+y_px, px_mark);
01009               }
01010             }
01011           }
01012         }
01013       }
01014 
01015       lnX += iconPaneWidth + 2;
01016     }
01017 
01018     // annotation information
01019     if( m_annotationBorderOn )
01020     {
01021       // Draw a border line between annotations and the line numbers
01022       p.setPen ( m_view->renderer()->config()->lineNumberColor() );
01023       p.setBrush ( m_view->renderer()->config()->lineNumberColor() );
01024 
01025       int borderWidth = m_annotationBorderWidth;
01026       p.drawLine(lnX+borderWidth+1, y, lnX+borderWidth+1, y+h);
01027 
01028       if( (realLine > -1) && model )
01029       {
01030         // Fetch data from the model
01031         QVariant text = model->data( realLine, Qt::DisplayRole );
01032         QVariant foreground = model->data( realLine, Qt::ForegroundRole );
01033         QVariant background = model->data( realLine, Qt::BackgroundRole );
01034         // Fill the background
01035         if( background.isValid() )
01036         {
01037           p.fillRect( lnX, y, borderWidth + 1, h, background.value<QBrush>() );
01038         }
01039         // Set the pen for drawing the foreground
01040         if( foreground.isValid() )
01041         {
01042           p.setBrush( foreground.value<QBrush>() );
01043         }
01044 
01045         // Draw a border around all adjacent entries that have the same text as the currently hovered one
01046         if( m_hoveredAnnotationText == text.toString() )
01047         {
01048           p.drawLine( lnX, y, lnX, y+h );
01049           p.drawLine( lnX+borderWidth, y, lnX+borderWidth, y+h );
01050 
01051           QVariant beforeText = model->data( realLine-1, Qt::DisplayRole );
01052           QVariant afterText = model->data( realLine+1, Qt::DisplayRole );
01053           if( (beforeText.isValid() && beforeText.canConvert<QString>()
01054               && text.isValid() && text.canConvert<QString>()
01055               && beforeText.toString() != text.toString() || realLine == 0)
01056               && m_viewInternal->cache()->viewLine(z).viewLine() == 0)
01057           {
01058             p.drawLine( lnX+1, y, lnX+borderWidth, y );
01059           }
01060 
01061           if( ((afterText.isValid() && afterText.canConvert<QString>()
01062               && text.isValid() && text.canConvert<QString>()
01063               && afterText.toString() != text.toString())
01064                 || realLine == m_view->doc()->lines() - 1)
01065               && m_viewInternal->cache()->viewLine(z).viewLine() == m_viewInternal->cache()->viewLineCount(realLine)-1)
01066           {
01067             p.drawLine( lnX+1, y+h-1, lnX+borderWidth, y+h-1 );
01068           }
01069         }
01070         if( foreground.isValid() )
01071         {
01072           QPen pen = p.pen();
01073           pen.setWidth( 1 );
01074           p.setPen( pen );
01075         }
01076 
01077         // Now draw the normal text
01078         if( text.isValid() && text.canConvert<QString>() && (m_viewInternal->cache()->viewLine(z).startCol() == 0)  )
01079         {
01080           p.drawText( lnX+3, y, borderWidth-3, h, Qt::AlignLeft|Qt::AlignVCenter, text.toString() );
01081         }
01082       }
01083 
01084       // adjust current X position and reset the pen and brush
01085       lnX += borderWidth + 2;
01086 
01087       p.setPen ( m_view->renderer()->config()->lineNumberColor() );
01088       p.setBrush ( m_view->renderer()->config()->lineNumberColor() );
01089     }
01090 
01091     // line number
01092     if( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) )
01093     {
01094       if (realLine > -1)
01095         if (m_viewInternal->cache()->viewLine(z).startCol() == 0) {
01096           if (m_lineNumbersOn)
01097             p.drawText( lnX, y, lnWidth-4, h, Qt::AlignRight|Qt::AlignVCenter, QString("%1").arg( realLine + 1 ) );
01098         } else if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) {
01099           p.drawPixmap(lnX + lnWidth - m_arrow.width() - 2, y, m_arrow);
01100         }
01101 
01102       lnX += lnWidth + 2;
01103     }
01104 
01105     // folding markers
01106     if( m_foldingMarkersOn )
01107     {
01108       if( realLine > -1 )
01109       {
01110         KateLineInfo info;
01111         m_doc->lineInfo(&info,realLine);
01112 
01113         QBrush brush (foldingColor(&info,realLine,true));
01114         p.fillRect(lnX, y, iconPaneWidth, h, brush);
01115 
01116         if (!info.topLevel)
01117         {
01118           if (info.startsVisibleBlock && (m_viewInternal->cache()->viewLine(z).startCol() == 0))
01119           {
01120             paintTriangle (p, brush.color(), lnX, y, iconPaneWidth, h, true);
01121           }
01122           else if (info.startsInVisibleBlock && m_viewInternal->cache()->viewLine(z).startCol() == 0)
01123           {
01124             paintTriangle (p, brush.color(), lnX, y, iconPaneWidth, h, false);
01125           }
01126           else
01127           {
01128            // p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1);
01129 
01130            // if (info.endsBlock && !m_viewInternal->cache()->viewLine(z).wrap())
01131             //  p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1);
01132           }
01133         }
01134 
01135         oldInfo = info;
01136       }
01137 
01138       lnX += iconPaneWidth + 2;
01139     }
01140   }
01141 }
01142 
01143 KateIconBorder::BorderArea KateIconBorder::positionToArea( const QPoint& p ) const
01144 {
01145   int x = 0;
01146   if( m_iconBorderOn ) {
01147     x += iconPaneWidth;
01148     if( p.x() <= x )
01149       return IconBorder;
01150   }
01151   if( this->m_annotationBorderOn ) {
01152     x += m_annotationBorderWidth;
01153     if( p.x() <= x )
01154       return AnnotationBorder;
01155   }
01156   if( m_lineNumbersOn || m_dynWrapIndicators ) {
01157     x += lineNumberWidth();
01158     if( p.x() <= x )
01159       return LineNumbers;
01160   }
01161   if( m_foldingMarkersOn ) {
01162     x += iconPaneWidth;
01163     if( p.x() <= x )
01164       return FoldingMarkers;
01165   }
01166   return None;
01167 }
01168 
01169 void KateIconBorder::mousePressEvent( QMouseEvent* e )
01170 {
01171   const KateTextLayout& t = m_viewInternal->yToKateTextLayout(e->y());
01172   if (t.isValid()) {
01173     m_lastClickedLine = t.line();
01174     if ( positionToArea( e->pos() ) != IconBorder && positionToArea( e->pos() ) != AnnotationBorder )
01175     {
01176       QMouseEvent forward( QEvent::MouseButtonPress,
01177         QPoint( 0, e->y() ), e->button(), e->buttons(),e->modifiers() );
01178       m_viewInternal->mousePressEvent( &forward );
01179     }
01180     return e->accept();
01181   }
01182 
01183   QWidget::mousePressEvent(e);
01184 }
01185 
01186 void KateIconBorder::showBlock(int line)
01187 {
01188   if (line == m_lastBlockLine) return;
01189   m_lastBlockLine = line;
01190 
01191   // get the new range, that should be highlighted
01192   KTextEditor::Range newRange = KTextEditor::Range::invalid();
01193   KateCodeFoldingTree *tree = m_doc->foldingTree();
01194   if (tree) {
01195     KateCodeFoldingNode *node = tree->findNodeForLine(line);
01196     KTextEditor::Cursor beg;
01197     KTextEditor::Cursor end;
01198     if (node != tree->rootNode () && node->getBegin(tree, &beg) && node->getEnd(tree, &end)) {
01199       newRange = KTextEditor::Range(beg, end);
01200     }
01201   }
01202 
01203   if (newRange.isValid() && m_foldingRange && *m_foldingRange == newRange) {
01204     // new range equals the old one, nothing to do.
01205     return;
01206   } else { // the ranges differ, delete the old, if it exists
01207     delete m_foldingRange;
01208     m_foldingRange = 0;
01209   }
01210 
01211   if (newRange.isValid()) {
01212     kDebug(13025) << "new folding hl-range:" << newRange;
01213     m_foldingRange = m_doc->newSmartRange(newRange);
01214     static_cast<KateSmartRange*>(m_foldingRange)->setInternal();
01215     KTextEditor::Attribute::Ptr attr(new KTextEditor::Attribute());
01216     attr->setBackground(foldingColor(0, line, false));
01217     m_foldingRange->setAttribute(attr);
01218     m_doc->addHighlightToView(m_view, m_foldingRange, false);
01219   }
01220 }
01221 
01222 void KateIconBorder::hideBlock() {
01223   m_lastBlockLine=-1;
01224   delete m_foldingRange;
01225   m_foldingRange = 0;
01226 }
01227 
01228 void KateIconBorder::leaveEvent(QEvent *event)
01229 {
01230   hideBlock();
01231   removeAnnotationHovering();
01232 
01233   QWidget::leaveEvent(event);
01234 }
01235 
01236 void KateIconBorder::mouseMoveEvent( QMouseEvent* e )
01237 {
01238   const KateTextLayout& t = m_viewInternal->yToKateTextLayout(e->y());
01239   if (t.isValid()) {
01240     if ( positionToArea( e->pos() ) == FoldingMarkers) showBlock(t.line());
01241     else hideBlock();
01242     if ( positionToArea( e->pos() ) == AnnotationBorder )
01243     {
01244       KTextEditor::AnnotationModel *model = m_view->annotationModel() ?
01245         m_view->annotationModel() : m_doc->annotationModel();
01246       if (model)
01247       {
01248         m_hoveredAnnotationText = model->data( t.line(), Qt::DisplayRole ).toString();
01249         showAnnotationTooltip( t.line(), e->globalPos() );
01250         QTimer::singleShot( 0, this, SLOT(update()) );
01251       }
01252     }
01253     else
01254     {
01255       m_hoveredAnnotationText = QString();
01256       hideAnnotationTooltip();
01257       QTimer::singleShot( 0, this, SLOT(update()) );
01258     }
01259     if ( positionToArea( e->pos() ) != IconBorder )
01260     {
01261       QMouseEvent forward( QEvent::MouseMove,
01262         QPoint( 0, e->y() ), e->button(), e->buttons(),e->modifiers() );
01263       m_viewInternal->mouseMoveEvent( &forward );
01264     }
01265   }
01266   else
01267   {
01268     // remove hovering if it's still there
01269     removeAnnotationHovering();
01270   }
01271 
01272   QWidget::mouseMoveEvent(e);
01273 }
01274 
01275 void KateIconBorder::mouseReleaseEvent( QMouseEvent* e )
01276 {
01277   int cursorOnLine = m_viewInternal->yToKateTextLayout(e->y()).line();
01278 
01279   if (cursorOnLine == m_lastClickedLine &&
01280       cursorOnLine <= m_doc->lastLine() )
01281   {
01282     BorderArea area = positionToArea( e->pos() );
01283     if( area == IconBorder) {
01284       if (e->button() == Qt::LeftButton) {
01285         if( m_doc->editableMarks() & KateViewConfig::global()->defaultMarkType() ) {
01286           if( m_doc->mark( cursorOnLine ) & KateViewConfig::global()->defaultMarkType() )
01287             m_doc->removeMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
01288           else
01289             m_doc->addMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() );
01290           } else {
01291             showMarkMenu( cursorOnLine, QCursor::pos() );
01292           }
01293         }
01294         else
01295         if (e->button() == Qt::RightButton) {
01296           showMarkMenu( cursorOnLine, QCursor::pos() );
01297         }
01298     }
01299 
01300     if ( area == FoldingMarkers) {
01301       KateLineInfo info;
01302       m_doc->lineInfo(&info,cursorOnLine);
01303       if ((info.startsVisibleBlock) || (info.startsInVisibleBlock)) {
01304         emit toggleRegionVisibility(cursorOnLine);
01305       }
01306     }
01307 
01308     if ( area == AnnotationBorder ) {
01309       if( e->button() == Qt::LeftButton && KGlobalSettings::singleClick() ) {
01310         emit m_view->annotationActivated( m_view, cursorOnLine );
01311       } else if ( e->button() == Qt::RightButton ) {
01312         showAnnotationMenu( cursorOnLine, e->globalPos() );
01313       }
01314     }
01315   }
01316 
01317   QMouseEvent forward( QEvent::MouseButtonRelease,
01318     QPoint( 0, e->y() ), e->button(), e->buttons(),e->modifiers() );
01319   m_viewInternal->mouseReleaseEvent( &forward );
01320 }
01321 
01322 void KateIconBorder::mouseDoubleClickEvent( QMouseEvent* e )
01323 {
01324   int cursorOnLine = m_viewInternal->yToKateTextLayout(e->y()).line();
01325 
01326   if (cursorOnLine == m_lastClickedLine &&
01327       cursorOnLine <= m_doc->lastLine() )
01328   {
01329     BorderArea area = positionToArea( e->pos() );
01330     if( area == AnnotationBorder && !KGlobalSettings::singleClick() ) {
01331       emit m_view->annotationActivated( m_view, cursorOnLine );
01332     }
01333   }
01334   QMouseEvent forward( QEvent::MouseButtonDblClick,
01335     QPoint( 0, e->y() ), e->button(), e->buttons(),e->modifiers() );
01336   m_viewInternal->mouseDoubleClickEvent( &forward );
01337 }
01338 
01339 void KateIconBorder::showMarkMenu( uint line, const QPoint& pos )
01340 {
01341   KMenu markMenu;
01342   KMenu selectDefaultMark;
01343 
01344   QVector<int> vec( 33 );
01345   int i=1;
01346 
01347   for( uint bit = 0; bit < 32; bit++ ) {
01348     MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit);
01349     if( !(m_doc->editableMarks() & markType) )
01350       continue;
01351 
01352     QAction *mA;
01353     QAction *dMA;
01354     if( !m_doc->markDescription( markType ).isEmpty() ) {
01355       mA=markMenu.addAction( m_doc->markDescription( markType ));
01356       dMA=selectDefaultMark.addAction( m_doc->markDescription( markType ));
01357     } else {
01358       mA=markMenu.addAction( i18n("Mark Type %1",  bit + 1 ));
01359       dMA=selectDefaultMark.addAction( i18n("Mark Type %1",  bit + 1 ));
01360     }
01361     mA->setData(i);
01362     mA->setCheckable(true);
01363     dMA->setData(i+100);
01364     dMA->setCheckable(true);
01365     if( m_doc->mark( line ) & markType )
01366       mA->setChecked(true );
01367 
01368     if( markType & KateViewConfig::global()->defaultMarkType() )
01369       dMA->setChecked(true );
01370 
01371     vec[i++] = markType;
01372   }
01373 
01374   if( markMenu.actions().count() == 0 )
01375     return;
01376 
01377   if( markMenu.actions().count() > 1 )
01378     markMenu.addAction( i18n("Set Default Mark Type" ))->setMenu(&selectDefaultMark);
01379 
01380   QAction *rA = markMenu.exec( pos );
01381   if( !rA )
01382     return;
01383   int result=rA->data().toInt();
01384   if ( result > 100)
01385   {
01386      KateViewConfig::global()->setDefaultMarkType (vec[result-100]);
01387      // flush config, otherwise it isn't nessecarily done
01388      KConfigGroup cg(KGlobal::config(), "Kate View Defaults");
01389      KateViewConfig::global()->writeConfig(cg);
01390   }
01391   else
01392   {
01393     MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes) vec[result];
01394     if( m_doc->mark( line ) & markType ) {
01395       m_doc->removeMark( line, markType );
01396     } else {
01397         m_doc->addMark( line, markType );
01398     }
01399   }
01400 }
01401 
01402 void KateIconBorder::showAnnotationTooltip( int line, const QPoint& pos )
01403 {
01404   KTextEditor::AnnotationModel *model = m_view->annotationModel() ?
01405     m_view->annotationModel() : m_doc->annotationModel();
01406 
01407   if( model )
01408   {
01409     QVariant data = model->data( line, Qt::ToolTipRole );
01410     QString tip = data.toString();
01411     if (!tip.isEmpty())
01412       QToolTip::showText( pos, data.toString(), this );
01413   }
01414 }
01415 
01416 
01417 int KateIconBorder::annotationLineWidth( int line )
01418 {
01419   KTextEditor::AnnotationModel *model = m_view->annotationModel() ?
01420     m_view->annotationModel() : m_doc->annotationModel();
01421 
01422   if( model )
01423   {
01424     QVariant data = model->data( line, Qt::DisplayRole );
01425     return data.toString().length() * m_maxCharWidth + 8;
01426   }
01427   return 8;
01428 }
01429 
01430 void KateIconBorder::updateAnnotationLine( int line )
01431 {
01432   if( annotationLineWidth(line) > m_annotationBorderWidth )
01433   {
01434     m_annotationBorderWidth = annotationLineWidth(line);
01435     updateGeometry();
01436 
01437     QTimer::singleShot( 0, this, SLOT(update()) );
01438   }
01439 }
01440 
01441 void KateIconBorder::showAnnotationMenu( int line, const QPoint& pos)
01442 {
01443   KMenu menu;
01444   QAction a("Disable Annotation Bar", &menu);
01445   menu.addAction(&a);
01446   emit m_view->annotationContextMenuAboutToShow( m_view, &menu, line  );
01447   if (menu.exec(pos) == &a)
01448     m_view->setAnnotationBorderVisible(false);
01449 }
01450 
01451 void KateIconBorder::hideAnnotationTooltip()
01452 {
01453   QToolTip::hideText();
01454 }
01455 
01456 void KateIconBorder::updateAnnotationBorderWidth( )
01457 {
01458   m_annotationBorderWidth = 6;
01459   KTextEditor::AnnotationModel *model = m_view->annotationModel() ?
01460     m_view->annotationModel() : m_doc->annotationModel();
01461 
01462   if( model ) {
01463     for( int i = 0; i < m_view->doc()->lines(); i++ ) {
01464       int curwidth = annotationLineWidth( i );
01465       if( curwidth > m_annotationBorderWidth )
01466         m_annotationBorderWidth = curwidth;
01467     }
01468   }
01469 
01470   updateGeometry();
01471 
01472   QTimer::singleShot( 0, this, SLOT(update()) );
01473 }
01474 
01475 
01476 
01477 void KateIconBorder::annotationModelChanged( KTextEditor::AnnotationModel * oldmodel, KTextEditor::AnnotationModel * newmodel )
01478 {
01479   if( oldmodel )
01480   {
01481     oldmodel->disconnect( this );
01482   }
01483   if( newmodel )
01484   {
01485     connect( newmodel, SIGNAL(reset()), this, SLOT(updateAnnotationBorderWidth()) );
01486     connect( newmodel, SIGNAL(lineChanged( int )), this, SLOT(updateAnnotationLine( int )) );
01487   }
01488   updateAnnotationBorderWidth();
01489 }
01490 
01491 //END KateIconBorder
01492 
01493 //BEGIN KateViewEncodingAction
01494 KateViewEncodingAction::KateViewEncodingAction(KateDocument *_doc, KateView *_view, const QString& text, QObject *parent)
01495        : KCodecAction(text, parent,true), doc(_doc), view (_view)
01496 {
01497   connect(this,SIGNAL(triggered(KEncodingDetector::AutoDetectScript)),this,SLOT(setScriptForEncodingAutoDetection(KEncodingDetector::AutoDetectScript)));
01498   connect(this,SIGNAL(triggered(const QString&)),this,SLOT(setEncoding(const QString&)));
01499   connect(menu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow()));
01500 }
01501 
01502 void KateViewEncodingAction::slotAboutToShow()
01503 {
01504   if (doc->scriptForEncodingAutoDetection()==KEncodingDetector::None)
01505   {
01506     if (!setCurrentCodec(doc->encoding()))
01507       kWarning() << "KateViewEncodingAction: cannot set current "<<doc->encoding();
01508   }
01509   else
01510     setCurrentAutoDetectScript(doc->scriptForEncodingAutoDetection());
01511 }
01512 
01513 void KateViewEncodingAction::setEncoding (const QString &e)
01514 {
01515   doc->setEncoding(e);
01516   //this is done in setEncoding()
01517   //doc->setScriptForEncodingAutoDetection(KEncodingDetector::None);
01518   view->reloadFile();
01519 
01520 }
01521 void KateViewEncodingAction::setScriptForEncodingAutoDetection (KEncodingDetector::AutoDetectScript script)
01522 {
01523   if (script==KEncodingDetector::SemiautomaticDetection)
01524   {
01525     doc->setEncoding("");
01526 #ifdef DECODE_DEBUG
01527     kWarning() << "KEncodingDetector::SemiautomaticDetection " <<doc->encoding();
01528 #endif
01529   }
01530   else
01531     doc->setScriptForEncodingAutoDetection(script);
01532   view->reloadFile();
01533 }
01534 //END KateViewEncodingAction
01535 
01536 //BEGIN KateViewBar related classes
01537 
01538 KateViewBarWidget::KateViewBarWidget (KateViewBar *viewBar)
01539  : QWidget (viewBar), m_viewBar (viewBar)
01540 {
01541   m_viewBar->addBarWidget (this);
01542 
01543   QHBoxLayout *layout = new QHBoxLayout;
01544 
01545   // NOTE: Here be cosmetics.
01546   layout->setMargin(2);
01547 
01548   // hide button
01549   QToolButton *hideButton = new QToolButton(this);
01550   hideButton->setAutoRaise(true);
01551   hideButton->setIcon(KIcon("dialog-close"));
01552   connect(hideButton, SIGNAL(clicked()), this, SLOT(hideBar()));
01553   layout->addWidget(hideButton);
01554   layout->setAlignment( hideButton, Qt::AlignLeft|Qt::AlignTop );
01555 
01556   // widget to be used as parent for the real content
01557   m_centralWidget = new QWidget ();
01558   layout->addWidget(m_centralWidget);
01559 
01560   setLayout(layout);
01561   setFocusProxy(m_centralWidget);
01562 }
01563 
01564 void KateViewBarWidget::showBar ()
01565 {
01566   m_viewBar->showBarWidget (this);
01567 }
01568 
01569 void KateViewBarWidget::hideBar ()
01570 {
01571   // let the barwidget do some stuff on hide, perhaps even say: no, don't hide me...
01572   if (!hideIsTriggered ())
01573     return;
01574 
01575   m_viewBar->hideBarWidget ();
01576 }
01577 
01578 
01579 
01580 KateStackedLayout::KateStackedLayout(QWidget* parent)
01581   : QStackedLayout(parent)
01582 {}
01583 
01584 QSize KateStackedLayout::sizeHint() const
01585 {
01586   if (currentWidget())
01587     return currentWidget()->sizeHint();
01588   return QStackedLayout::sizeHint();
01589 }
01590 
01591 QSize KateStackedLayout::minimumSize() const
01592 {
01593   if (currentWidget())
01594     return currentWidget()->minimumSize();
01595   return QStackedLayout::minimumSize();
01596 }
01597 
01598 
01599 
01600 KateViewBar::KateViewBar (KateView *view)
01601  : QWidget (view), m_view (view)
01602 {
01603   m_stack = new KateStackedLayout(this);
01604   hide ();
01605 }
01606 
01607 void KateViewBar::addBarWidget (KateViewBarWidget *newBarWidget)
01608 {
01609   // add new widget, invisible...
01610   m_stack->addWidget (newBarWidget);
01611 
01612   kDebug(13025)<<"add barwidget " << newBarWidget;
01613 }
01614 
01615 void KateViewBar::showBarWidget (KateViewBarWidget *barWidget)
01616 {
01617   // raise correct widget
01618   m_stack->setCurrentWidget (barWidget);
01619   kDebug(13025)<<"show barwidget " << barWidget;
01620   show ();
01621 }
01622 
01623 void KateViewBar::hideBarWidget ()
01624 {
01625   hide();
01626   kDebug(13025)<<"hide barwidget";
01627 }
01628 
01629 void KateViewBar::keyPressEvent(QKeyEvent* event)
01630 {
01631   if (event->key() == Qt::Key_Escape) {
01632     hideBarWidget();
01633     return;
01634   }
01635   QWidget::keyPressEvent(event);
01636 
01637 }
01638 
01639 void KateViewBar::hideEvent(QHideEvent* event)
01640 {
01641   if (!event->spontaneous())
01642     m_view->setFocus();
01643 }
01644 
01645 //END KateViewBar related classes
01646 
01647 // kate: space-indent on; indent-width 2; replace-tabs on;
01648 
01649 
01650 

Kate

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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