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