Kate
kateviewhelpers.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2008, 2009 Matthew Woehlke <mw_triad@users.sourceforge.net> 00003 Copyright (C) 2007 Mirko Stocker <me@misto.ch> 00004 Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org> 00005 Copyright (C) 2001 Anders Lund <anders@alweb.dk> 00006 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License version 2 as published by the Free Software Foundation. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include "kateviewhelpers.h" 00024 00025 #include "katecmd.h" 00026 #include <ktexteditor/attribute.h> 00027 #include <ktexteditor/annotationinterface.h> 00028 #include <ktexteditor/movingrange.h> 00029 #include <ktexteditor/containerinterface.h> 00030 #include "katecodefolding.h" 00031 #include "kateconfig.h" 00032 #include "katedocument.h" 00033 #include "katerenderer.h" 00034 #include "kateview.h" 00035 #include "kateviewinternal.h" 00036 #include "katelayoutcache.h" 00037 #include "katetextlayout.h" 00038 #include "kateglobal.h" 00039 00040 #include <kapplication.h> 00041 #include <kcharsets.h> 00042 #include <kcolorscheme.h> 00043 #include <kcolorutils.h> 00044 #include <kdebug.h> 00045 #include <kglobalsettings.h> 00046 #include <klocale.h> 00047 #include <knotification.h> 00048 #include <kglobal.h> 00049 #include <kmenu.h> 00050 #include <kiconloader.h> 00051 #include <kconfiggroup.h> 00052 00053 #include <QtAlgorithms> 00054 #include <QVariant> 00055 #include <QtGui/QCursor> 00056 #include <QtGui/QMenu> 00057 #include <QtGui/QPainter> 00058 #include <QtGui/QStyle> 00059 #include <QtCore/QTimer> 00060 #include <QtCore/QRegExp> 00061 #include <QtCore/QTextCodec> 00062 #include <QtGui/QKeyEvent> 00063 #include <QtGui/QPainterPath> 00064 #include <QtGui/QStyleOption> 00065 #include <QtGui/QPalette> 00066 #include <QtGui/QPen> 00067 #include <QtGui/QBoxLayout> 00068 #include <QtGui/QToolButton> 00069 #include <QtGui/QToolTip> 00070 #include <QtGui/QAction> 00071 #include <QtGui/QWhatsThis> 00072 00073 #include <math.h> 00074 00075 //BEGIN KateScrollBar 00076 KateScrollBar::KateScrollBar (Qt::Orientation orientation, KateViewInternal* parent) 00077 : QScrollBar (orientation, parent->m_view) 00078 , m_middleMouseDown (false) 00079 , m_view(parent->m_view) 00080 , m_doc(parent->doc()) 00081 , m_viewInternal(parent) 00082 , m_showMarks(false) 00083 { 00084 connect(this, SIGNAL(valueChanged(int)), this, SLOT(sliderMaybeMoved(int))); 00085 connect(m_doc, SIGNAL(marksChanged(KTextEditor::Document*)), this, SLOT(marksChanged())); 00086 00087 styleChange(*style()); 00088 } 00089 00090 void KateScrollBar::mousePressEvent(QMouseEvent* e) 00091 { 00092 if (e->button() == Qt::MidButton) 00093 m_middleMouseDown = true; 00094 00095 QScrollBar::mousePressEvent(e); 00096 00097 redrawMarks(); 00098 } 00099 00100 void KateScrollBar::mouseReleaseEvent(QMouseEvent* e) 00101 { 00102 QScrollBar::mouseReleaseEvent(e); 00103 00104 m_middleMouseDown = false; 00105 00106 redrawMarks(); 00107 } 00108 00109 void KateScrollBar::mouseMoveEvent(QMouseEvent* e) 00110 { 00111 QScrollBar::mouseMoveEvent(e); 00112 00113 if (e->buttons() | Qt::LeftButton) 00114 redrawMarks(); 00115 } 00116 00117 void KateScrollBar::paintEvent(QPaintEvent *e) 00118 { 00119 QScrollBar::paintEvent(e); 00120 00121 if (!m_showMarks) 00122 return; 00123 00124 QPainter painter(this); 00125 00126 QStyleOptionSlider opt; 00127 opt.init(this); 00128 opt.subControls = QStyle::SC_None; 00129 opt.activeSubControls = QStyle::SC_None; 00130 opt.orientation = orientation(); 00131 opt.minimum = minimum(); 00132 opt.maximum = maximum(); 00133 opt.sliderPosition = sliderPosition(); 00134 opt.sliderValue = value(); 00135 opt.singleStep = singleStep(); 00136 opt.pageStep = pageStep(); 00137 00138 QRect rect = style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSlider, this); 00139 00140 QHashIterator<int, QColor> it = m_lines; 00141 while (it.hasNext()) 00142 { 00143 it.next(); 00144 if (it.key() < rect.top() || it.key() > rect.bottom()) 00145 { 00146 painter.setPen(it.value()); 00147 painter.drawLine(0, it.key(), width(), it.key()); 00148 } 00149 } 00150 } 00151 00152 void KateScrollBar::resizeEvent(QResizeEvent *e) 00153 { 00154 QScrollBar::resizeEvent(e); 00155 recomputeMarksPositions(); 00156 } 00157 00158 void KateScrollBar::styleChange(QStyle &s) 00159 { 00160 QScrollBar::styleChange(s); 00161 recomputeMarksPositions(); 00162 } 00163 00164 void KateScrollBar::sliderChange ( SliderChange change ) 00165 { 00166 // call parents implementation 00167 QScrollBar::sliderChange (change); 00168 00169 if (change == QAbstractSlider::SliderValueChange) 00170 { 00171 redrawMarks(); 00172 } 00173 else if (change == QAbstractSlider::SliderRangeChange) 00174 { 00175 recomputeMarksPositions(); 00176 } 00177 } 00178 00179 void KateScrollBar::wheelEvent(QWheelEvent *e) 00180 { 00181 if (e->modifiers() == Qt::NoModifier) 00182 return QScrollBar::wheelEvent(e); 00183 00184 QCoreApplication::sendEvent(m_viewInternal, e); 00185 } 00186 00187 void KateScrollBar::marksChanged() 00188 { 00189 recomputeMarksPositions(); 00190 } 00191 00192 void KateScrollBar::redrawMarks() 00193 { 00194 if (!m_showMarks) 00195 return; 00196 00197 update(); 00198 } 00199 00200 void KateScrollBar::recomputeMarksPositions() 00201 { 00202 m_lines.clear(); 00203 int visibleLines = m_doc->visibleLines(); 00204 00205 QStyleOptionSlider opt; 00206 initStyleOption(&opt); 00207 00208 int topMargin = style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSubPage, this).top() + 1; 00209 int realHeight = style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarAddPage, this).bottom() - topMargin - 1; 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 / (visibleLines - 1); 00235 m_lines.insert(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 KateCommandLineBar::KateCommandLineBar (KateView *view, QWidget *parent) 00277 : KateViewBarWidget (true, parent) 00278 { 00279 QVBoxLayout *topLayout = new QVBoxLayout (); 00280 centralWidget()->setLayout(topLayout); 00281 topLayout->setMargin(0); 00282 m_lineEdit = new KateCmdLineEdit (this, view); 00283 connect(m_lineEdit, SIGNAL(hideRequested()), SIGNAL(hideMe())); 00284 topLayout->addWidget (m_lineEdit); 00285 00286 setFocusProxy (m_lineEdit); 00287 } 00288 00289 KateCommandLineBar::~KateCommandLineBar() 00290 { 00291 } 00292 00293 // inserts the given string in the command line edit and (if selcted = true) selects it so the user 00294 // can type over it if she wants to 00295 // inserts the given string in the command line edit and selects it so the user can type over it if 00296 // she wants to 00297 void KateCommandLineBar::setText(const QString &text, bool selected) 00298 { 00299 m_lineEdit->setText(text); 00300 if (selected) { 00301 m_lineEdit->selectAll(); 00302 } 00303 } 00304 00305 void KateCommandLineBar::execute(const QString &text) 00306 { 00307 m_lineEdit->slotReturnPressed(text); 00308 } 00309 00310 KateCmdLineEdit::KateCmdLineEdit (KateCommandLineBar *bar, KateView *view) 00311 : KLineEdit () 00312 , m_view (view) 00313 , m_bar (bar) 00314 , m_msgMode (false) 00315 , m_histpos( 0 ) 00316 , m_cmdend( 0 ) 00317 , m_command( 0L ) 00318 { 00319 connect (this, SIGNAL(returnPressed(const QString &)), 00320 this, SLOT(slotReturnPressed(const QString &))); 00321 00322 setCompletionObject(KateCmd::self()->commandCompletionObject()); 00323 setAutoDeleteCompletionObject( false ); 00324 m_cmdRange.setPattern("^([0-9$]+|\\.([+-]\\d+)?)?,([0-9$]+|\\.([+-]\\d+)?)?"); 00325 m_cmdExpr.setPattern("^(\\d+)([+-])(\\d+)$"); 00326 m_gotoLine.setPattern("[+-]?\\d+"); 00327 00328 m_hideTimer = new QTimer(this); 00329 m_hideTimer->setSingleShot(true); 00330 connect(m_hideTimer, SIGNAL(timeout()), this, SLOT(hideLineEdit())); 00331 00332 // make sure the timer is stopped when the user switches views. if not, focus will be given to the 00333 // wrong view when KateViewBar::hideCurrentBarWidget() is called after 4 seconds. (the timer is 00334 // used for showing things like "Success" for four seconds after the user has used the kate 00335 // command line) 00336 connect(m_view, SIGNAL(focusOut (KTextEditor::View*)), m_hideTimer, SLOT(stop())); 00337 } 00338 00339 void KateCmdLineEdit::hideEvent(QHideEvent *e) 00340 { 00341 Q_UNUSED(e); 00342 m_view->showViModeBar(); 00343 } 00344 00345 00346 QString KateCmdLineEdit::helptext( const QPoint & ) const 00347 { 00348 QString beg = "<qt background=\"white\"><div><table width=\"100%\"><tr><td bgcolor=\"brown\"><font color=\"white\"><b>Help: <big>"; 00349 QString mid = "</big></b></font></td></tr><tr><td>"; 00350 QString end = "</td></tr></table></div><qt>"; 00351 00352 QString t = text(); 00353 QRegExp re( "\\s*help\\s+(.*)" ); 00354 if ( re.indexIn( t ) > -1 ) 00355 { 00356 QString s; 00357 // get help for command 00358 QString name = re.cap( 1 ); 00359 if ( name == "list" ) 00360 { 00361 return beg + i18n("Available Commands") + mid 00362 + KateCmd::self()->commandList().join(" ") 00363 + i18n("<p>For help on individual commands, do <code>'help <command>'</code></p>") 00364 + end; 00365 } 00366 else if ( ! name.isEmpty() ) 00367 { 00368 KTextEditor::Command *cmd = KateCmd::self()->queryCommand( name ); 00369 if ( cmd ) 00370 { 00371 if ( cmd->help( m_view, name, s ) ) 00372 return beg + name + mid + s + end; 00373 else 00374 return beg + name + mid + i18n("No help for '%1'", name ) + end; 00375 } 00376 else 00377 return beg + mid + i18n("No such command <b>%1</b>", name) + end; 00378 } 00379 } 00380 00381 return beg + mid + i18n( 00382 "<p>This is the Katepart <b>command line</b>.<br />" 00383 "Syntax: <code><b>command [ arguments ]</b></code><br />" 00384 "For a list of available commands, enter <code><b>help list</b></code><br />" 00385 "For help for individual commands, enter <code><b>help <command></b></code></p>") 00386 + end; 00387 } 00388 00389 00390 00391 bool KateCmdLineEdit::event(QEvent *e) { 00392 if (e->type() == QEvent::QueryWhatsThis) { 00393 setWhatsThis(helptext(QPoint())); 00394 e->accept(); 00395 return true; 00396 } 00397 return KLineEdit::event(e); 00398 } 00399 00400 void KateCmdLineEdit::slotReturnPressed ( const QString& text ) 00401 { 00402 if (text.isEmpty()) return; 00403 // silently ignore leading space characters and colon characters (for vi-heads) 00404 uint n = 0; 00405 const uint textlen=text.length(); 00406 while( (n<textlen) && ( text[n].isSpace() || text[n] == ':' ) ) 00407 n++; 00408 00409 if (n>=textlen) return; 00410 00411 QString cmd = text.mid( n ); 00412 00413 // expand '%' to '1,$' ("all lines") if at the start of the line 00414 if ( cmd.at( 0 ) == '%' ) { 00415 cmd.replace( 0, 1, "1,$" ); 00416 } 00417 00418 KTextEditor::Range range(-1, 0, -1, 0); 00419 00420 // check if a range was given 00421 if (m_cmdRange.indexIn(cmd) != -1 && m_cmdRange.matchedLength() > 0) { 00422 00423 cmd.remove( m_cmdRange ); 00424 00425 QString s = m_cmdRange.capturedTexts().at(1); 00426 QString e = m_cmdRange.capturedTexts().at(3); 00427 00428 if ( s.isEmpty() ) 00429 s = '.'; 00430 if ( e.isEmpty() ) 00431 e = s; 00432 00433 // replace '$' with the number of the last line and '.' with the current line 00434 s.replace('$', QString::number( m_view->doc()->lines() ) ); 00435 e.replace('$', QString::number( m_view->doc()->lines() ) ); 00436 s.replace('.', QString::number( m_view->cursorPosition().line()+1 ) ); 00437 e.replace('.', QString::number( m_view->cursorPosition().line()+1 ) ); 00438 00439 // evaluate expressions (a+b or a-b) if we have any 00440 if (m_cmdExpr.indexIn(s) != -1) { 00441 if (m_cmdExpr.capturedTexts().at(2) == "+") { 00442 s = QString::number(m_cmdExpr.capturedTexts().at(1).toInt() 00443 + m_cmdExpr.capturedTexts().at(3).toInt()); 00444 } else { 00445 s = QString::number(m_cmdExpr.capturedTexts().at(1).toInt() 00446 - m_cmdExpr.capturedTexts().at(3).toInt()); 00447 } 00448 } 00449 if (m_cmdExpr.indexIn(e) != -1) { 00450 if (m_cmdExpr.capturedTexts().at(2) == "+") { 00451 e = QString::number(m_cmdExpr.capturedTexts().at(1).toInt() 00452 + m_cmdExpr.capturedTexts().at(3).toInt()); 00453 } else { 00454 e = QString::number(m_cmdExpr.capturedTexts().at(1).toInt() 00455 - m_cmdExpr.capturedTexts().at(3).toInt()); 00456 } 00457 } 00458 00459 range.setRange(KTextEditor::Range(s.toInt()-1, 0, e.toInt()-1, 0)); 00460 } 00461 00462 // special case: if the command is just a number with an optional +/- prefix, rewrite to "goto" 00463 if (m_gotoLine.exactMatch(cmd)) { 00464 cmd.prepend("goto "); 00465 } 00466 00467 // Built in help: if the command starts with "help", [try to] show some help 00468 if ( cmd.startsWith( QLatin1String("help") ) ) 00469 { 00470 QWhatsThis::showText(mapToGlobal(QPoint(0,0)), helptext( QPoint() ) ); 00471 clear(); 00472 KateCmd::self()->appendHistory( cmd ); 00473 m_histpos = KateCmd::self()->historyLength(); 00474 m_oldText.clear(); 00475 return; 00476 } 00477 00478 if (cmd.length () > 0) 00479 { 00480 KTextEditor::Command *p = KateCmd::self()->queryCommand (cmd); 00481 KTextEditor::RangeCommand *ce = dynamic_cast<KTextEditor::RangeCommand*>(p); 00482 00483 m_oldText = m_cmdRange.capturedTexts().at(0) + cmd; 00484 m_msgMode = true; 00485 00486 // we got a range and a valid command, but the command does not inherit the RangeCommand 00487 // extension. bail out. 00488 if ( ( !ce && range.isValid() && p ) || ( range.isValid() && ce && !ce->supportsRange(cmd) ) ) { 00489 setText (i18n ("Error: No range allowed for command \"%1\".", cmd)); 00490 } else { 00491 00492 if (p) 00493 { 00494 QString msg; 00495 00496 if ((ce && ce->exec(m_view, cmd, msg, range)) || p->exec (m_view, cmd, msg)) 00497 { 00498 00499 // append command along with range (will be empty if none given) to history 00500 KateCmd::self()->appendHistory( m_cmdRange.capturedTexts().at(0) + cmd ); 00501 m_histpos = KateCmd::self()->historyLength(); 00502 m_oldText.clear(); 00503 00504 if (msg.length() > 0) 00505 setText (i18n ("Success: ") + msg); 00506 else 00507 // always hide on success without message 00508 emit hideRequested(); 00509 } 00510 else 00511 { 00512 if (msg.length() > 0) { 00513 if (msg.contains('\n')) { 00514 // multiline error, use widget with more space 00515 QWhatsThis::showText(mapToGlobal(QPoint(0,0)), msg); 00516 } else { 00517 setText(msg); 00518 } 00519 } else 00520 setText (i18n ("Command \"%1\" failed.", cmd)); 00521 KNotification::beep(); 00522 } 00523 } 00524 else 00525 { 00526 setText (i18n ("No such command: \"%1\"", cmd)); 00527 KNotification::beep(); 00528 } 00529 } 00530 } 00531 00532 // clean up 00533 if (completionObject() != KateCmd::self()->commandCompletionObject()) 00534 { 00535 KCompletion *c = completionObject(); 00536 setCompletionObject(KateCmd::self()->commandCompletionObject()); 00537 delete c; 00538 } 00539 m_command = 0; 00540 m_cmdend = 0; 00541 00542 // the following commands change the focus themselves 00543 // FIXME: ugly :-( 00544 if (cmd != "bn" && cmd != "bp" && cmd != "new" && cmd != "vnew" && cmd != "enew") { 00545 m_view->setFocus (); 00546 } 00547 00548 if (isVisible()) { 00549 m_hideTimer->start(4000); 00550 } 00551 } 00552 00553 void KateCmdLineEdit::hideLineEdit () // unless i have focus ;) 00554 { 00555 if ( ! hasFocus() ) { 00556 emit hideRequested(); 00557 } 00558 } 00559 00560 void KateCmdLineEdit::focusInEvent ( QFocusEvent *ev ) 00561 { 00562 if (m_msgMode) 00563 { 00564 m_msgMode = false; 00565 setText (m_oldText); 00566 selectAll(); 00567 } 00568 00569 KLineEdit::focusInEvent (ev); 00570 } 00571 00572 void KateCmdLineEdit::keyPressEvent( QKeyEvent *ev ) 00573 { 00574 if (ev->key() == Qt::Key_Escape || 00575 (ev->key() == Qt::Key_BracketLeft && ev->modifiers() == Qt::ControlModifier)) 00576 { 00577 m_view->setFocus (); 00578 hideLineEdit(); 00579 clear(); 00580 } 00581 else if ( ev->key() == Qt::Key_Up ) 00582 fromHistory( true ); 00583 else if ( ev->key() == Qt::Key_Down ) 00584 fromHistory( false ); 00585 00586 uint cursorpos = cursorPosition(); 00587 KLineEdit::keyPressEvent (ev); 00588 00589 // during typing, let us see if we have a valid command 00590 if ( ! m_cmdend || cursorpos <= m_cmdend ) 00591 { 00592 QChar c; 00593 if ( ! ev->text().isEmpty() ) 00594 c = ev->text()[0]; 00595 00596 if ( ! m_cmdend && ! c.isNull() ) // we have no command, so lets see if we got one 00597 { 00598 if ( ! c.isLetterOrNumber() && c != '-' && c != '_' ) 00599 { 00600 m_command = KateCmd::self()->queryCommand( text().trimmed() ); 00601 if ( m_command ) 00602 { 00603 //kDebug(13025)<<"keypress in commandline: We have a command! "<<m_command<<". text is '"<<text()<<"'"; 00604 // if the typed character is ":", 00605 // we try if the command has flag completions 00606 m_cmdend = cursorpos; 00607 //kDebug(13025)<<"keypress in commandline: Set m_cmdend to "<<m_cmdend; 00608 } 00609 else 00610 m_cmdend = 0; 00611 } 00612 } 00613 else // since cursor is inside the command name, we reconsider it 00614 { 00615 kDebug(13025)<<"keypress in commandline: \\W -- text is "<<text(); 00616 m_command = KateCmd::self()->queryCommand( text().trimmed() ); 00617 if ( m_command ) 00618 { 00619 //kDebug(13025)<<"keypress in commandline: We have a command! "<<m_command; 00620 QString t = text(); 00621 m_cmdend = 0; 00622 bool b = false; 00623 for ( ; (int)m_cmdend < t.length(); m_cmdend++ ) 00624 { 00625 if ( t[m_cmdend].isLetter() ) 00626 b = true; 00627 if ( b && ( ! t[m_cmdend].isLetterOrNumber() && t[m_cmdend] != '-' && t[m_cmdend] != '_' ) ) 00628 break; 00629 } 00630 00631 if ( c == ':' && cursorpos == m_cmdend ) 00632 { 00633 // check if this command wants to complete flags 00634 //kDebug(13025)<<"keypress in commandline: Checking if flag completion is desired!"; 00635 } 00636 } 00637 else 00638 { 00639 // clean up if needed 00640 if (completionObject() != KateCmd::self()->commandCompletionObject()) 00641 { 00642 KCompletion *c = completionObject(); 00643 setCompletionObject(KateCmd::self()->commandCompletionObject()); 00644 delete c; 00645 } 00646 00647 m_cmdend = 0; 00648 } 00649 } 00650 00651 // if we got a command, check if it wants to do something. 00652 if ( m_command ) 00653 { 00654 //kDebug(13025)<<"Checking for CommandExtension.."; 00655 KTextEditor::CommandExtension *ce = dynamic_cast<KTextEditor::CommandExtension*>(m_command); 00656 if ( ce ) 00657 { 00658 KCompletion *cmpl = ce->completionObject( m_view, text().left( m_cmdend ).trimmed() ); 00659 if ( cmpl ) 00660 { 00661 // We need to prepend the current command name + flag string 00662 // when completion is done 00663 //kDebug(13025)<<"keypress in commandline: Setting completion object!"; 00664 00665 setCompletionObject( cmpl ); 00666 } 00667 } 00668 } 00669 } 00670 else if ( m_command )// check if we should call the commands processText() 00671 { 00672 KTextEditor::CommandExtension *ce = dynamic_cast<KTextEditor::CommandExtension*>( m_command ); 00673 if ( ce && ce->wantsToProcessText( text().left( m_cmdend ).trimmed() ) 00674 && ! ( ev->text().isNull() || ev->text().isEmpty() ) ) 00675 ce->processText( m_view, text() ); 00676 } 00677 } 00678 00679 void KateCmdLineEdit::fromHistory( bool up ) 00680 { 00681 if ( ! KateCmd::self()->historyLength() ) 00682 return; 00683 00684 QString s; 00685 00686 if ( up ) 00687 { 00688 if ( m_histpos > 0 ) 00689 { 00690 m_histpos--; 00691 s = KateCmd::self()->fromHistory( m_histpos ); 00692 } 00693 } 00694 else 00695 { 00696 if ( m_histpos < ( KateCmd::self()->historyLength() - 1 ) ) 00697 { 00698 m_histpos++; 00699 s = KateCmd::self()->fromHistory( m_histpos ); 00700 } 00701 else 00702 { 00703 m_histpos = KateCmd::self()->historyLength(); 00704 setText( m_oldText ); 00705 } 00706 } 00707 if ( ! s.isEmpty() ) 00708 { 00709 // Select the argument part of the command, so that it is easy to overwrite 00710 setText( s ); 00711 static QRegExp reCmd = QRegExp(".*[\\w\\-]+(?:[^a-zA-Z0-9_-]|:\\w+)(.*)"); 00712 if ( reCmd.indexIn( text() ) == 0 ) 00713 setSelection( text().length() - reCmd.cap(1).length(), reCmd.cap(1).length() ); 00714 } 00715 } 00716 //END KateCmdLineEdit 00717 00718 //BEGIN KateIconBorder 00719 using namespace KTextEditor; 00720 00721 const int halfIPW = 8; 00722 00723 KateIconBorder::KateIconBorder ( KateViewInternal* internalView, QWidget *parent ) 00724 : QWidget(parent) 00725 , m_view( internalView->m_view ) 00726 , m_doc( internalView->doc() ) 00727 , m_viewInternal( internalView ) 00728 , m_iconBorderOn( false ) 00729 , m_lineNumbersOn( false ) 00730 , m_foldingMarkersOn( false ) 00731 , m_dynWrapIndicatorsOn( false ) 00732 , m_annotationBorderOn( false ) 00733 , m_dynWrapIndicators( 0 ) 00734 , m_cachedLNWidth( 0 ) 00735 , m_maxCharWidth( 0 ) 00736 , iconPaneWidth (16) 00737 , m_annotationBorderWidth (6) 00738 , m_foldingRange(0) 00739 , m_nextHighlightBlock(-2) 00740 , m_currentBlockLine(-1) 00741 { 00742 initializeFoldingColors(); 00743 00744 setAttribute( Qt::WA_StaticContents ); 00745 setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ); 00746 setMouseTracking(true); 00747 m_doc->setMarkDescription( MarkInterface::markType01, i18n("Bookmark") ); 00748 m_doc->setMarkPixmap( MarkInterface::markType01, KIcon("bookmarks").pixmap(16, 16) ); 00749 00750 updateFont(); 00751 00752 m_delayFoldingHlTimer.setSingleShot(true); 00753 m_delayFoldingHlTimer.setInterval(250); 00754 connect(&m_delayFoldingHlTimer, SIGNAL(timeout()), this, SLOT(showBlock())); 00755 } 00756 00757 void KateIconBorder::initializeFoldingColors() 00758 { 00759 // Get the schema 00760 KateRendererConfig *config = m_view->renderer()->config(); 00761 // FIXME next 3 lines temporary until this moves to config 00762 const KColorScheme scheme( QPalette::Normal ); 00763 const QColor middle( KColorUtils::tint( config->iconBarColor(), scheme.foreground( KColorScheme::NeutralText ).color(), 0.7 ) ); 00764 const QColor final( KColorUtils::tint( config->iconBarColor(), scheme.foreground( KColorScheme::PositiveText ).color(), 0.7 ) ); 00765 00766 const QColor start( config->iconBarColor() ); 00767 static const int MIDFOLDINGCOLORS = MAXFOLDINGCOLORS / 2; 00768 static const qreal n = 2.0 / MAXFOLDINGCOLORS; 00769 00770 int i, j; 00771 for( i = 0; i < MIDFOLDINGCOLORS; i++ ) { 00772 const qreal a = 0.9 * pow(qreal(i) * n, 1.0); 00773 m_foldingColors[i] = KColorUtils::tint( start, middle, a ); 00774 } 00775 for( j = 0; i < MAXFOLDINGCOLORS; i++, j++ ) { 00776 const qreal a = 0.9 * pow(qreal(j) * n, 1.0); 00777 m_foldingColors[i] = KColorUtils::tint( middle, final, a ); 00778 } 00779 } 00780 00781 00782 KateIconBorder::~KateIconBorder() 00783 { 00784 delete m_foldingRange; 00785 m_foldingRange = 0; 00786 } 00787 00788 void KateIconBorder::setIconBorderOn( bool enable ) 00789 { 00790 if( enable == m_iconBorderOn ) 00791 return; 00792 00793 m_iconBorderOn = enable; 00794 00795 updateGeometry(); 00796 00797 QTimer::singleShot( 0, this, SLOT(update()) ); 00798 } 00799 00800 void KateIconBorder::setAnnotationBorderOn( bool enable ) 00801 { 00802 if( enable == m_annotationBorderOn ) 00803 return; 00804 00805 m_annotationBorderOn = enable; 00806 00807 emit m_view->annotationBorderVisibilityChanged(m_view, enable); 00808 00809 updateGeometry(); 00810 00811 QTimer::singleShot( 0, this, SLOT(update()) ); 00812 } 00813 00814 void KateIconBorder::removeAnnotationHovering() 00815 { 00816 // remove hovering if it's still there 00817 if (m_annotationBorderOn && !m_hoveredAnnotationText.isEmpty()) 00818 { 00819 m_hoveredAnnotationText.clear(); 00820 hideAnnotationTooltip(); 00821 QTimer::singleShot( 0, this, SLOT(update()) ); 00822 } 00823 } 00824 00825 void KateIconBorder::setLineNumbersOn( bool enable ) 00826 { 00827 if( enable == m_lineNumbersOn ) 00828 return; 00829 00830 m_lineNumbersOn = enable; 00831 m_dynWrapIndicatorsOn = (m_dynWrapIndicators == 1) ? enable : m_dynWrapIndicators; 00832 00833 updateGeometry(); 00834 00835 QTimer::singleShot( 0, this, SLOT(update()) ); 00836 } 00837 00838 void KateIconBorder::setDynWrapIndicators( int state ) 00839 { 00840 if (state == m_dynWrapIndicators ) 00841 return; 00842 00843 m_dynWrapIndicators = state; 00844 m_dynWrapIndicatorsOn = (state == 1) ? m_lineNumbersOn : state; 00845 00846 updateGeometry (); 00847 00848 QTimer::singleShot( 0, this, SLOT(update()) ); 00849 } 00850 00851 void KateIconBorder::setFoldingMarkersOn( bool enable ) 00852 { 00853 if( enable == m_foldingMarkersOn ) 00854 return; 00855 00856 m_foldingMarkersOn = enable; 00857 00858 updateGeometry(); 00859 00860 QTimer::singleShot( 0, this, SLOT(update()) ); 00861 } 00862 00863 QSize KateIconBorder::sizeHint() const 00864 { 00865 int w = 0; 00866 00867 if (m_iconBorderOn) 00868 w += iconPaneWidth + 1; 00869 00870 if (m_annotationBorderOn) 00871 { 00872 w += m_annotationBorderWidth + 1; 00873 } 00874 00875 if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) { 00876 w += lineNumberWidth() + 1; 00877 } 00878 00879 if (m_foldingMarkersOn) 00880 w += iconPaneWidth + 1; 00881 00882 w += 4; 00883 00884 return QSize( w, 0 ); 00885 } 00886 00887 // This function (re)calculates the maximum width of any of the digit characters (0 -> 9) 00888 // for graceful handling of variable-width fonts as the linenumber font. 00889 void KateIconBorder::updateFont() 00890 { 00891 QFontMetrics fm = m_view->renderer()->config()->fontMetrics(); 00892 m_maxCharWidth = 0; 00893 // Loop to determine the widest numeric character in the current font. 00894 // 48 is ascii '0' 00895 for (int i = 48; i < 58; i++) { 00896 int charWidth = fm.width( QChar(i) ); 00897 m_maxCharWidth = qMax(m_maxCharWidth, charWidth); 00898 } 00899 00900 // the icon pane scales with the font... 00901 iconPaneWidth = fm.height(); 00902 00903 updateGeometry(); 00904 00905 QTimer::singleShot( 0, this, SLOT(update()) ); 00906 } 00907 00908 int KateIconBorder::lineNumberWidth() const 00909 { 00910 int width = m_lineNumbersOn ? ((int)log10((double)(m_view->doc()->lines())) + 1) * m_maxCharWidth + 4 : 0; 00911 00912 if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) { 00913 // HACK: 16 == style().scrollBarExtent().width() 00914 width = qMax(16 + 4, width); 00915 00916 if (m_cachedLNWidth != width || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) { 00917 int w = 16;// HACK: 16 == style().scrollBarExtent().width() style().scrollBarExtent().width(); 00918 int h = m_view->renderer()->config()->fontMetrics().height(); 00919 00920 QSize newSize(w, h); 00921 if ((m_arrow.size() != newSize || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor()) && !newSize.isEmpty()) { 00922 m_arrow = QPixmap(newSize); 00923 00924 QPainter p(&m_arrow); 00925 p.fillRect( 0, 0, w, h, m_view->renderer()->config()->iconBarColor() ); 00926 00927 h = m_view->renderer()->config()->fontMetrics().ascent(); 00928 00929 p.setPen(m_view->renderer()->config()->lineNumberColor()); 00930 00931 QPainterPath path; 00932 path.moveTo(w/2, h/2); 00933 path.lineTo(w/2, 0); 00934 path.lineTo(w/4, h/4); 00935 path.lineTo(0, 0); 00936 path.lineTo(0, h/2); 00937 path.lineTo(w/2, h-1); 00938 path.lineTo(w*3/4, h-1); 00939 path.lineTo(w-1, h*3/4); 00940 path.lineTo(w*3/4, h/2); 00941 path.lineTo(0, h/2); 00942 p.drawPath(path); 00943 } 00944 } 00945 } 00946 00947 return width; 00948 } 00949 00950 QBrush KateIconBorder::foldingColor(KateLineInfo *info,int realLine, bool solid) { 00951 int depth; 00952 if (info != 0) { 00953 depth = info->depth; 00954 } else { 00955 KateLineInfo tmp; 00956 m_doc->lineInfo(&tmp, realLine); 00957 depth = tmp.depth; 00958 } 00959 00960 QColor result; 00961 if (depth < MAXFOLDINGCOLORS) 00962 result = m_foldingColors[depth]; 00963 else 00964 result = m_foldingColors[MAXFOLDINGCOLORS-1]; 00965 if (!solid) 00966 result.setAlphaF(0.4); 00967 00968 return QBrush( result ); 00969 00970 } 00971 00972 void KateIconBorder::paintEvent(QPaintEvent* e) 00973 { 00974 paintBorder(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height()); 00975 } 00976 00977 static void paintTriangle (QPainter &painter, const QColor &baseColor, int xOffset, int yOffset, int width, int height, bool open) 00978 { 00979 painter.setRenderHint(QPainter::Antialiasing); 00980 00981 qreal size = qMin (width, height); 00982 00983 QColor c; 00984 if ( KColorUtils::luma( baseColor ) > 0.25 ) 00985 c = KColorUtils::darken( baseColor ); 00986 else 00987 c = KColorUtils::shade( baseColor, 0.2 ); 00988 00989 QPen pen; 00990 pen.setJoinStyle (Qt::RoundJoin); 00991 pen.setColor (c); 00992 pen.setWidthF (1.5); 00993 painter.setPen ( pen ); 00994 00995 painter.setBrush ( c ); 00996 00997 // let some border, if possible 00998 size *= 0.6; 00999 01000 qreal halfSize = size / 2; 01001 qreal halfSizeP = halfSize * 0.6; 01002 QPointF middle (xOffset + (qreal)width / 2, yOffset + (qreal)height / 2); 01003 01004 if (open) 01005 { 01006 QPointF points[3] = { middle+QPointF(-halfSize, -halfSizeP), middle+QPointF(halfSize, -halfSizeP), middle+QPointF(0, halfSizeP) }; 01007 painter.drawConvexPolygon(points, 3); 01008 } 01009 else 01010 { 01011 QPointF points[3] = { middle+QPointF(-halfSizeP, -halfSize), middle+QPointF(-halfSizeP, halfSize), middle+QPointF(halfSizeP, 0) }; 01012 painter.drawConvexPolygon(points, 3); 01013 } 01014 01015 painter.setRenderHint(QPainter::Antialiasing, false); 01016 } 01017 01018 void KateIconBorder::paintBorder (int /*x*/, int y, int /*width*/, int height) 01019 { 01020 uint h = m_view->renderer()->config()->fontMetrics().height(); 01021 uint startz = (y / h); 01022 uint endz = startz + 1 + (height / h); 01023 uint lineRangesSize = m_viewInternal->cache()->viewCacheLineCount(); 01024 01025 // center the folding boxes 01026 int m_px = (h - 11) / 2; 01027 if (m_px < 0) 01028 m_px = 0; 01029 01030 int lnWidth( 0 ); 01031 if ( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) // avoid calculating unless needed ;-) 01032 { 01033 lnWidth = lineNumberWidth(); 01034 if ( lnWidth != m_cachedLNWidth || m_oldBackgroundColor != m_view->renderer()->config()->iconBarColor() ) 01035 { 01036 // we went from n0 ->n9 lines or vice verca 01037 // this causes an extra updateGeometry() first time the line numbers 01038 // are displayed, but sizeHint() is supposed to be const so we can't set 01039 // the cached value there. 01040 m_cachedLNWidth = lnWidth; 01041 m_oldBackgroundColor = m_view->renderer()->config()->iconBarColor(); 01042 updateGeometry(); 01043 update (); 01044 return; 01045 } 01046 } 01047 01048 int w( this->width() ); // sane value/calc only once 01049 01050 QPainter p ( this ); 01051 p.setRenderHints (QPainter::TextAntialiasing); 01052 p.setFont ( m_view->renderer()->config()->font() ); // for line numbers 01053 01054 KateLineInfo oldInfo; 01055 if (startz < lineRangesSize) 01056 { 01057 if ((m_viewInternal->cache()->viewLine(startz).line()-1) < 0) 01058 oldInfo.topLevel = true; 01059 else 01060 m_doc->lineInfo(&oldInfo,m_viewInternal->cache()->viewLine(startz).line()-1); 01061 } 01062 01063 KTextEditor::AnnotationModel *model = m_view->annotationModel() ? 01064 m_view->annotationModel() : m_doc->annotationModel(); 01065 01066 for (uint z=startz; z <= endz; z++) 01067 { 01068 int y = h * z; 01069 int realLine = -1; 01070 01071 if (z < lineRangesSize) 01072 realLine = m_viewInternal->cache()->viewLine(z).line(); 01073 01074 int lnX = 0; 01075 01076 p.fillRect( 0, y, w-4, h, m_view->renderer()->config()->iconBarColor() ); 01077 p.fillRect( w-4, y, 4, h, m_view->renderer()->config()->backgroundColor() ); 01078 01079 // icon pane 01080 if( m_iconBorderOn ) 01081 { 01082 p.setPen ( m_view->renderer()->config()->lineNumberColor() ); 01083 p.setBrush ( m_view->renderer()->config()->lineNumberColor() ); 01084 p.drawLine(lnX+iconPaneWidth+1, y, lnX+iconPaneWidth+1, y+h); 01085 01086 if( (realLine > -1) && (m_viewInternal->cache()->viewLine(z).startCol() == 0) ) 01087 { 01088 uint mrk ( m_doc->mark( realLine ) ); // call only once 01089 01090 if ( mrk ) 01091 { 01092 for( uint bit = 0; bit < 32; bit++ ) 01093 { 01094 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit); 01095 if( mrk & markType ) 01096 { 01097 QPixmap px_mark (m_doc->markPixmap( markType )); 01098 01099 if (!px_mark.isNull() && h > 0 && iconPaneWidth > 0) 01100 { 01101 if (iconPaneWidth < px_mark.width() || h < (uint)px_mark.height()) 01102 px_mark = px_mark.scaled (iconPaneWidth, h, Qt::KeepAspectRatio); 01103 01104 // center the mark pixmap 01105 int x_px = (iconPaneWidth - px_mark.width()) / 2; 01106 if (x_px < 0) 01107 x_px = 0; 01108 01109 int y_px = (h - px_mark.height()) / 2; 01110 if (y_px < 0) 01111 y_px = 0; 01112 01113 p.drawPixmap( lnX+x_px, y+y_px, px_mark); 01114 } 01115 } 01116 } 01117 } 01118 } 01119 01120 lnX += iconPaneWidth + 2; 01121 } 01122 01123 // annotation information 01124 if( m_annotationBorderOn ) 01125 { 01126 // Draw a border line between annotations and the line numbers 01127 p.setPen ( m_view->renderer()->config()->lineNumberColor() ); 01128 p.setBrush ( m_view->renderer()->config()->lineNumberColor() ); 01129 01130 int borderWidth = m_annotationBorderWidth; 01131 p.drawLine(lnX+borderWidth+1, y, lnX+borderWidth+1, y+h); 01132 01133 if( (realLine > -1) && model ) 01134 { 01135 // Fetch data from the model 01136 QVariant text = model->data( realLine, Qt::DisplayRole ); 01137 QVariant foreground = model->data( realLine, Qt::ForegroundRole ); 01138 QVariant background = model->data( realLine, Qt::BackgroundRole ); 01139 // Fill the background 01140 if( background.isValid() ) 01141 { 01142 p.fillRect( lnX, y, borderWidth + 1, h, background.value<QBrush>() ); 01143 } 01144 // Set the pen for drawing the foreground 01145 if( foreground.isValid() ) 01146 { 01147 p.setBrush( foreground.value<QBrush>() ); 01148 } 01149 01150 // Draw a border around all adjacent entries that have the same text as the currently hovered one 01151 if( m_hoveredAnnotationText == text.toString() ) 01152 { 01153 p.drawLine( lnX, y, lnX, y+h ); 01154 p.drawLine( lnX+borderWidth, y, lnX+borderWidth, y+h ); 01155 01156 QVariant beforeText = model->data( realLine-1, Qt::DisplayRole ); 01157 QVariant afterText = model->data( realLine+1, Qt::DisplayRole ); 01158 if( ((beforeText.isValid() && beforeText.canConvert<QString>() 01159 && text.isValid() && text.canConvert<QString>() 01160 && beforeText.toString() != text.toString()) || realLine == 0) 01161 && m_viewInternal->cache()->viewLine(z).viewLine() == 0) 01162 { 01163 p.drawLine( lnX+1, y, lnX+borderWidth, y ); 01164 } 01165 01166 if( ((afterText.isValid() && afterText.canConvert<QString>() 01167 && text.isValid() && text.canConvert<QString>() 01168 && afterText.toString() != text.toString()) 01169 || realLine == m_view->doc()->lines() - 1) 01170 && m_viewInternal->cache()->viewLine(z).viewLine() == m_viewInternal->cache()->viewLineCount(realLine)-1) 01171 { 01172 p.drawLine( lnX+1, y+h-1, lnX+borderWidth, y+h-1 ); 01173 } 01174 } 01175 if( foreground.isValid() ) 01176 { 01177 QPen pen = p.pen(); 01178 pen.setWidth( 1 ); 01179 p.setPen( pen ); 01180 } 01181 01182 // Now draw the normal text 01183 if( text.isValid() && text.canConvert<QString>() && (m_viewInternal->cache()->viewLine(z).startCol() == 0) ) 01184 { 01185 p.drawText( lnX+3, y, borderWidth-3, h, Qt::AlignLeft|Qt::AlignVCenter, text.toString() ); 01186 } 01187 } 01188 01189 // adjust current X position and reset the pen and brush 01190 lnX += borderWidth + 2; 01191 } 01192 01193 // line number 01194 if( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) 01195 { 01196 p.setPen ( m_view->renderer()->config()->lineNumberColor() ); 01197 p.setBrush ( m_view->renderer()->config()->lineNumberColor() ); 01198 01199 if (realLine > -1) { 01200 if (m_viewInternal->cache()->viewLine(z).startCol() == 0) { 01201 if (m_lineNumbersOn) 01202 p.drawText( lnX, y, lnWidth-4, h, Qt::AlignRight|Qt::AlignVCenter, QString("%1").arg( realLine + 1 ) ); 01203 } else if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) { 01204 p.drawPixmap(lnX + lnWidth - m_arrow.width() - 2, y, m_arrow); 01205 } 01206 } 01207 01208 lnX += lnWidth + 2; 01209 } 01210 01211 // folding markers 01212 if( m_foldingMarkersOn ) 01213 { 01214 if( realLine > -1 ) 01215 { 01216 KateLineInfo info; 01217 m_doc->lineInfo(&info,realLine); 01218 01219 QBrush brush (foldingColor(&info,realLine,true)); 01220 p.fillRect(lnX, y, iconPaneWidth, h, brush); 01221 01222 if (!info.topLevel) 01223 { 01224 if (info.startsVisibleBlock && (m_viewInternal->cache()->viewLine(z).startCol() == 0)) 01225 { 01226 paintTriangle (p, brush.color(), lnX, y, iconPaneWidth, h, true); 01227 } 01228 else if (info.startsInVisibleBlock && m_viewInternal->cache()->viewLine(z).startCol() == 0) 01229 { 01230 paintTriangle (p, brush.color(), lnX, y, iconPaneWidth, h, false); 01231 } 01232 else 01233 { 01234 // p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 01235 01236 // if (info.endsBlock && !m_viewInternal->cache()->viewLine(z).wrap()) 01237 // p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1); 01238 } 01239 } 01240 01241 oldInfo = info; 01242 } 01243 01244 lnX += iconPaneWidth + 2; 01245 } 01246 } 01247 } 01248 01249 KateIconBorder::BorderArea KateIconBorder::positionToArea( const QPoint& p ) const 01250 { 01251 int x = 0; 01252 if( m_iconBorderOn ) { 01253 x += iconPaneWidth; 01254 if( p.x() <= x ) 01255 return IconBorder; 01256 } 01257 if( this->m_annotationBorderOn ) { 01258 x += m_annotationBorderWidth; 01259 if( p.x() <= x ) 01260 return AnnotationBorder; 01261 } 01262 if( m_lineNumbersOn || m_dynWrapIndicators ) { 01263 x += lineNumberWidth(); 01264 if( p.x() <= x ) 01265 return LineNumbers; 01266 } 01267 if( m_foldingMarkersOn ) { 01268 x += iconPaneWidth; 01269 if( p.x() <= x ) 01270 return FoldingMarkers; 01271 } 01272 return None; 01273 } 01274 01275 void KateIconBorder::mousePressEvent( QMouseEvent* e ) 01276 { 01277 const KateTextLayout& t = m_viewInternal->yToKateTextLayout(e->y()); 01278 if (t.isValid()) { 01279 m_lastClickedLine = t.line(); 01280 if ( positionToArea( e->pos() ) != IconBorder && positionToArea( e->pos() ) != AnnotationBorder ) 01281 { 01282 QMouseEvent forward( QEvent::MouseButtonPress, 01283 QPoint( 0, e->y() ), e->button(), e->buttons(),e->modifiers() ); 01284 m_viewInternal->mousePressEvent( &forward ); 01285 } 01286 return e->accept(); 01287 } 01288 01289 QWidget::mousePressEvent(e); 01290 } 01291 01292 void KateIconBorder::showDelayedBlock(int line) 01293 { 01294 // save the line over which the mouse hovers 01295 // either we start the timer for delay, or we show the block immediately 01296 // if the smart range already exists 01297 m_nextHighlightBlock = line; 01298 if (!m_foldingRange) { 01299 if (!m_delayFoldingHlTimer.isActive()) { 01300 m_delayFoldingHlTimer.start(); 01301 } 01302 } else { 01303 showBlock(); 01304 } 01305 } 01306 01307 void KateIconBorder::showBlock() 01308 { 01309 if (m_nextHighlightBlock == m_currentBlockLine) return; 01310 m_currentBlockLine = m_nextHighlightBlock; 01311 01312 // get the new range, that should be highlighted 01313 KTextEditor::Range newRange = KTextEditor::Range::invalid(); 01314 KateCodeFoldingTree *tree = m_doc->foldingTree(); 01315 if (tree) { 01316 KateCodeFoldingNode *node = tree->findNodeForLine(m_currentBlockLine); 01317 KTextEditor::Cursor beg; 01318 KTextEditor::Cursor end; 01319 if (node != tree->rootNode () && node->getBegin(tree, &beg)) { 01320 if (node->getEnd(tree, &end)) 01321 newRange = KTextEditor::Range(beg, end); 01322 else 01323 newRange = KTextEditor::Range(beg, m_viewInternal->doc()->documentEnd()); 01324 } 01325 KateLineInfo info; 01326 tree->getLineInfo(&info, m_currentBlockLine); 01327 if ((info.startsVisibleBlock)){ 01328 node=tree->findNodeStartingAt(m_currentBlockLine); 01329 if (node) { 01330 if (node != tree->rootNode () && node->getBegin(tree, &beg) && node->getEnd(tree, &end)) { 01331 newRange = KTextEditor::Range(beg, end); 01332 } 01333 } 01334 } 01335 01336 } 01337 01338 if (newRange.isValid() && m_foldingRange && *m_foldingRange == newRange) { 01339 // new range equals the old one, nothing to do. 01340 return; 01341 } else { // the ranges differ, delete the old, if it exists 01342 delete m_foldingRange; 01343 m_foldingRange = 0; 01344 } 01345 01346 if (newRange.isValid()) { 01347 kDebug(13025) << "new folding hl-range:" << newRange; 01348 m_foldingRange = m_doc->newMovingRange(newRange, KTextEditor::MovingRange::ExpandRight); 01349 KTextEditor::Attribute::Ptr attr(new KTextEditor::Attribute()); 01350 attr->setBackground(foldingColor(0, m_currentBlockLine, false)); 01351 m_foldingRange->setView (m_view); 01352 // use z depth defined in moving ranges interface 01353 m_foldingRange->setZDepth (-100.0); 01354 m_foldingRange->setAttribute(attr); 01355 } 01356 } 01357 01358 void KateIconBorder::hideBlock() 01359 { 01360 if (m_delayFoldingHlTimer.isActive()) { 01361 m_delayFoldingHlTimer.stop(); 01362 } 01363 01364 m_nextHighlightBlock = -2; 01365 m_currentBlockLine = -1; 01366 delete m_foldingRange; 01367 m_foldingRange = 0; 01368 } 01369 01370 void KateIconBorder::leaveEvent(QEvent *event) 01371 { 01372 hideBlock(); 01373 removeAnnotationHovering(); 01374 01375 QWidget::leaveEvent(event); 01376 } 01377 01378 void KateIconBorder::mouseMoveEvent( QMouseEvent* e ) 01379 { 01380 const KateTextLayout& t = m_viewInternal->yToKateTextLayout(e->y()); 01381 if (t.isValid()) { 01382 if ( positionToArea( e->pos() ) == FoldingMarkers) showDelayedBlock(t.line()); 01383 else hideBlock(); 01384 if ( positionToArea( e->pos() ) == AnnotationBorder ) 01385 { 01386 KTextEditor::AnnotationModel *model = m_view->annotationModel() ? 01387 m_view->annotationModel() : m_doc->annotationModel(); 01388 if (model) 01389 { 01390 m_hoveredAnnotationText = model->data( t.line(), Qt::DisplayRole ).toString(); 01391 showAnnotationTooltip( t.line(), e->globalPos() ); 01392 QTimer::singleShot( 0, this, SLOT(update()) ); 01393 } 01394 } 01395 else 01396 { 01397 if( positionToArea( e->pos() ) == IconBorder ) 01398 m_doc->requestMarkTooltip( t.line(), e->globalPos() ); 01399 01400 m_hoveredAnnotationText.clear(); 01401 hideAnnotationTooltip(); 01402 QTimer::singleShot( 0, this, SLOT(update()) ); 01403 } 01404 if ( positionToArea( e->pos() ) != IconBorder ) 01405 { 01406 QPoint p = m_viewInternal->mapFromGlobal( e->globalPos() ); 01407 QMouseEvent forward( QEvent::MouseMove, p, e->button(), e->buttons(), e->modifiers() ); 01408 m_viewInternal->mouseMoveEvent( &forward ); 01409 } 01410 } 01411 else 01412 { 01413 // remove hovering if it's still there 01414 removeAnnotationHovering(); 01415 } 01416 01417 QWidget::mouseMoveEvent(e); 01418 } 01419 01420 void KateIconBorder::mouseReleaseEvent( QMouseEvent* e ) 01421 { 01422 int cursorOnLine = m_viewInternal->yToKateTextLayout(e->y()).line(); 01423 01424 if (cursorOnLine == m_lastClickedLine && 01425 cursorOnLine <= m_doc->lastLine() ) 01426 { 01427 BorderArea area = positionToArea( e->pos() ); 01428 if( area == IconBorder) { 01429 if (e->button() == Qt::LeftButton) { 01430 if( !m_doc->handleMarkClick(cursorOnLine) ) { 01431 KateViewConfig *config = m_view->config(); 01432 if( m_doc->editableMarks() & config->defaultMarkType() ) { 01433 if( m_doc->mark( cursorOnLine ) & config->defaultMarkType() ) 01434 m_doc->removeMark( cursorOnLine, config->defaultMarkType() ); 01435 else 01436 m_doc->addMark( cursorOnLine, config->defaultMarkType() ); 01437 } else if (config->allowMarkMenu()) { 01438 showMarkMenu( cursorOnLine, QCursor::pos() ); 01439 } 01440 } 01441 } 01442 else 01443 if (e->button() == Qt::RightButton) { 01444 showMarkMenu( cursorOnLine, QCursor::pos() ); 01445 } 01446 } 01447 01448 if ( area == FoldingMarkers) { 01449 KateLineInfo info; 01450 m_doc->lineInfo(&info,cursorOnLine); 01451 if ((info.startsVisibleBlock) || (info.startsInVisibleBlock)) { 01452 emit toggleRegionVisibility(cursorOnLine); 01453 } 01454 } 01455 01456 if ( area == AnnotationBorder ) { 01457 if( e->button() == Qt::LeftButton && KGlobalSettings::singleClick() ) { 01458 emit m_view->annotationActivated( m_view, cursorOnLine ); 01459 } else if ( e->button() == Qt::RightButton ) { 01460 showAnnotationMenu( cursorOnLine, e->globalPos() ); 01461 } 01462 } 01463 } 01464 01465 QMouseEvent forward( QEvent::MouseButtonRelease, 01466 QPoint( 0, e->y() ), e->button(), e->buttons(),e->modifiers() ); 01467 m_viewInternal->mouseReleaseEvent( &forward ); 01468 } 01469 01470 void KateIconBorder::mouseDoubleClickEvent( QMouseEvent* e ) 01471 { 01472 int cursorOnLine = m_viewInternal->yToKateTextLayout(e->y()).line(); 01473 01474 if (cursorOnLine == m_lastClickedLine && 01475 cursorOnLine <= m_doc->lastLine() ) 01476 { 01477 BorderArea area = positionToArea( e->pos() ); 01478 if( area == AnnotationBorder && !KGlobalSettings::singleClick() ) { 01479 emit m_view->annotationActivated( m_view, cursorOnLine ); 01480 } 01481 } 01482 QMouseEvent forward( QEvent::MouseButtonDblClick, 01483 QPoint( 0, e->y() ), e->button(), e->buttons(),e->modifiers() ); 01484 m_viewInternal->mouseDoubleClickEvent( &forward ); 01485 } 01486 01487 void KateIconBorder::showMarkMenu( uint line, const QPoint& pos ) 01488 { 01489 if( !m_view->config()->allowMarkMenu() ) 01490 return; 01491 01492 if( m_doc->handleMarkContextMenu( line, pos ) ) 01493 return; 01494 01495 KMenu markMenu; 01496 KMenu selectDefaultMark; 01497 01498 QVector<int> vec( 33 ); 01499 int i=1; 01500 01501 for( uint bit = 0; bit < 32; bit++ ) { 01502 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit); 01503 if( !(m_doc->editableMarks() & markType) ) 01504 continue; 01505 01506 QAction *mA; 01507 QAction *dMA; 01508 if( !m_doc->markDescription( markType ).isEmpty() ) { 01509 mA=markMenu.addAction( m_doc->markDescription( markType )); 01510 dMA=selectDefaultMark.addAction( m_doc->markDescription( markType )); 01511 } else { 01512 mA=markMenu.addAction( i18n("Mark Type %1", bit + 1 )); 01513 dMA=selectDefaultMark.addAction( i18n("Mark Type %1", bit + 1 )); 01514 } 01515 mA->setData(i); 01516 mA->setCheckable(true); 01517 dMA->setData(i+100); 01518 dMA->setCheckable(true); 01519 if( m_doc->mark( line ) & markType ) 01520 mA->setChecked(true ); 01521 01522 if( markType & KateViewConfig::global()->defaultMarkType() ) 01523 dMA->setChecked(true ); 01524 01525 vec[i++] = markType; 01526 } 01527 01528 if( markMenu.actions().count() == 0 ) 01529 return; 01530 01531 if( markMenu.actions().count() > 1 ) 01532 markMenu.addAction( i18n("Set Default Mark Type" ))->setMenu(&selectDefaultMark); 01533 01534 QAction *rA = markMenu.exec( pos ); 01535 if( !rA ) 01536 return; 01537 int result=rA->data().toInt(); 01538 if ( result > 100) 01539 { 01540 KateViewConfig::global()->setDefaultMarkType (vec[result-100]); 01541 // flush config, otherwise it isn't necessarily done 01542 KConfigGroup cg(KGlobal::config(), "Kate View Defaults"); 01543 KateViewConfig::global()->writeConfig(cg); 01544 } 01545 else 01546 { 01547 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes) vec[result]; 01548 if( m_doc->mark( line ) & markType ) { 01549 m_doc->removeMark( line, markType ); 01550 } else { 01551 m_doc->addMark( line, markType ); 01552 } 01553 } 01554 } 01555 01556 void KateIconBorder::showAnnotationTooltip( int line, const QPoint& pos ) 01557 { 01558 KTextEditor::AnnotationModel *model = m_view->annotationModel() ? 01559 m_view->annotationModel() : m_doc->annotationModel(); 01560 01561 if( model ) 01562 { 01563 QVariant data = model->data( line, Qt::ToolTipRole ); 01564 QString tip = data.toString(); 01565 if (!tip.isEmpty()) 01566 QToolTip::showText( pos, data.toString(), this ); 01567 } 01568 } 01569 01570 01571 int KateIconBorder::annotationLineWidth( int line ) 01572 { 01573 KTextEditor::AnnotationModel *model = m_view->annotationModel() ? 01574 m_view->annotationModel() : m_doc->annotationModel(); 01575 01576 if( model ) 01577 { 01578 QVariant data = model->data( line, Qt::DisplayRole ); 01579 return data.toString().length() * m_maxCharWidth + 8; 01580 } 01581 return 8; 01582 } 01583 01584 void KateIconBorder::updateAnnotationLine( int line ) 01585 { 01586 if( annotationLineWidth(line) > m_annotationBorderWidth ) 01587 { 01588 m_annotationBorderWidth = annotationLineWidth(line); 01589 updateGeometry(); 01590 01591 QTimer::singleShot( 0, this, SLOT(update()) ); 01592 } 01593 } 01594 01595 void KateIconBorder::showAnnotationMenu( int line, const QPoint& pos) 01596 { 01597 KMenu menu; 01598 QAction a(i18n("Disable Annotation Bar"), &menu); 01599 menu.addAction(&a); 01600 emit m_view->annotationContextMenuAboutToShow( m_view, &menu, line ); 01601 if (menu.exec(pos) == &a) 01602 m_view->setAnnotationBorderVisible(false); 01603 } 01604 01605 void KateIconBorder::hideAnnotationTooltip() 01606 { 01607 QToolTip::hideText(); 01608 } 01609 01610 void KateIconBorder::updateAnnotationBorderWidth( ) 01611 { 01612 m_annotationBorderWidth = 6; 01613 KTextEditor::AnnotationModel *model = m_view->annotationModel() ? 01614 m_view->annotationModel() : m_doc->annotationModel(); 01615 01616 if( model ) { 01617 for( int i = 0; i < m_view->doc()->lines(); i++ ) { 01618 int curwidth = annotationLineWidth( i ); 01619 if( curwidth > m_annotationBorderWidth ) 01620 m_annotationBorderWidth = curwidth; 01621 } 01622 } 01623 01624 updateGeometry(); 01625 01626 QTimer::singleShot( 0, this, SLOT(update()) ); 01627 } 01628 01629 01630 01631 void KateIconBorder::annotationModelChanged( KTextEditor::AnnotationModel * oldmodel, KTextEditor::AnnotationModel * newmodel ) 01632 { 01633 if( oldmodel ) 01634 { 01635 oldmodel->disconnect( this ); 01636 } 01637 if( newmodel ) 01638 { 01639 connect( newmodel, SIGNAL(reset()), this, SLOT(updateAnnotationBorderWidth()) ); 01640 connect( newmodel, SIGNAL(lineChanged( int )), this, SLOT(updateAnnotationLine( int )) ); 01641 } 01642 updateAnnotationBorderWidth(); 01643 } 01644 01645 //END KateIconBorder 01646 01647 //BEGIN KateViewEncodingAction 01648 // Acording to http://www.iana.org/assignments/ianacharset-mib 01649 // the default/unknown mib value is 2. 01650 #define MIB_DEFAULT 2 01651 01652 class KateViewEncodingAction::Private 01653 { 01654 public: 01655 Private(KateViewEncodingAction *parent) 01656 : q(parent), 01657 currentSubAction(0) 01658 { 01659 } 01660 01661 void init(); 01662 01663 void _k_subActionTriggered(QAction*); 01664 01665 KateViewEncodingAction *q; 01666 QAction *currentSubAction; 01667 }; 01668 01669 bool lessThanAction(KSelectAction *a, KSelectAction *b) 01670 { 01671 return a->text() < b->text(); 01672 } 01673 01674 void KateViewEncodingAction::Private::init() 01675 { 01676 QList<KSelectAction *> actions; 01677 01678 q->setToolBarMode(MenuMode); 01679 01680 int i; 01681 foreach(const QStringList &encodingsForScript, KGlobal::charsets()->encodingsByScript()) 01682 { 01683 KSelectAction* tmp = new KSelectAction(encodingsForScript.at(0),q); 01684 01685 for (i=1; i<encodingsForScript.size(); ++i) 01686 { 01687 tmp->addAction(encodingsForScript.at(i)); 01688 } 01689 q->connect(tmp,SIGNAL(triggered(QAction*)),q,SLOT(_k_subActionTriggered(QAction*))); 01690 //tmp->setCheckable(true); 01691 actions << tmp; 01692 } 01693 qSort(actions.begin(), actions.end(), lessThanAction); 01694 foreach (KSelectAction *action, actions) 01695 q->addAction(action); 01696 } 01697 01698 void KateViewEncodingAction::Private::_k_subActionTriggered(QAction *action) 01699 { 01700 if (currentSubAction==action) 01701 return; 01702 currentSubAction=action; 01703 bool ok = false; 01704 int mib = q->mibForName(action->text(), &ok); 01705 if (ok) 01706 { 01707 emit q->KSelectAction::triggered(action->text()); 01708 emit q->triggered(q->codecForMib(mib)); 01709 } 01710 } 01711 01712 KateViewEncodingAction::KateViewEncodingAction(KateDocument *_doc, KateView *_view, const QString& text, QObject *parent) 01713 : KSelectAction(text, parent), doc(_doc), view (_view), d(new Private(this)) 01714 { 01715 d->init(); 01716 01717 connect(menu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow())); 01718 connect(this,SIGNAL(triggered(const QString&)),this,SLOT(setEncoding(const QString&))); 01719 } 01720 01721 KateViewEncodingAction::~KateViewEncodingAction() 01722 { 01723 delete d; 01724 } 01725 01726 void KateViewEncodingAction::slotAboutToShow() 01727 { 01728 setCurrentCodec(doc->config()->encoding()); 01729 } 01730 01731 void KateViewEncodingAction::setEncoding (const QString &e) 01732 { 01733 doc->setEncoding(e); 01734 01735 view->reloadFile(); 01736 01737 } 01738 int KateViewEncodingAction::mibForName(const QString &codecName, bool *ok) const 01739 { 01740 // FIXME logic is good but code is ugly 01741 01742 bool success = false; 01743 int mib = MIB_DEFAULT; 01744 KCharsets *charsets = KGlobal::charsets(); 01745 01746 QTextCodec *codec = charsets->codecForName(codecName, success); 01747 if (!success) 01748 { 01749 // Maybe we got a description name instead 01750 codec = charsets->codecForName(charsets->encodingForName(codecName), success); 01751 } 01752 01753 if (codec) 01754 mib = codec->mibEnum(); 01755 01756 if (ok) 01757 *ok = success; 01758 01759 if (success) 01760 return mib; 01761 01762 kWarning() << "Invalid codec name: " << codecName; 01763 return MIB_DEFAULT; 01764 } 01765 01766 QTextCodec *KateViewEncodingAction::codecForMib(int mib) const 01767 { 01768 if (mib == MIB_DEFAULT) 01769 { 01770 // FIXME offer to change the default codec 01771 return QTextCodec::codecForLocale(); 01772 } 01773 else 01774 return QTextCodec::codecForMib(mib); 01775 } 01776 01777 QTextCodec *KateViewEncodingAction::currentCodec() const 01778 { 01779 return codecForMib(currentCodecMib()); 01780 } 01781 01782 bool KateViewEncodingAction::setCurrentCodec( QTextCodec *codec ) 01783 { 01784 disconnect(this,SIGNAL(triggered(const QString&)),this,SLOT(setEncoding(const QString&))); 01785 01786 int i,j; 01787 for (i=0;i<actions().size();++i) 01788 { 01789 if (actions().at(i)->menu()) 01790 { 01791 for (j=0;j<actions().at(i)->menu()->actions().size();++j) 01792 { 01793 if (!j && !actions().at(i)->menu()->actions().at(j)->data().isNull()) 01794 continue; 01795 if (actions().at(i)->menu()->actions().at(j)->isSeparator()) 01796 continue; 01797 01798 if (codec==KGlobal::charsets()->codecForName(actions().at(i)->menu()->actions().at(j)->text())) 01799 { 01800 d->currentSubAction=actions().at(i)->menu()->actions().at(j); 01801 d->currentSubAction->setChecked(true); 01802 } 01803 else 01804 actions().at(i)->menu()->actions().at(j)->setChecked (false); 01805 } 01806 } 01807 } 01808 01809 connect(this,SIGNAL(triggered(const QString&)),this,SLOT(setEncoding(const QString&))); 01810 return true; 01811 } 01812 01813 QString KateViewEncodingAction::currentCodecName() const 01814 { 01815 return d->currentSubAction->text(); 01816 } 01817 01818 bool KateViewEncodingAction::setCurrentCodec( const QString &codecName ) 01819 { 01820 return setCurrentCodec(KGlobal::charsets()->codecForName(codecName)); 01821 } 01822 01823 int KateViewEncodingAction::currentCodecMib() const 01824 { 01825 return mibForName(currentCodecName()); 01826 } 01827 01828 bool KateViewEncodingAction::setCurrentCodec( int mib ) 01829 { 01830 return setCurrentCodec(codecForMib(mib)); 01831 } 01832 //END KateViewEncodingAction 01833 01834 //BEGIN KateViewBar related classes 01835 01836 KateViewBarWidget::KateViewBarWidget (bool addCloseButton, QWidget *parent) 01837 : QWidget (parent) 01838 { 01839 QHBoxLayout *layout = new QHBoxLayout (this); 01840 01841 // NOTE: Here be cosmetics. 01842 layout->setMargin(0); 01843 01844 // hide button 01845 if (addCloseButton) { 01846 QToolButton *hideButton = new QToolButton(this); 01847 hideButton->setAutoRaise(true); 01848 hideButton->setIcon(KIcon("dialog-close")); 01849 connect(hideButton, SIGNAL(clicked()), SIGNAL(hideMe())); 01850 layout->addWidget(hideButton); 01851 layout->setAlignment( hideButton, Qt::AlignLeft|Qt::AlignTop ); 01852 } 01853 01854 // widget to be used as parent for the real content 01855 m_centralWidget = new QWidget (this); 01856 layout->addWidget(m_centralWidget); 01857 01858 setLayout(layout); 01859 setFocusProxy(m_centralWidget); 01860 } 01861 01862 01863 KateViewBar::KateViewBar (bool external,KTextEditor::ViewBarContainer::Position pos,QWidget *parent, KateView *view) 01864 : QWidget (parent), m_external(external), m_pos(pos),m_view (view), m_permanentBarWidget(0) 01865 01866 { 01867 m_layout = new QVBoxLayout(this); 01868 m_stack = new QStackedWidget(this); 01869 m_layout->addWidget(m_stack); 01870 m_layout->setMargin(0); 01871 01872 m_stack->hide(); 01873 hide (); 01874 } 01875 01876 void KateViewBar::addBarWidget (KateViewBarWidget *newBarWidget) 01877 { 01878 if (hasBarWidget(newBarWidget)) { 01879 kDebug(13025) << "this bar widget is already added"; 01880 return; 01881 } 01882 // add new widget, invisible... 01883 newBarWidget->hide(); 01884 m_stack->addWidget (newBarWidget); 01885 connect(newBarWidget, SIGNAL(hideMe()), SLOT(hideCurrentBarWidget())); 01886 01887 kDebug(13025)<<"add barwidget " << newBarWidget; 01888 } 01889 01890 void KateViewBar::removeBarWidget (KateViewBarWidget *barWidget) 01891 { 01892 m_stack->removeWidget(barWidget); 01893 } 01894 01895 void KateViewBar::addPermanentBarWidget (KateViewBarWidget *barWidget) 01896 { 01897 // remove old widget from layout (if any) 01898 if (m_permanentBarWidget) { 01899 m_permanentBarWidget->hide(); 01900 m_layout->removeWidget(m_permanentBarWidget); 01901 } 01902 01903 m_layout->addWidget(barWidget, 0, Qt::AlignBottom); 01904 m_permanentBarWidget = barWidget; 01905 m_permanentBarWidget->show(); 01906 01907 setViewBarVisible(true); 01908 } 01909 01910 void KateViewBar::removePermanentBarWidget (KateViewBarWidget *barWidget) 01911 { 01912 if (m_permanentBarWidget != barWidget) { 01913 kDebug(13025) << "no such permanent widget exists in bar"; 01914 return; 01915 } 01916 01917 if (!m_permanentBarWidget) 01918 return; 01919 01920 m_permanentBarWidget->hide(); 01921 m_layout->removeWidget(m_permanentBarWidget); 01922 m_permanentBarWidget = 0; 01923 01924 if (!m_stack->isVisible()) { 01925 setViewBarVisible(false); 01926 } 01927 } 01928 01929 bool KateViewBar::hasPermanentWidget (KateViewBarWidget *barWidget ) const 01930 { 01931 return (m_permanentBarWidget == barWidget); 01932 } 01933 01934 void KateViewBar::showBarWidget (KateViewBarWidget *barWidget) 01935 { 01936 Q_ASSERT(barWidget != 0); 01937 01938 // raise correct widget 01939 m_stack->setCurrentWidget (barWidget); 01940 barWidget->show(); 01941 barWidget->setFocus(Qt::ShortcutFocusReason); 01942 m_stack->show(); 01943 01944 // if we have any permanent widget, bar is always visible, 01945 // no need to show it 01946 if (!m_permanentBarWidget) { 01947 setViewBarVisible(true); 01948 } 01949 } 01950 01951 bool KateViewBar::hasBarWidget(KateViewBarWidget* barWidget) const 01952 { 01953 return m_stack->indexOf(barWidget) != -1; 01954 } 01955 01956 void KateViewBar::hideCurrentBarWidget () 01957 { 01958 KateViewBarWidget *current=qobject_cast<KateViewBarWidget*>(m_stack->currentWidget()); 01959 if (current) { 01960 current->closed(); 01961 } 01962 m_stack->hide(); 01963 01964 // if we have any permanent widget, bar is always visible, 01965 // no need to hide it 01966 if (!m_permanentBarWidget) { 01967 setViewBarVisible(false); 01968 } 01969 01970 m_view->setFocus(); 01971 kDebug(13025)<<"hide barwidget"; 01972 } 01973 01974 void KateViewBar::setViewBarVisible (bool visible) 01975 { 01976 if (m_external) { 01977 KTextEditor::ViewBarContainer *viewBarContainer=qobject_cast<KTextEditor::ViewBarContainer*>( KateGlobal::self()->container() ); 01978 if (viewBarContainer) { 01979 if (visible) { 01980 viewBarContainer->showViewBarForView(m_view,m_pos); 01981 } else { 01982 viewBarContainer->hideViewBarForView(m_view,m_pos); 01983 } 01984 } 01985 } else { 01986 setVisible (visible); 01987 } 01988 } 01989 01990 void KateViewBar::keyPressEvent(QKeyEvent* event) 01991 { 01992 if (event->key() == Qt::Key_Escape) { 01993 hideCurrentBarWidget(); 01994 return; 01995 } 01996 QWidget::keyPressEvent(event); 01997 01998 } 01999 02000 void KateViewBar::hideEvent(QHideEvent* event) 02001 { 02002 Q_UNUSED(event); 02003 // if (!event->spontaneous()) 02004 // m_view->setFocus(); 02005 } 02006 02007 //END KateViewBar related classes 02008 02009 #include "kateviewhelpers.moc" 02010 02011 // kate: space-indent on; indent-width 2; replace-tabs on; 02012
KDE 4.6 API Reference