Beispiel #1
0
bool PythonCodeCompletionModel::shouldStartCompletion(KTextEditor::View* view, const QString& inserted,
                                                bool userInsertion, const KTextEditor::Cursor& position)
{
    QList<QString> words;
    words << "for" << "raise" << "except" << "in";
    foreach ( const QString& word, words ) {
        if ( view->document()->line(position.line()).mid(0, position.column()).endsWith(word + " ") ) {
            return true;
        }
    }
    // shebang / encoding lines
    if ( view->document()->line(position.line()).mid(0, position.column()).endsWith("#") && 
         position.line() < 2 )
    {
        return true;
    }

    // we're probably dealing with string formatting completion
    // is there any other case where this condition is true?
    if ( ! userInsertion && inserted.startsWith('{') ) {
        return true;
    }

    return KDevelop::CodeCompletionModel::shouldStartCompletion(view, inserted, userInsertion, position);
}
Beispiel #2
0
/**
 * This returns the view line upon which realCursor is situated.
 * The view line is the number of lines in the view from the first line
 * The supplied cursor should be in real lines.
 */
int KateLayoutCache::viewLine(const KTextEditor::Cursor& realCursor)
{
  if (realCursor.column() <= 0 || realCursor.line() < 0) return 0;

  KateLineLayoutPtr thisLine = line(realCursor.line());

  for (int i = 0; i < thisLine->viewLineCount(); ++i) {
    const KateTextLayout& l = thisLine->viewLine(i);
    if (realCursor.column() >= l.startCol() && realCursor.column() < l.endCol())
      return i;
  }

  return thisLine->viewLineCount() - 1;
}
/**
 * Initiate completion when there is \c #include on a line (\c m_range
 * in a result of \c parseIncludeDirective() not empty -- i.e. there is some file present)
 * and cursor placed within that range... despite of completeness of the whole line.
 */
bool IncludeHelperCompletionModel::shouldStartCompletion(
    KTextEditor::View* view
  , const QString& inserted_text
  , bool user_insertion
  , const KTextEditor::Cursor& position
  )
{
    kDebug(DEBUG_AREA) << "position=" << position << ", inserted_text=" << inserted_text << ", ui=" << user_insertion;

    m_should_complete = false;
    auto* doc = view->document();                           // get current document
    auto line = doc->line(position.line());                 // get current line
    auto* iface = qobject_cast<KTextEditor::HighlightInterface*>(doc);
    // Do nothing if no highlighting interface or not suitable document or
    // a place within it... (we won't to complete smth in non C++ files or comments for example)
    if (!iface || !isSuitableDocumentAndHighlighting(doc->mimeType(), iface->highlightingModeAt(position)))
        return m_should_complete;

    // Try to parse it...
    auto r = parseIncludeDirective(line, false);
    m_should_complete = r.m_range.isValid();
    if (m_should_complete)
    {
        kDebug(DEBUG_AREA) << "range=" << r.m_range;
        m_should_complete = position.column() >= r.m_range.start().column()
          && position.column() <= r.m_range.end().column();
        if (m_should_complete)
        {
            m_closer = r.close_char();
            kDebug(DEBUG_AREA) << "closer=" << m_closer;
        }
    }
    else if (position.column() == line.length())
    {
        auto text = tryToCompleteIncludeDirective(line.mid(0, position.column()).trimmed());
        m_should_complete = !text.isEmpty();
        if (m_should_complete)
        {
            /// \todo Hardcoded angle bracket! Better to check what file was selected
            /// (from system path or session specific) and replace it accordingly...
            text += QLatin1String(" <");
            auto start = position;
            start.setColumn(0);
            auto range = KTextEditor::Range{start, position};
            view->document()->replaceText(range, text);
        }
    }
    return m_should_complete;
}
Beispiel #4
0
void TextCursor::setPosition(const KTextEditor::Cursor& position, bool init)
{
  // any change or init? else do nothing
  if (!init && position.line() == line() && position.column() == m_column)
    return;

  // remove cursor from old block in any case
  if (m_block)
    m_block->removeCursor (this);

  // first: validate the line and column, else invalid
  if (position.column() < 0 || position.line () < 0 || position.line () >= m_buffer.lines ()) {
    if (!m_range)
      m_buffer.m_invalidCursors.insert (this);
    m_block = 0;
    m_line = m_column = -1;
    return;
  }

  // else, find block
  TextBlock *block = m_buffer.blockForIndex (m_buffer.blockForLine (position.line()));
  Q_ASSERT(block);

  // get line
  TextLine textLine = block->line (position.line());

#if 0 // this is no good idea, smart cursors don't do that, too, for non-wrapping cursors
  // now, validate column, else stay invalid
  if (position.column() > textLine->text().size()) {
    if (!m_range)
      m_buffer.m_invalidCursors.insert (this);
    m_block = 0;
    m_line = m_column = -1;
    return;
  }
#endif

  // if cursor was invalid before, remove it from invalid cursor list
  if (!m_range && !m_block && !init) {
    Q_ASSERT(m_buffer.m_invalidCursors.contains (this));
    m_buffer.m_invalidCursors.remove (this);
  }

  // else: valid cursor
  m_block = block;
  m_line = position.line () - m_block->startLine ();
  m_column = position.column ();
  m_block->insertCursor (this);
}
Beispiel #5
0
	QString Help::getKeyword(KTextEditor::View *view)
	{
		if(!view) {
			return QString();
		}

		// get current position
		int row, col, col1, col2;
		QString word;
		KTextEditor::Document *doc = view->document();
		KTextEditor::Cursor cursor = view->cursorPosition();
		row = cursor.line();
		col = cursor.column();

		if (m_edit->getCurrentWord(doc, row, col, KileDocument::EditorExtension::smTex, word, col1, col2)) {
		   // There is no starred keyword in the references. So if     // dani 04.08.2004
			// we find one, we better try the unstarred keyword.
			if(word.right(1) == "*") {
				return word.left(word.length() - 1);
			}
			else {
				return word;
			}
		}
		else {
			return QString();
		}
	}
Beispiel #6
0
int KateLayoutCache::displayViewLine(const KTextEditor::Cursor& virtualCursor, bool limitToVisible)
{
  KTextEditor::Cursor work = viewCacheStart();
  
  // only try this with valid lines!
  if (work.isValid())
    work.setLine(m_renderer->folding().lineToVisibleLine(work.line()));

  if (!work.isValid())
    return virtualCursor.line();

  int limit = m_textLayouts.count();

  // Efficient non-word-wrapped path
  if (!m_renderer->view()->dynWordWrap()) {
    int ret = virtualCursor.line() - work.line();
    if (limitToVisible && (ret < 0 || ret > limit))
      return -1;
    else
      return ret;
  }

  if (work == virtualCursor) {
    return 0;
  }

  int ret = -(int)viewLine(viewCacheStart());
  bool forwards = (work < virtualCursor);

  // FIXME switch to using ranges? faster?
  if (forwards) {
    while (work.line() != virtualCursor.line()) {
      ret += viewLineCount(m_renderer->folding().visibleLineToLine(work.line()));
      work.setLine(work.line() + 1);
      if (limitToVisible && ret > limit)
        return -1;
    }
  } else {
    while (work.line() != virtualCursor.line()) {
      work.setLine(work.line() - 1);
      ret -= viewLineCount(m_renderer->folding().visibleLineToLine(work.line()));
      if (limitToVisible && ret < 0)
        return -1;
    }
  }

  // final difference
  KTextEditor::Cursor realCursor = virtualCursor;
  realCursor.setLine(m_renderer->folding().visibleLineToLine(realCursor.line()));
  if (realCursor.column() == -1) realCursor.setColumn(m_renderer->doc()->lineLength(realCursor.line()));
  ret += viewLine(realCursor);

  if (limitToVisible && (ret < 0 || ret > limit))
    return -1;

  return ret;
}
Beispiel #7
0
void TextHistory::wrapLine(const KTextEditor::Cursor &position)
{
    // create and add new entry
    Entry entry;
    entry.type = Entry::WrapLine;
    entry.line = position.line();
    entry.column = position.column();
    addEntry(entry);
}
Beispiel #8
0
void RangeTest::testCursorStringConversion()
{
    using KTextEditor::Cursor;

    KTextEditor::Cursor c;
    QCOMPARE(c.line(), 0);
    QCOMPARE(c.column(), 0);
    QCOMPARE(c.toString(), QStringLiteral("(0, 0)"));
    c = Cursor::fromString(QStringLiteral("(0, 0)"));
    QCOMPARE(c.toString(), QStringLiteral("(0, 0)"));
    c = Cursor::fromString(QStringLiteral("(0,0)"));
    QCOMPARE(c.toString(), QStringLiteral("(0, 0)"));

    c.setPosition(-1, -1);
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));
    c = Cursor::fromString(QStringLiteral("(-1, -1)"));
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));
    c = Cursor::fromString(QStringLiteral("(-1,-1)"));
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));

    c.setPosition(12, 42);
    QCOMPARE(c.toString(), QStringLiteral("(12, 42)"));
    c = Cursor::fromString(QStringLiteral("(12, 42)"));
    QCOMPARE(c.toString(), QStringLiteral("(12, 42)"));
    c = Cursor::fromString(QStringLiteral("( 12,42)"));
    QCOMPARE(c.toString(), QStringLiteral("(12, 42)"));

    c.setPosition(12, 42);
    QCOMPARE(c.toString(), QStringLiteral("(12, 42)"));
    c = Cursor::fromString(QStringLiteral("(12, 42)"));
    QCOMPARE(c.toString(), QStringLiteral("(12, 42)"));

    c.setPosition(-12, 42);
    QCOMPARE(c.toString(), QStringLiteral("(-12, 42)"));
    c = Cursor::fromString(QStringLiteral("(-12, 42)"));
    QCOMPARE(c.toString(), QStringLiteral("(-12, 42)"));
    c = Cursor::fromString(QStringLiteral("(-12, +42)"));
    QCOMPARE(c.toString(), QStringLiteral("(-12, 42)"));
    c = Cursor::fromString(QStringLiteral("( -12 ,  +42)"));
    QCOMPARE(c.toString(), QStringLiteral("(-12, 42)"));
    c = Cursor::fromString(QStringLiteral("(-12 , 42 )"));
    QCOMPARE(c.toString(), QStringLiteral("(-12, 42)"));

    // test invalid input
    c = Cursor::fromString(QStringLiteral("( - 12 ,  + 42)"));
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));
    c = Cursor::fromString(QStringLiteral("(, 42)"));
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));
    c = Cursor::fromString(QStringLiteral("(-, -)"));
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));
    c = Cursor::fromString(QStringLiteral("(-, -)"));
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));
    c = Cursor::fromString(QStringLiteral("(-x,y)"));
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));
    c = Cursor::fromString(QStringLiteral("(-3,-2y)"));
    QCOMPARE(c.toString(), QStringLiteral("(-1, -1)"));
}
Beispiel #9
0
unsigned int KDocumentTextBuffer::cursorToOffset_kte( const KTextEditor::Cursor &cursor )
{
    unsigned int offset = 0;
    for( int i = 0; i < cursor.line(); i++ ) {
        offset += countUnicodeCharacters(kDocument()->line(i)) + 1; // Add newline
    }
    offset += countUnicodeCharacters(kDocument()->line(cursor.line()).left(cursor.column()));
    return offset;
}
Beispiel #10
0
KTextEditor::Cursor KDocumentTextBuffer::offsetRelativeTo_kte(const KTextEditor::Cursor& cursor, unsigned int offset)
{
    int lineno = cursor.line();
    const QString& firstLine = kDocument()->line(lineno).mid(cursor.column());
    unsigned int remaining = offset;
    int surrogates = surrogatesForCodePoints(firstLine, remaining);
    while ( remaining > 0 ) {
        remaining -= 1; // for the newline character
        lineno += 1;
        if ( remaining == 0 ) {
            surrogates = 0;
            break;
        }
        const QString& line = kDocument()->line(lineno);
        Q_ASSERT( lineno < kDocument()->lines() );
        surrogates = surrogatesForCodePoints(line, remaining);
    }
    return KTextEditor::Cursor(lineno, lineno == cursor.line() ? cursor.column() + surrogates : surrogates);
}
Recorder::Recorder(KTextEditor::View *view, Manager *manager) : QObject(view), m_manager(manager), m_view(view)
{
	connect(m_manager, SIGNAL(watchedKeySequencesChanged()), this, SLOT(reloadWatchedKeySequences()));
	connect(this, SIGNAL(detectedTypedKeySequence(const QString&)), m_manager, SLOT(keySequenceTyped(const QString&)));
	KTextEditor::Cursor cursor = m_view->cursorPosition();
	m_oldLine = cursor.line();
	m_oldCol = cursor.column();

	reloadWatchedKeySequences();
}
Beispiel #12
0
void SwapFile::insertText (const KTextEditor::Cursor &position, const QString &text)
{
  // skip if not open
  if (!m_swapfile.isOpen ())
    return;
  
  // format: qint8, int, int, bytearray
  m_stream << EA_InsertText << position.line() << position.column() << text.toUtf8 ();

  m_needSync = true;
}
Beispiel #13
0
void SwapFile::wrapLine (const KTextEditor::Cursor &position)
{
  // skip if not open
  if (!m_swapfile.isOpen ())
    return;
  
  // format: qint8, int, int
  m_stream << EA_WrapLine << position.line() << position.column();

  m_needSync = true;
}
Beispiel #14
0
void TextHistory::insertText(const KTextEditor::Cursor &position, int length, int oldLineLength)
{
    // create and add new entry
    Entry entry;
    entry.type = Entry::InsertText;
    entry.line = position.line();
    entry.column = position.column();
    entry.length = length;
    entry.oldLineLength = oldLineLength;
    addEntry(entry);
}
// Return the range containing the word left of the cursor
KTextEditor::Range KateNewCompletionModel::completionRange(KTextEditor::View* view, const KTextEditor::Cursor &position)
{
  int line = position.line();
  int col = position.column();

  KTextEditor::Document *doc = view->document();

  // ktuan java case: new List<Integer>
  // yieldXXX, Ent::load('XXX, genXXX, getXXX
  {
    QString text = view->document()->line(position.line()).left(position.column());
    const static QRegExp ktuan_new_class("((new \\w*)|(gen\\w*)|(get\\w*))$");
    int pos = ktuan_new_class.indexIn(text);
    if (pos >= 0) {
      return KTextEditor::Range( KTextEditor::Cursor( line, pos ), position );
    }
  }

  return KTextEditor::Range( KTextEditor::Cursor( line, col ), position );
}
Beispiel #16
0
// Take the given QML line and check if it's a line of the form foo.bar: value.
// Return ranges for the key and the value.
const QPair<KTextEditor::Range, KTextEditor::Range> parseProperty(const QString& line, const KTextEditor::Cursor& position) {
    QStringList items = line.split(';');
    QString matchingItem;
    int col_offset = -1;
    // This is to also support FooAnimation { foo: bar; baz: bang; duration: 200 }
    // or similar
    foreach ( const QString& item, items ) {
        col_offset += item.size() + 1;
        if ( position.column() < col_offset ) {
            matchingItem = item;
            break;
        }
    }
bool KateNewCompletionModel::shouldStartCompletion(KTextEditor::View* view, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor &position)
{
    if (!userInsertion) return false;
    if(insertedText.isEmpty())
        return false;

    KateView *v = qobject_cast<KateView*> (view);

    QString text = view->document()->line(position.line()).left(position.column());
    static const QRegExp ktuan_new_class("((new \\w*)|(gen\\w*)|(get\\w*))$");
    if (ktuan_new_class.indexIn(text) >= 0) return true;
    return false;
}
Beispiel #18
0
// Return the range containing the word left of the cursor
KTextEditor::Range KateWordCompletionModel::completionRange(KTextEditor::View* view, const KTextEditor::Cursor &position)
{
  int line = position.line();
  int col = position.column();

  KTextEditor::Document *doc = view->document();
  while ( col > 0 )
  {
    QChar c = ( doc->character( KTextEditor::Cursor( line, col-1 ) ) );
    if ( c.isLetterOrNumber() || c.isMark() || c == '_' )
    {
      col--;
      continue;
    }

    break;
  }

  return KTextEditor::Range( KTextEditor::Cursor( line, col ), position );
}
bool KateWordCompletionModel::shouldStartCompletion(KTextEditor::View* view, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor &position)
{
    if (!userInsertion) return false;
    if(insertedText.isEmpty())
        return false;

    KateView *v = qobject_cast<KateView*> (view);

    QString text = view->document()->line(position.line()).left(position.column());
    uint check=v->config()->wordCompletionMinimalWordLength();
    if (check<=0) return true;
    int start=text.length();
    int end=text.length()-check;
    if (end<0) return false;
    for (int i=start-1;i>=end;i--) {
      QChar c=text.at(i);
      if (! (c.isLetter() || (c.isNumber()) || c=='_') ) return false;
    }
    return true;
}
QString VariableController::expressionUnderCursor(KTextEditor::Document* doc, const KTextEditor::Cursor& cursor)
{
    QString line = doc->line(cursor.line());
    int index = cursor.column();
    QChar c = line[index];
    if (!c.isLetterOrNumber() && c != '_' && c != '$')
        return QString();

    int start = Utils::expressionAt(line, index);
    int end = index;
    for (; end < line.size(); ++end) {
        QChar c = line[end];
        if (!(c.isLetterOrNumber() || c == '_' || c == '$'))
            break;
    }
    if (!(start < end))
        return QString();

    QString expression(line.mid(start, end-start));
    expression = expression.trimmed();
    return expression;
}
bool Recorder::eventFilter(QObject* /* o */, QEvent *e)
{
	if (e->type() == QEvent::KeyPress) {
		QKeyEvent *keyEvent = (QKeyEvent*)(e);
		int curLine, curCol;
		KTextEditor::Cursor cursor = m_view->cursorPosition();
		curLine = cursor.line();
		curCol = cursor.column();
		if(curLine != m_oldLine || m_oldCol+1 != curCol) {
			m_typedSequence.clear();
			m_oldLine = curLine;
			m_oldCol = curCol;
		}
		else {
			++m_oldCol;
		}
		m_typedSequence += keyEvent->text();
		if(m_typedSequence.length() == m_maxSequenceLength + 1) {
			m_typedSequence = m_typedSequence.mid(1, m_typedSequence.length() - 1);
		}
		return seekForKeySequence(m_typedSequence);
	}
	return false;
}
Beispiel #22
0
void KateLayoutCache::updateViewCache(const KTextEditor::Cursor& startPos, int newViewLineCount, int viewLinesScrolled)
{
  //kDebug( 13033 ) << startPos << " nvlc " << newViewLineCount << " vls " << viewLinesScrolled;

  int oldViewLineCount = m_textLayouts.count();
  if (newViewLineCount == -1)
    newViewLineCount = oldViewLineCount;

  enableLayoutCache = true;

  int realLine;
  if (newViewLineCount == -1)
    realLine = m_renderer->folding().visibleLineToLine(m_renderer->folding().lineToVisibleLine(startPos.line()));
  else
    realLine = m_renderer->folding().visibleLineToLine(startPos.line());
  int _viewLine = 0;

  if (wrap()) {
    // TODO check these assumptions are ok... probably they don't give much speedup anyway?
    if (startPos == m_startPos && m_textLayouts.count()) {
      _viewLine = m_textLayouts.first().viewLine();

    } else if (viewLinesScrolled > 0 && viewLinesScrolled < m_textLayouts.count()) {
      _viewLine = m_textLayouts[viewLinesScrolled].viewLine();

    } else {
      KateLineLayoutPtr l = line(realLine);
      if (l) {
        Q_ASSERT(l->isValid());
        Q_ASSERT(l->length() >= startPos.column() || m_renderer->view()->wrapCursor());

        for (; _viewLine < l->viewLineCount(); ++_viewLine) {
          const KateTextLayout& t = l->viewLine(_viewLine);
          if (t.startCol() >= startPos.column() || _viewLine == l->viewLineCount() - 1)
            goto foundViewLine;
        }

        // FIXME FIXME need to calculate past-end-of-line position here...
        Q_ASSERT(false);

        foundViewLine:
        Q_ASSERT(true);
      }
    }
  }

  m_startPos = startPos;

  // Move the text layouts if we've just scrolled...
  if (viewLinesScrolled != 0) {
    // loop backwards if we've just scrolled up...
    bool forwards = viewLinesScrolled >= 0 ? true : false;
    for (int z = forwards ? 0 : m_textLayouts.count() - 1; forwards ? (z < m_textLayouts.count()) : (z >= 0); forwards ? z++ : z--) {
      int oldZ = z + viewLinesScrolled;
      if (oldZ >= 0 && oldZ < m_textLayouts.count())
        m_textLayouts[z] = m_textLayouts[oldZ];
    }
  }

  // Resize functionality
  if (newViewLineCount > oldViewLineCount) {
    m_textLayouts.reserve(newViewLineCount);

  } else if (newViewLineCount < oldViewLineCount) {
    /* FIXME reintroduce... check we're not missing any
    int lastLine = m_textLayouts[newSize - 1].line();
    for (int i = oldSize; i < newSize; i++) {
      const KateTextLayout& layout = m_textLayouts[i];
      if (layout.line() > lastLine && !layout.viewLine())
        layout.kateLineLayout()->layout()->setCacheEnabled(false);
    }*/
    m_textLayouts.resize(newViewLineCount);
  }

  KateLineLayoutPtr l = line(realLine);
  for (int i = 0; i < newViewLineCount; ++i) {
    if (!l) {
      if (i < m_textLayouts.count()) {
        if (m_textLayouts[i].isValid())
          m_textLayouts[i] = KateTextLayout::invalid();
      } else {
        m_textLayouts.append(KateTextLayout::invalid());
      }
      continue;
    }

    Q_ASSERT(l->isValid());
    Q_ASSERT(_viewLine < l->viewLineCount());

    if (i < m_textLayouts.count()) {
      bool dirty = false;
      if (m_textLayouts[i].line() != realLine || m_textLayouts[i].viewLine() != _viewLine || (!m_textLayouts[i].isValid() && l->viewLine(_viewLine).isValid()))
        dirty = true;
      m_textLayouts[i] = l->viewLine(_viewLine);
      if (dirty)
        m_textLayouts[i].setDirty(true);

    } else {
      m_textLayouts.append(l->viewLine(_viewLine));
    }

    //kDebug( 13033 ) << "Laid out line " << realLine << " (" << l << "), viewLine " << _viewLine << " (" << m_textLayouts[i].kateLineLayout().data() << ")";
    //m_textLayouts[i].debugOutput();

    _viewLine++;

    if (_viewLine > l->viewLineCount() - 1) {
      int virtualLine = l->virtualLine() + 1;
      realLine = m_renderer->folding().visibleLineToLine(virtualLine);
      _viewLine = 0;
      if (realLine < m_renderer->doc()->lines()) {
        l = line(realLine, virtualLine);
      } else {
        l = 0;
      }
    }
  }

  enableLayoutCache = false;
}
Beispiel #23
0
/** Conversion function from KTextEditor::Cursor to QtScript cursor */
static QScriptValue cursorToScriptValue(QScriptEngine *engine, const KTextEditor::Cursor &cursor)
{
  QString code = QString("new Cursor(%1, %2);").arg(cursor.line())
                                               .arg(cursor.column());
  return engine->evaluate(code);
}
Beispiel #24
0
int KileScriptDocument::nextNonSpaceColumn(const KTextEditor::Cursor& cursor)
{
    return nextNonSpaceColumn(cursor.line(), cursor.column());
}
Beispiel #25
0
bool KileScriptDocument::matchesAt(const KTextEditor::Cursor& cursor, const QString &s)
{
    QString textline = m_document->line(cursor.line());
    return textline.mid(cursor.column()).startsWith(s);
}
Beispiel #26
0
bool KileScriptDocument::truncate(const KTextEditor::Cursor& cursor)
{
    return truncate(cursor.line(), cursor.column());
}
Beispiel #27
0
QList<QTextLayout::FormatRange> KateRenderer::decorationsForLine( const Kate::TextLine& textLine, int line, bool selectionsOnly, KateRenderRange* completionHighlight, bool completionSelected ) const
{
  QList<QTextLayout::FormatRange> newHighlight;

  // Don't compute the highlighting if there isn't going to be any highlighting
  QList<Kate::TextRange *> rangesWithAttributes = m_doc->buffer().rangesForLine (line, m_printerFriendly ? 0 : m_view, true);
  if (selectionsOnly || textLine->attributesList().count() || rangesWithAttributes.count()) {
    RenderRangeList renderRanges;

    // Add the inbuilt highlighting to the list
    NormalRenderRange* inbuiltHighlight = new NormalRenderRange();
    const QVector<Kate::TextLineData::Attribute> &al = textLine->attributesList();
    for (int i = 0; i < al.count(); ++i)
      if (al[i].length > 0 && al[i].attributeValue > 0)
        inbuiltHighlight->addRange(new KTextEditor::Range(KTextEditor::Cursor(line, al[i].offset), al[i].length), specificAttribute(al[i].attributeValue));
    renderRanges.append(inbuiltHighlight);

    if (!completionHighlight) {
      // check for dynamic hl stuff
      const QSet<Kate::TextRange *> *rangesMouseIn = m_view ? m_view->rangesMouseIn () : 0;
      const QSet<Kate::TextRange *> *rangesCaretIn = m_view ? m_view->rangesCaretIn () : 0;
      bool anyDynamicHlsActive = m_view && (!rangesMouseIn->empty() || !rangesCaretIn->empty());

      // sort all ranges, we want that the most specific ranges win during rendering, multiple equal ranges are kind of random, still better than old smart rangs behavior ;)
      qSort (rangesWithAttributes.begin(), rangesWithAttributes.end(), rangeLessThanForRenderer);

      // loop over all ranges
      for (int i = 0; i < rangesWithAttributes.size(); ++i) {
        // real range
        Kate::TextRange *kateRange = rangesWithAttributes[i];

        // calculate attribute, default: normal attribute
        KTextEditor::Attribute::Ptr attribute = kateRange->attribute();
        if (anyDynamicHlsActive) {
          // check mouse in
          if (KTextEditor::Attribute::Ptr attributeMouseIn = attribute->dynamicAttribute (KTextEditor::Attribute::ActivateMouseIn)) {
            if (rangesMouseIn->contains (kateRange))
              attribute = attributeMouseIn;
          }

          // check caret in
          if (KTextEditor::Attribute::Ptr attributeCaretIn = attribute->dynamicAttribute (KTextEditor::Attribute::ActivateCaretIn)) {
            if (rangesCaretIn->contains (kateRange))
              attribute = attributeCaretIn;
          }
        }

        // span range
        NormalRenderRange *additionaHl = new NormalRenderRange();
        additionaHl->addRange(new KTextEditor::Range (*kateRange), attribute);
        renderRanges.append(additionaHl);
      }
    } else {
      // Add the code completion arbitrary highlight to the list
      renderRanges.append(completionHighlight);
    }

    // Add selection highlighting if we're creating the selection decorations
    if ((selectionsOnly && showSelections() && m_view->selection()) || (completionHighlight && completionSelected) || m_view->blockSelection()) {
      NormalRenderRange* selectionHighlight = new NormalRenderRange();

      // Set up the selection background attribute TODO: move this elsewhere, eg. into the config?
      static KTextEditor::Attribute::Ptr backgroundAttribute;
      if (!backgroundAttribute)
        backgroundAttribute = KTextEditor::Attribute::Ptr(new KTextEditor::Attribute());

      backgroundAttribute->setBackground(config()->selectionColor());
      backgroundAttribute->setForeground(attribute(KTextEditor::HighlightInterface::dsNormal)->selectedForeground().color());

      // Create a range for the current selection
      if (completionHighlight && completionSelected)
        selectionHighlight->addRange(new KTextEditor::Range(line, 0, line + 1, 0), backgroundAttribute);
      else
        if(m_view->blockSelection() && m_view->selectionRange().overlapsLine(line))
          selectionHighlight->addRange(new KTextEditor::Range(m_doc->rangeOnLine(m_view->selectionRange(), line)), backgroundAttribute);
        else {
          selectionHighlight->addRange(new KTextEditor::Range(m_view->selectionRange()), backgroundAttribute);
        }

      renderRanges.append(selectionHighlight);
    // highlighting for the vi visual modes
    }

    KTextEditor::Cursor currentPosition, endPosition;

    // Calculate the range which we need to iterate in order to get the highlighting for just this line
    if (selectionsOnly) {
      if(m_view->blockSelection()) {
        KTextEditor::Range subRange = m_doc->rangeOnLine(m_view->selectionRange(), line);
        currentPosition = subRange.start();
        endPosition = subRange.end();
      } else {
        KTextEditor::Range rangeNeeded = m_view->selectionRange() & KTextEditor::Range(line, 0, line + 1, 0);

        currentPosition = qMax(KTextEditor::Cursor(line, 0), rangeNeeded.start());
        endPosition = qMin(KTextEditor::Cursor(line + 1, 0), rangeNeeded.end());
      }
    } else {
      currentPosition = KTextEditor::Cursor(line, 0);
      endPosition = KTextEditor::Cursor(line + 1, 0);
    }

    // Main iterative loop.  This walks through each set of highlighting ranges, and stops each
    // time the highlighting changes.  It then creates the corresponding QTextLayout::FormatRanges.
    while (currentPosition < endPosition) {
      renderRanges.advanceTo(currentPosition);

      if (!renderRanges.hasAttribute()) {
        // No attribute, don't need to create a FormatRange for this text range
        currentPosition = renderRanges.nextBoundary();
        continue;
      }

      KTextEditor::Cursor nextPosition = renderRanges.nextBoundary();

      // Create the format range and populate with the correct start, length and format info
      QTextLayout::FormatRange fr;
      fr.start = currentPosition.column();

      if (nextPosition < endPosition || endPosition.line() <= line) {
        fr.length = nextPosition.column() - currentPosition.column();

      } else {
        // +1 to force background drawing at the end of the line when it's warranted
        fr.length = textLine->length() - currentPosition.column() + 1;
      }

      KTextEditor::Attribute::Ptr a = renderRanges.generateAttribute();
      if (a) {
        fr.format = *a;

        if(selectionsOnly) {
              assignSelectionBrushesFromAttribute(fr, *a);
        }
      }

      newHighlight.append(fr);

      currentPosition = nextPosition;
    }

    if (completionHighlight)
      // Don't delete external completion render range
      renderRanges.removeAll(completionHighlight);

    qDeleteAll(renderRanges);
  }

  return newHighlight;
}
Beispiel #28
0
bool KTEView::setCursorPosition( KTextEditor::Cursor position )
{
    kDebug() << "KTEView::setCursorPosition x: " << position.column() << " y: " << position.line() << "\n";
    m_view->gotoLinePosition(position.line(), position.column());
    return true;
}
Beispiel #29
0
QPoint KTEView::cursorToCoordinate( const KTextEditor::Cursor& cursor ) const
{
    return QPoint( cursor.column(), cursor.line() );
}