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