Beispiel #1
0
bool KateAutoIndent::changeIndent (const KTextEditor::Range &range, int change)
{
  QList<int> skippedLines;

  // loop over all lines given...
  for (int line = range.start().line () < 0 ? 0 : range.start().line ();
       line <= qMin (range.end().line (), doc->lines()-1); ++line)
  {
    // don't indent empty lines
    if (doc->line(line).isEmpty())
    {
      skippedLines.append (line);
      continue;
    }
    // don't indent the last line when the cursor is on the first column
    if (line == range.end().line() && range.end().column() == 0)
    {
      skippedLines.append (line);
      continue;
    }

    doIndentRelative(line, change * indentWidth);
  }

  if (skippedLines.count() > range.numberOfLines())
  {
    // all lines were empty, so indent them nevertheless
    foreach (int line, skippedLines)
      doIndentRelative(line, change * indentWidth);
  }
Beispiel #2
0
/** Conversion function from QtScript range to KTextEditor::Range */
static QScriptValue rangeToScriptValue(QScriptEngine *engine, const KTextEditor::Range &range)
{
  QString code = QString("new Range(%1, %2, %3, %4);").arg(range.start().line())
                                                      .arg(range.start().column())
                                                      .arg(range.end().line())
                                                      .arg(range.end().column());
  return engine->evaluate(code);
}
Beispiel #3
0
void SwapFile::removeText (const KTextEditor::Range &range)
{
  // skip if not open
  if (!m_swapfile.isOpen ())
    return;
  
  // format: qint8, int, int, int
  Q_ASSERT (range.start().line() == range.end().line());
  m_stream << EA_RemoveText
            << range.start().line() << range.start().column()
            << range.end().column();

  m_needSync = true;
}
QString CodeRepresentation::rangeText(const KTextEditor::Range& range) const
{
    Q_ASSERT(range.end().line() < lines());

    //Easier for single line ranges which should happen most of the time
    if(range.onSingleLine())
        return QString( line( range.start().line() ).mid( range.start().column(), range.columnWidth() ) );

    //Add up al the requested lines
    QString rangedText = line(range.start().line()).mid(range.start().column());

    for(int i = range.start().line() + 1; i <= range.end().line(); ++i)
        rangedText += '\n' + ((i == range.end().line()) ? line(i).left(range.end().column()) : line(i));

    return rangedText;
}
Beispiel #5
0
QRect KTextEditorHelpers::getItemBoundingRect(const KTextEditor::View* view, const KTextEditor::Range& itemRange)
{
  QPoint startPoint = view->mapToGlobal(view->cursorToCoordinate(itemRange.start()));
  QPoint endPoint = view->mapToGlobal(view->cursorToCoordinate(itemRange.end()));
  endPoint.ry() += getLineHeight(view, itemRange.start().line());
  return QRect(startPoint, endPoint);
}
Beispiel #6
0
/** Conversion function from QtScript range to KTextEditor::Range */
static void rangeFromScriptValue(const QScriptValue &obj, KTextEditor::Range &range)
{
  range.start().setPosition(obj.property("start").property("line").toInt32(),
                            obj.property("start").property("column").toInt32());
  range.end().setPosition(obj.property("end").property("line").toInt32(),
                          obj.property("end").property("column").toInt32());
}
Beispiel #7
0
void KateViInsertMode::textInserted(KTextEditor::Document* document, KTextEditor::Range range)
{
  if (m_isExecutingCompletion)
  {
    m_textInsertedByCompletion += document->text(range);
    m_textInsertedByCompletionEndPos = range.end();
  }
}
void FunctionDeclarationCompletionItem::executed(KTextEditor::View* view, const KTextEditor::Range& word)
{
    qCDebug(KDEV_PYTHON_CODECOMPLETION) << "FunctionDeclarationCompletionItem executed";
    KTextEditor::Document* document = view->document();
    auto resolvedDecl = Helper::resolveAliasDeclaration(declaration().data());
    DUChainReadLocker lock;
    auto functionDecl = Helper::functionForCalled(resolvedDecl).declaration;
    lock.unlock();
    if ( ! functionDecl && (! resolvedDecl || ! resolvedDecl->abstractType()
                           || resolvedDecl->abstractType()->whichType() != AbstractType::TypeStructure) ) {
        qCritical(KDEV_PYTHON_CODECOMPLETION) << "ERROR: could not get declaration data, not executing completion item!";
        return;
    }
    QString suffix = "()";
    KTextEditor::Range checkPrefix(word.start().line(), 0, word.start().line(), word.start().column());
    KTextEditor::Range checkSuffix(word.end().line(), word.end().column(), word.end().line(), document->lineLength(word.end().line()));
    if ( m_doNotCall || document->text(checkSuffix).trimmed().startsWith('(')
         || document->text(checkPrefix).trimmed().endsWith('@')
         || (functionDecl && Helper::findDecoratorByName(functionDecl, QLatin1String("property"))) )
    {
        // don't insert brackets if they're already there,
        // the item is a decorator, or if it's an import item.
        suffix.clear();
    }
    // place cursor behind bracktes by default
    int skip = 2;
    if ( functionDecl ) {
        bool needsArguments = false;
        int argumentCount = functionDecl->type<FunctionType>()->arguments().length();
        if ( functionDecl->context()->type() == KDevelop::DUContext::Class ) {
            // it's a member function, so it has the implicit self
            // TODO static methods
            needsArguments = argumentCount > 1;
        }
        else {
            // it's a free function
            needsArguments = argumentCount > 0;
        }
        if ( needsArguments ) {
            // place cursor in brackets if there's parameters
            skip = 1;
        }
    }
    document->replaceText(word, declaration()->identifier().toString() + suffix);
    view->setCursorPosition( Cursor(word.end().line(), word.end().column() + skip) );
}
void PreprocessorCompletionModel::completionInvoked(
    KTextEditor::View* const view
  , const KTextEditor::Range& word
  , InvocationType /*itype*/
  )
{
    // Reuse shouldStartCompletion to disable/enable completion
    m_should_complete = shouldStartCompletion(view, QString{}, false, word.end());
}
void ClangCodeCompletionModel::executeCompletionItem2(
    KTextEditor::Document* const doc
  , const KTextEditor::Range& word
  , const QModelIndex& index
  ) const
{
    assert("Active view expected to be equal to the stored one" && doc->activeView() == m_current_view);
    assert("Invalid index is not expected here!" && index.isValid());
    assert("Parent index is not valid" && index.parent().isValid());
    assert("Parent index must be GROUP" && index.parent().internalId() == Level::GROUP);
    assert(
        "Parent index points to invalid group"
      && 0 <= index.internalId()
      && unsigned(index.internalId()) < m_groups.size()
      );
    assert(
        "Index points to invalid item"
      && 0 <= index.row()
      && unsigned(index.row()) < m_groups[index.internalId()].second.m_completions.size()
      );

    auto* const template_iface = qobject_cast<KTextEditor::TemplateInterface2*>(m_current_view);
    if (template_iface)
    {
        kDebug(DEBUG_AREA) << "TemplateInterface available for a view" << m_current_view;
        const auto result = m_groups[index.internalId()]
          .second.m_completions[index.row()]
          .getCompletionTemplate();
        kDebug(DEBUG_AREA) << "Template:" << result.m_tpl;
        kDebug(DEBUG_AREA) << "Values:" << result.m_values;
        // Check if current template is a function and there is a '()' right after cursor
        auto range = word;
        if (result.m_is_function)
        {
            const auto next_word_range = DocumentProxy(doc).firstWordAfterCursor(word.end());
            kDebug(DEBUG_AREA) << "OK THIS IS FUNCTION TEMPLATE: next word range" << next_word_range;
            kDebug(DEBUG_AREA) << "replace range before:" << range;
            if (next_word_range.isValid() && doc->text(next_word_range).startsWith(QLatin1String("()")))
            {
                range.end().setColumn(next_word_range.start().column() + 2);
                kDebug(DEBUG_AREA) << "replace range after:" << range;
            }
        }
        doc->removeText(range);
        template_iface->insertTemplateText(range.start(), result.m_tpl, result.m_values, nullptr);
    }
    else
    {
        kDebug(DEBUG_AREA) << "No TemplateInterface for a view" << m_current_view;
        const auto p = m_groups[index.internalId()].second.m_completions[index.row()].executeCompletion();
        doc->replaceText(word, p.first);
        // Try to reposition a cursor inside a current (hope it still is) view
        auto pos = word.start();
        pos.setColumn(pos.column() + p.second);
        m_current_view->setCursorPosition(pos);
    }
}
    void execute(KTextEditor::View* view, const KTextEditor::Range& word) override
    {
        auto document = view->document();
        auto range = word;
        const int lineNumber = word.end().line();
        const QString line = document->line(lineNumber);
        const auto properties = includePathProperties(line, word.end().column());
        if (!properties.valid) {
            return;
        }

        QString newText = includeItem.isDirectory ? (includeItem.name + QLatin1Char('/')) : includeItem.name;

        if (properties.inputFrom == -1) {
            newText.prepend(QLatin1Char('<'));
        } else {
            range.setStart({lineNumber, properties.inputFrom});
        }
        if (properties.inputTo == -1) {
            // Add suffix
            if (properties.local) {
                newText += QLatin1Char('"');
            } else {
                newText += QLatin1Char('>');
            }

            // replace the whole line
            range.setEnd({lineNumber, line.size()});
        } else {
            range.setEnd({lineNumber, properties.inputTo});
        }

        document->replaceText(range, newText);

        if (includeItem.isDirectory) {
            // ensure we can continue to add files/paths when we just added a directory
            int offset = (properties.inputTo == -1) ? 1 : 0;
            view->setCursorPosition(range.start() + KTextEditor::Cursor(0, newText.length() - offset));
        } else {
            // place cursor at end of line
            view->setCursorPosition({lineNumber, document->lineLength(lineNumber)});
        }
    }
void ImplementFunctionCompletionItem::execute(KTextEditor::Document* document, const KTextEditor::Range& word)
{
    const QString finalText = m_name + "(" + m_arguments.join(", ") + "):";
    document->replaceText(word, finalText);
    // 4 spaces is indentation for python. everyone does it like this. you must, too.
    // TODO use kate settings
    document->insertLine(word.start().line() + 1, m_previousIndent + "    ");
    if ( View* view = document->activeView() ) {
        view->setCursorPosition(Cursor(word.end().line() + 1, m_previousIndent.length() + 4));
    }
}
Beispiel #13
0
void TextHistory::removeText(const KTextEditor::Range &range, int oldLineLength)
{
    // create and add new entry
    Entry entry;
    entry.type = Entry::RemoveText;
    entry.line = range.start().line();
    entry.column = range.start().column();
    entry.length = range.end().column() - range.start().column();
    entry.oldLineLength = oldLineLength;
    addEntry(entry);
}
Beispiel #14
0
QSize GrepOutputDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    const GrepOutputModel *model = dynamic_cast<const GrepOutputModel *>(index.model());
    const GrepOutputItem  *item  = model ? dynamic_cast<const GrepOutputItem *>(model->itemFromIndex(index)) : nullptr;

    QSize ret = QStyledItemDelegate::sizeHint(option, index);

    //take account of additional width required for highlighting (bold text)
    //and line numbers. These are not included in the default Qt size calculation.
    if(item && item->isText())
    {
        QFont font = option.font;
        QFontMetrics metrics(font);
        font.setBold(true);
        QFontMetrics bMetrics(font);

        const KTextEditor::Range rng = item->change()->m_range;

        int width = metrics.width(item->text().left(rng.start().column())) +
                    metrics.width(item->text().right(item->text().length() - rng.end().column())) +
                    bMetrics.width(item->text().mid(rng.start().column(), rng.end().column() - rng.start().column())) +
                    option.fontMetrics.width(i18n("Line %1: ",item->lineNumber())) +
                    std::max(option.decorationSize.width(), 0);
        ret.setWidth(width);
    }else{
        // This is only used for titles, so not very performance critical
        QString text;
        if(item)
            text = item->text();
        else
            text = index.data().toString();
        
        QTextDocument doc;
        doc.setDocumentMargin(0);
        doc.setHtml(text);
        QSize newSize = doc.size().toSize();
        if(newSize.height() > ret.height())
            ret.setHeight(newSize.height());
    }
    return ret;
}
/**
 * We have to stop \c #include completion when current line would parsed well
 * (i.e. contains complete \c #include expression) or have no \c #include at all.
 */
bool IncludeHelperCompletionModel::shouldAbortCompletion(
    KTextEditor::View* view
  , const KTextEditor::Range& range
  , const QString& current_completion
  )
{
    kDebug(DEBUG_AREA) << "range=" << range << ", current_completion=" << current_completion;
    kDebug(DEBUG_AREA) << "m_should_complete=" << m_should_complete << ", closer=" << m_closer;

    // Get current line
    const auto line = view->document()->line(range.end().line());
    // Try to parse it...
    auto r = parseIncludeDirective(line, false);
    // nothing to complete for lines w/o #include
    const auto need_abort = !r.m_range.isValid()
      || range.end().column() < r.m_range.start().column()
      || range.end().column() > (r.m_range.end().column() + 1)
      ;
    kDebug(DEBUG_AREA) << "result=" << need_abort;
    return need_abort;
}
Beispiel #16
0
void RangeTest::rangeCheck(KTextEditor::Range &valid)
{
    QVERIFY(valid.isValid() && valid.start() <= valid.end());

    KTextEditor::Cursor before(0, 1), start(0, 2), end(1, 4), after(1, 10);

    KTextEditor::Range result(start, end);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());

    valid.setRange(start, end);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());
    QCOMPARE(valid, result);

    valid.setRange(end, start);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());
    QCOMPARE(valid, result);

    valid.setStart(after);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());
    QCOMPARE(valid, KTextEditor::Range(after, after));

    valid = result;
    QCOMPARE(valid, result);

    valid.setEnd(before);
    QVERIFY(valid.isValid() && valid.start() <= valid.end());
    QCOMPARE(valid, KTextEditor::Range(before, before));
}
Beispiel #17
0
// Contributed by <*****@*****.**>
void KateWordCompletionView::shellComplete()
{
  KTextEditor::Range r = range();

  QStringList matches = m_dWCompletionModel->allMatches( m_view, r );

  if (matches.size() == 0)
    return;

  QString partial = findLongestUnique( matches, r.columnWidth() );

  if ( ! partial.length() )
    popupCompletionList();

  else
  {
    m_view->document()->insertText( r.end(), partial.mid( r.columnWidth() ) );
    d->liRange->setView(m_view);
    d->liRange->setRange( KTextEditor::Range( r.end(), partial.length() - r.columnWidth() ) );
    connect( m_view, SIGNAL(cursorPositionChanged(KTextEditor::View*,KTextEditor::Cursor)), this, SLOT(slotCursorMoved()) );
  }
}
Beispiel #18
0
void TextBuffer::removeText (const KTextEditor::Range &range)
{
  // only allowed if editing transaction running
  Q_ASSERT (m_editingTransactions > 0);

  // only ranges on one line are supported
  Q_ASSERT (range.start().line() == range.end().line());

  // start colum <= end column and >= 0
  Q_ASSERT (range.start().column() <= range.end().column());
  Q_ASSERT (range.start().column() >= 0);

  // skip work, if no text to remove
  if (range.isEmpty())
    return;

  // get block, this will assert on invalid line
  int blockIndex = blockForLine (range.start().line());

  // let the block handle the removeText, retrieve removed text
  QString text;
  m_blocks.at(blockIndex)->removeText (range, text);

  // remember changes
  ++m_revision;

  // update changed line interval
  if (range.start().line() < m_editingMinimalLineChanged || m_editingMinimalLineChanged == -1)
    m_editingMinimalLineChanged = range.start().line();

  if (range.start().line() > m_editingMaximalLineChanged)
    m_editingMaximalLineChanged = range.start().line();

  // emit signal about done change
  emit textRemoved (range, text);
}
Beispiel #19
0
TextRange::TextRange (TextBuffer &buffer, const KTextEditor::Range &range, InsertBehaviors insertBehavior, EmptyBehavior emptyBehavior)
  : m_buffer (buffer)
  , m_start (buffer, this, range.start(), (insertBehavior & ExpandLeft) ? Kate::TextCursor::StayOnInsert : Kate::TextCursor::MoveOnInsert)
  , m_end (buffer, this, range.end(), (insertBehavior & ExpandRight) ? Kate::TextCursor::MoveOnInsert : Kate::TextCursor::StayOnInsert)
  , m_view (0)
  , m_feedback (0)
  , m_zDepth (0.0)
  , m_attributeOnlyForViews (false)
  , m_invalidateIfEmpty (emptyBehavior == InvalidateIfEmpty)
{
  // remember this range in buffer
  m_buffer.m_ranges.insert (this);

  // check if range now invalid, there can happen no feedback, as m_feedback == 0
  checkValidity ();
}
Beispiel #20
0
void TextRange::setRange (const KTextEditor::Range &range)
{
  // avoid work if nothing changed!
  if (range == toRange())
    return;

  // remember old line range
  int oldStartLine = m_start.line();
  int oldEndLine = m_end.line();

  // change start and end cursor
  m_start.setPosition (range.start ());
  m_end.setPosition (range.end ());

  // check if range now invalid, don't emit feedback here, will be handled below
  // otherwise you can't delete ranges in feedback!
  checkValidity (oldStartLine, oldEndLine, false);

  // no attribute or feedback set, be done
  if (!m_attribute && !m_feedback)
    return;

  // get full range
  int startLineMin = oldStartLine;
  if (oldStartLine == -1 || (m_start.line() != -1 && m_start.line() < oldStartLine))
    startLineMin = m_start.line();

  int endLineMax = oldEndLine;
  if (oldEndLine == -1 || m_end.line() > oldEndLine)
    endLineMax = m_end.line();

  /**
   * notify buffer about attribute change, it will propagate the changes
   * notify right view
   */
  m_buffer.notifyAboutRangeChange (m_view, startLineMin, endLineMax, m_attribute);

  // perhaps need to notify stuff!
  if (m_feedback) {
    // do this last: may delete this range
    if (!toRange().isValid())
      m_feedback->rangeInvalid (this);
    else if (toRange().isEmpty())
      m_feedback->rangeEmpty (this);
  }
}
Beispiel #21
0
void RangeTest::testRangeStringConversion()
{
    using KTextEditor::Cursor;
    using KTextEditor::Range;

    KTextEditor::Range r;
    QCOMPARE(r.start(), Cursor(0, 0));
    QCOMPARE(r.end(), Cursor(0, 0));
    QCOMPARE(r.toString(), QStringLiteral("[(0, 0), (0, 0)]"));

    r = Range::fromString(QStringLiteral("[(0, 0), (0, 0)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(0, 0), (0, 0)]"));
    r = Range::fromString(QStringLiteral("[(0,0),(0,0)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(0, 0), (0, 0)]"));
    r = Range::fromString(QStringLiteral("[(-1, -1), (-1, -1)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(-1, -1), (-1, -1)]"));
    r = Range::fromString(QStringLiteral("[(-1, -1), (0, 0)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(-1, -1), (0, 0)]"));
    r = Range::fromString(QStringLiteral("[(0, 0), (-1, -1)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(-1, -1), (0, 0)]")); // start > end -> swap

    r = Range::fromString(QStringLiteral("[(0, 0), (12, 42)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(0, 0), (12, 42)]"));
    r = Range::fromString(QStringLiteral("[(12, 42), (0, 0)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(0, 0), (12, 42)]")); // start > end -> swap
    r = Range::fromString(QStringLiteral("[(12,42),(0,0)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(0, 0), (12, 42)]")); // start > end -> swap
    r = Range::fromString(QStringLiteral("[(-12, -42), (0, 0)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(-12, -42), (0, 0)]"));
    r = Range::fromString(QStringLiteral("[(0, 0), (-12, -42)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(-12, -42), (0, 0)]")); // start > end -> swap

    // invalid input
    r = Range::fromString(QStringLiteral("[(0:0)(-12:-42)]"));
    QCOMPARE(r.toString(), QStringLiteral("[(-1, -1), (-1, -1)]"));
    r = Range::fromString(QStringLiteral("[0,1]"));
    QCOMPARE(r.toString(), QStringLiteral("[(-1, -1), (-1, -1)]"));
}
void NormalDeclarationCompletionItem::execute(KTextEditor::View* view, const KTextEditor::Range& word) {

    if( m_completionContext && m_completionContext->depth() != 0 )
        return; //Do not replace any text when it is an argument-hint

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

    {
        KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock());
        if(m_declaration) {
            newText = declarationName();
        } else {
            qCDebug(LANGUAGE) << "Declaration disappeared";
            return;
        }
    }

    document->replaceText(word, newText);
    KTextEditor::Range newRange = word;
    newRange.setEnd(KTextEditor::Cursor(newRange.end().line(), newRange.start().column() + newText.length()));

    executed(view, newRange);
}
Beispiel #23
0
bool KateCommands::CoreCommands::exec(KTextEditor::View *view,
                            const QString &_cmd,
                            QString &errorMsg,
                            const KTextEditor::Range& range)
{
#define KCC_ERR(s) { errorMsg=s; return false; }
  // cast it hardcore, we know that it is really a kateview :)
  KateView *v = static_cast<KateView*>(view);

  if ( ! v )
    KCC_ERR( i18n("Could not access view") );

  //create a list of args
  QStringList args(_cmd.split( QRegExp("\\s+"), QString::SkipEmptyParts)) ;
  QString cmd ( args.takeFirst() );

  // ALL commands that takes no arguments.
  if ( cmd == "indent" )
  {
    if ( range.isValid() ) {
      v->doc()->editStart();
      for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
        v->doc()->indent( KTextEditor::Range(line, 0, line, 0), 1 );
      }
      v->doc()->editEnd();
    } else {
      v->indent();
    }
    return true;
  }
  else if ( cmd == "unindent" )
  {
    if ( range.isValid() ) {
      v->doc()->editStart();
      for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
        v->doc()->indent( KTextEditor::Range(line, 0, line, 0), -1 );
      }
      v->doc()->editEnd();
    } else {
      v->unIndent();
    }
    return true;
  }
  else if ( cmd == "cleanindent" )
  {
    if ( range.isValid() ) {
      v->doc()->editStart();
      for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
        v->doc()->indent( KTextEditor::Range(line, 0, line, 0), 0 );
      }
      v->doc()->editEnd();
    } else {
      v->cleanIndent();
    }
    return true;
  }
  else if ( cmd == "comment" )
  {
    if ( range.isValid() ) {
      v->doc()->editStart();
      for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
        v->doc()->comment( v, line, 0, 1 );
      }
      v->doc()->editEnd();
    } else {
      v->comment();
    }
    return true;
  }
  else if ( cmd == "uncomment" )
  {
    if ( range.isValid() ) {
      v->doc()->editStart();
      for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
        v->doc()->comment( v, line, 0, -1 );
      }
      v->doc()->editEnd();
    } else {
      v->uncomment();
    }
    return true;
  }
  else if ( cmd == "kill-line" )
  {
    if ( range.isValid() ) {
      v->doc()->editStart();
      for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
        v->doc()->removeLine( range.start().line() );
      }
      v->doc()->editEnd();
    } else {
      v->killLine();
    }
    return true;
  }
  else if ( cmd == "print" )
  {
    v->doc()->printDialog();
    return true;
  }

  // ALL commands that take a string argument
  else if ( cmd == "set-indent-mode" ||
            cmd == "set-highlight" ||
            cmd == "set-mode" )
  {
    // need at least one item, otherwise args.first() crashes
    if ( ! args.count() )
      KCC_ERR( i18n("Missing argument. Usage: %1 <value>",  cmd ) );

    if ( cmd == "set-indent-mode" )
    {
      v->doc()->config()->setIndentationMode( args.join(" ") );
      v->doc()->rememberUserDidSetIndentationMode ();
      return true;
    }
    else if ( cmd == "set-highlight" )
    {
      if ( v->doc()->setHighlightingMode( args.first()) )
      {
        static_cast<KateDocument*>(v->doc())->setDontChangeHlOnSave ();
        return true;
      }

      KCC_ERR( i18n("No such highlighting '%1'",  args.first() ) );
    }
    else if ( cmd == "set-mode" )
    {
      if ( v->doc()->setMode( args.first()) )
        return true;

      KCC_ERR( i18n("No such mode '%1'",  args.first() ) );
    }
  }
  // ALL commands that takes exactly one integer argument.
  else if ( cmd == "set-tab-width" ||
            cmd == "set-indent-width" ||
            cmd == "set-word-wrap-column" ||
            cmd == "goto" )
  {
    // find a integer value > 0
    if ( ! args.count() )
      KCC_ERR( i18n("Missing argument. Usage: %1 <value>",  cmd ) );
    bool ok;
    int val ( args.first().toInt( &ok, 10 ) ); // use base 10 even if the string starts with '0'
    if ( !ok )
      KCC_ERR( i18n("Failed to convert argument '%1' to integer.",
                  args.first() ) );

    if ( cmd == "set-tab-width" )
    {
      if ( val < 1 )
        KCC_ERR( i18n("Width must be at least 1.") );
      v->doc()->config()->setTabWidth( val );
    }
    else if ( cmd == "set-indent-width" )
    {
      if ( val < 1 )
        KCC_ERR( i18n("Width must be at least 1.") );
      v->doc()->config()->setIndentationWidth( val );
    }
    else if ( cmd == "set-word-wrap-column" )
    {
      if ( val < 2 )
        KCC_ERR( i18n("Column must be at least 1.") );
      v->doc()->setWordWrapAt( val );
    }
    else if ( cmd == "goto" )
    {
      if ( args.first().at(0) == '-' || args.first().at(0) == '+' ) {
        // if the number starts with a minus or plus sign, add/subract the number
        val = v->cursorPosition().line() + val;
      } else {
        val--; // convert given line number to the internal representation of line numbers
      }

      // constrain cursor to the range [0, number of lines]
      if ( val < 0 ) {
        val = 0;
      } else if ( val > v->doc()->lines()-1 ) {
        val = v->doc()->lines()-1;
      }

      v->setCursorPosition( KTextEditor::Cursor( val, 0 ) );
      return true;
    }
    return true;
  }

  // ALL commands that takes 1 boolean argument.
  else if ( cmd == "set-icon-border" ||
            cmd == "set-folding-markers" ||
            cmd == "set-line-numbers" ||
            cmd == "set-replace-tabs" ||
            cmd == "set-show-tabs" ||
            cmd == "set-word-wrap" ||
            cmd == "set-wrap-cursor" ||
            cmd == "set-replace-tabs-save" ||
            cmd == "set-show-indent" )
  {
    if ( ! args.count() )
      KCC_ERR( i18n("Usage: %1 on|off|1|0|true|false",  cmd ) );
    bool enable = false;
    KateDocumentConfig * const config = v->doc()->config();
    if ( getBoolArg( args.first(), &enable ) )
    {
      if ( cmd == "set-icon-border" )
        v->setIconBorder( enable );
      else if (cmd == "set-folding-markers")
        v->setFoldingMarkersOn( enable );
      else if ( cmd == "set-line-numbers" )
        v->setLineNumbersOn( enable );
      else if ( cmd == "set-show-indent" )
        v->renderer()->setShowIndentLines( enable );
      else if ( cmd == "set-replace-tabs" )
        config->setReplaceTabsDyn( enable );
      else if ( cmd == "set-show-tabs" )
        config->setShowTabs( enable );
      else if ( cmd == "set-show-trailing-spaces" )
        config->setShowSpaces( enable );
      else if ( cmd == "set-word-wrap" )
        v->doc()->setWordWrap( enable );

      return true;
    }
    else
      KCC_ERR( i18n("Bad argument '%1'. Usage: %2 on|off|1|0|true|false",
                 args.first() ,  cmd ) );
  }
  else if ( cmd == "set-remove-trailing-spaces" ) {
    // need at least one item, otherwise args.first() crashes
    if ( args.count() != 1 )
      KCC_ERR( i18n("Usage: set-remove-trailing-spaces 0|-|none or 1|+|mod|modified or 2|*|all") );

    QString tmp = args.first().toLower().trimmed();
    if (tmp == "1" || tmp == "modified" || tmp == "mod" || tmp == "+") {
      v->doc()->config()->setRemoveSpaces(1);
    } else if (tmp == "2" || tmp == "all" || tmp == "*") {
      v->doc()->config()->setRemoveSpaces(2);
    } else {
      v->doc()->config()->setRemoveSpaces(0);
    }
  }

  // unlikely..
  KCC_ERR( i18n("Unknown command '%1'", cmd) );
}
Beispiel #24
0
void GrepOutputDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{ 
    // there is no function in QString to left-trim. A call to remove this this regexp does the job
    static const QRegExp leftspaces("^\\s*", Qt::CaseSensitive, QRegExp::RegExp);
    
    // rich text component
    const GrepOutputModel *model = dynamic_cast<const GrepOutputModel *>(index.model());
    const GrepOutputItem  *item  = dynamic_cast<const GrepOutputItem *>(model->itemFromIndex(index));

    QStyleOptionViewItem options = option;
    initStyleOption(&options, index);

    // building item representation
    QTextDocument doc;
    QTextCursor cur(&doc);
    
    QPalette::ColorGroup cg = options.state & QStyle::State_Enabled
                                ? QPalette::Normal : QPalette::Disabled;
    QPalette::ColorRole cr  = options.state & QStyle::State_Selected
                                ? QPalette::HighlightedText : QPalette::Text;
    QTextCharFormat fmt = cur.charFormat();
    fmt.setFont(options.font);

    if(item && item->isText())
    {
        // Use custom manual highlighting

        const KTextEditor::Range rng = item->change()->m_range;

        // the line number appears grayed
        fmt.setForeground(options.palette.brush(QPalette::Disabled, cr));
        cur.insertText(i18n("Line %1: ",item->lineNumber()), fmt);
        
        // switch to normal color
        fmt.setForeground(options.palette.brush(cg, cr));
        cur.insertText(item->text().left(rng.start().column()).remove(leftspaces), fmt);
        
        fmt.setFontWeight(QFont::Bold);
        if ( !(options.state & QStyle::State_Selected) ) {
            QColor bgHighlight = option.palette.color(QPalette::AlternateBase);
            fmt.setBackground(bgHighlight);
        }
        cur.insertText(item->text().mid(rng.start().column(), rng.end().column() - rng.start().column()), fmt);
        fmt.clearBackground();
        
        fmt.setFontWeight(QFont::Normal);
        cur.insertText(item->text().right(item->text().length() - rng.end().column()), fmt);
    }else{
        QString text;
        if(item)
            text = item->text();
        else
            text = index.data().toString();
        // Simply insert the text as html. We use this for the titles.
        doc.setHtml(text);
    }
    
    painter->save();
    options.text = QString();  // text will be drawn separately
    options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget);

    // set correct draw area
    QRect clip = options.widget->style()->subElementRect(QStyle::SE_ItemViewItemText, &options);
    QFontMetrics metrics(options.font);
    painter->translate(clip.topLeft() - QPoint(0, metrics.descent()));

    // We disable the clipping for now, as it leads to strange clipping errors
//     clip.setTopLeft(QPoint(0,0));
    
//     painter->setClipRect(clip);
    QAbstractTextDocumentLayout::PaintContext ctx;
//     ctx.clip = clip;
    painter->setBackground(Qt::transparent);
    doc.documentLayout()->draw(painter, ctx);

    painter->restore();
}
// Scan throughout the entire document for possible completions,
// ignoring any dublets
const QStringList KateNewCompletionModel::allMatches( KTextEditor::View *view, const KTextEditor::Range &range ) const
{
  KTextEditor::Document *doc = view->document();
  QString match_str = doc->text(range);
  QString s, m;
  QSet<QString> seen;
  QStringList l;

  int i( 0 );
  int pos( 0 );

  QRegExp class_rek("([A-Z]\\w*<( |\\w|,|<|>)+>)");
  if (match_str.startsWith("new ")) {
    QString class_name = match_str.mid(4);
    for (i = 0; i < doc->lines(); ++i) {
      QString s = doc->line(i);
      QString m;
      pos = 0;
      while (pos >= 0) {
        pos = class_rek.indexIn(s, pos);
        if ( pos >= 0 )
        {
          // typing in the middle of a word
          if ( ! ( i == range.start().line() && pos >= range.start().column() && pos <= range.end().column()) )
          {
            m = class_rek.cap( 1 );
            if ( ! seen.contains( m ) && m.startsWith(class_name)) {
              seen.insert( m );
              m = "new " + m;
              l << m;
            }
          }
          pos += class_rek.matchedLength();
        }
      }
    }
  }

  // convert yieldXXX and Ent::load('XXX') to genXXX and getXXX
  if (match_str.startsWith("gen") || match_str.startsWith("get")) {
    QString x = match_str.mid(3);
    class_rek = QRegExp("(yield|Ent::load\\(\\\'|Ent::load\\(\\\")([A-Z]\\w*)");
    for (i = 0; i < doc->lines(); ++i) {
      QString s = doc->line(i);
      QString m;
      pos = 0;
      while (pos >= 0) {
        pos = class_rek.indexIn(s, pos);
        if ( pos >= 0 )
        {
          // typing in the middle of a word
          if ( ! ( i == range.start().line() && pos >= range.start().column() && pos <= range.end().column()) )
          {
            m = class_rek.cap( 2 );
            if ( ! seen.contains( m ) && m.startsWith(x)) {
              seen.insert( m );
              l << ("gen" + m);
              l << ("get" + m);
            }
          }
          pos += class_rek.matchedLength();
        }
      }
    }
  }

  return l;
}
Beispiel #26
0
bool KatePrinter::print (KateDocument *doc)
{
  QPrinter printer;
  readSettings(printer);

  // docname is now always there, including the right Untitled name
  printer.setDocName(doc->documentName());

  KatePrintTextSettings *kpts = new KatePrintTextSettings;
  KatePrintHeaderFooter *kphf = new KatePrintHeaderFooter;
  KatePrintLayout *kpl = new KatePrintLayout;

  QList<QWidget*> tabs;
  tabs << kpts;
  tabs << kphf;
  tabs << kpl;

  QWidget *parentWidget=doc->widget();

  if ( !parentWidget )
    parentWidget=QApplication::activeWindow();

  QScopedPointer<QPrintDialog> printDialog(KdePrint::createPrintDialog(&printer, KdePrint::SystemSelectsPages, tabs, parentWidget));

  if ( doc->activeView()->selection() ) {
    printer.setPrintRange(QPrinter::Selection);
    printDialog->setOption(QAbstractPrintDialog::PrintSelection, true);
  }

  if ( printDialog->exec() )
  {
    writeSettings(printer);

    KateRenderer renderer(doc, doc->activeKateView());
    renderer.config()->setSchema (kpl->colorScheme());
    renderer.setPrinterFriendly(true);

    QPainter paint( &printer );
    /*
     *        We work in tree cycles:
     *        1) initialize variables and retrieve print settings
     *        2) prepare data according to those settings
     *        3) draw to the printer
     */
    uint pdmWidth = printer.width();
    uint pdmHeight = printer.height();
    int y = 0;
    uint xstart = 0; // beginning point for painting lines
    uint lineCount = 0;
    uint maxWidth = pdmWidth;
    int headerWidth = pdmWidth;
    int startCol = 0;
    int endCol = 0;
    bool pageStarted = true;
    int remainder = 0; // remaining sublines from a wrapped line (for the top of a new page)

    // Text Settings Page
    bool selectionOnly = (printDialog->printRange() == QAbstractPrintDialog::Selection);
    bool useGuide = kpts->printGuide();

    bool printLineNumbers = kpts->printLineNumbers();
    uint lineNumberWidth( 0 );

    // Header/Footer Page
    QFont headerFont(kphf->font()); // used for header/footer

    bool useHeader = kphf->useHeader();
    QColor headerBgColor(kphf->headerBackground());
    QColor headerFgColor(kphf->headerForeground());
    uint headerHeight( 0 ); // further init only if needed
    QStringList headerTagList; // do
    bool headerDrawBg = false; // do

    bool useFooter = kphf->useFooter();
    QColor footerBgColor(kphf->footerBackground());
    QColor footerFgColor(kphf->footerForeground());
    uint footerHeight( 0 ); // further init only if needed
    QStringList footerTagList; // do
    bool footerDrawBg = false; // do

    // Layout Page
    renderer.config()->setSchema( kpl->colorScheme() );
    bool useBackground = kpl->useBackground();
    bool useBox = kpl->useBox();
    int boxWidth(kpl->boxWidth());
    QColor boxColor(kpl->boxColor());
    int innerMargin = useBox ? kpl->boxMargin() : 6;

    // Post initialization
    int maxHeight = (useBox ? pdmHeight-innerMargin : pdmHeight);
    uint currentPage( 1 );
    uint lastline = doc->lastLine(); // necessary to print selection only
    uint firstline( 0 );
    const int fontHeight = renderer.fontHeight();
    KTextEditor::Range selectionRange;

    /*
    *        Now on for preparations...
    *        during preparations, variable names starting with a "_" means
    *        those variables are local to the enclosing block.
    */
    {
      if ( selectionOnly )
      {
        // set a line range from the first selected line to the last
        selectionRange = doc->activeView()->selectionRange();
        firstline = selectionRange.start().line();
        lastline = selectionRange.end().line();
        lineCount = firstline;
      }

      if ( printLineNumbers )
      {
        // figure out the horiizontal space required
        QString s( QString("%1 ").arg( doc->lines() ) );
        s.fill('5', -1); // some non-fixed fonts haven't equally wide numbers
        // FIXME calculate which is actually the widest...
        lineNumberWidth = renderer.currentFontMetrics().width( s );
        // a small space between the line numbers and the text
        int _adj = renderer.currentFontMetrics().width( "5" );
        // adjust available width and set horizontal start point for data
        maxWidth -= (lineNumberWidth + _adj);
        xstart += lineNumberWidth + _adj;
      }

      if ( useHeader || useFooter )
      {
        // Set up a tag map
        // This retrieves all tags, ued or not, but
        // none of theese operations should be expensive,
        // and searcing each tag in the format strings is avoided.
        QDateTime dt = QDateTime::currentDateTime();
        QMap<QString,QString> tags;

        KUser u (KUser::UseRealUserID);
        tags["u"] = u.loginName();

        tags["d"] = KGlobal::locale()->formatDateTime(dt, KLocale::ShortDate);
        tags["D"] =  KGlobal::locale()->formatDateTime(dt, KLocale::LongDate);
        tags["h"] =  KGlobal::locale()->formatTime(dt.time(), false);
        tags["y"] =  KGlobal::locale()->formatDate(dt.date(), KLocale::ShortDate);
        tags["Y"] =  KGlobal::locale()->formatDate(dt.date(), KLocale::LongDate);
        tags["f"] =  doc->url().fileName();
        tags["U"] =  doc->url().prettyUrl();
        if ( selectionOnly )
        {
          QString s( i18n("(Selection of) ") );
          tags["f"].prepend( s );
          tags["U"].prepend( s );
        }

        QRegExp reTags( "%([dDfUhuyY])" ); // TODO tjeck for "%%<TAG>"

        if (useHeader)
        {
          headerDrawBg = kphf->useHeaderBackground();
          headerHeight = QFontMetrics( headerFont ).height();
          if ( useBox || headerDrawBg )
            headerHeight += innerMargin * 2;
          else
            headerHeight += 1 + QFontMetrics( headerFont ).leading();

          headerTagList = kphf->headerFormat();
          QMutableStringListIterator it(headerTagList);
          while ( it.hasNext() ) {
            QString tag = it.next();
            int pos = reTags.indexIn( tag );
            QString rep;
            while ( pos > -1 )
            {
              rep = tags[reTags.cap( 1 )];
              tag.replace( (uint)pos, 2, rep );
              pos += rep.length();
              pos = reTags.indexIn( tag, pos );
            }
            it.setValue( tag );
          }

          if (!headerBgColor.isValid())
            headerBgColor = Qt::lightGray;
          if (!headerFgColor.isValid())
            headerFgColor = Qt::black;
        }

        if (useFooter)
        {
          footerDrawBg = kphf->useFooterBackground();
          footerHeight = QFontMetrics( headerFont ).height();
          if ( useBox || footerDrawBg )
            footerHeight += 2*innerMargin;
          else
            footerHeight += 1; // line only

          footerTagList = kphf->footerFormat();
          QMutableStringListIterator it(footerTagList);
          while ( it.hasNext() ) {
            QString tag = it.next();
            int pos = reTags.indexIn( tag );
            QString rep;
            while ( pos > -1 )
            {
              rep = tags[reTags.cap( 1 )];
              tag.replace( (uint)pos, 2, rep );
              pos += rep.length();
              pos = reTags.indexIn( tag, pos );
            }
            it.setValue( tag );
          }

          if (!footerBgColor.isValid())
            footerBgColor = Qt::lightGray;
          if (!footerFgColor.isValid())
            footerFgColor = Qt::black;
          // adjust maxheight, so we can know when/where to print footer
          maxHeight -= footerHeight;
        }
      } // if ( useHeader || useFooter )

      if ( useBackground )
      {
        if ( ! useBox )
        {
          xstart += innerMargin;
          maxWidth -= innerMargin * 2;
        }
      }

      if ( useBox )
      {
        if (!boxColor.isValid())
          boxColor = Qt::black;
        if (boxWidth < 1) // shouldn't be pssible no more!
          boxWidth = 1;
        // set maxwidth to something sensible
        maxWidth -= ( ( boxWidth + innerMargin )  * 2 );
        xstart += boxWidth + innerMargin;
        // maxheight too..
        maxHeight -= boxWidth;
      }
      else
        boxWidth = 0;

      // now that we know the vertical amount of space needed,
      // it is possible to calculate the total number of pages
      // if needed, that is if any header/footer tag contains "%P".
      if ( !headerTagList.filter("%P").isEmpty() || !footerTagList.filter("%P").isEmpty() )
      {
        kDebug(13020)<<"'%P' found! calculating number of pages...";
        int pageHeight = maxHeight;
        if ( useHeader )
          pageHeight -= ( headerHeight + innerMargin );
        if ( useFooter )
          pageHeight -= innerMargin;
        const int linesPerPage = pageHeight / fontHeight;
//         kDebug() << "Lines per page:" << linesPerPage;
        
        // calculate total layouted lines in the document
        int totalLines = 0;
        // TODO: right now ignores selection printing
        for (int i = firstline; i <= lastline; ++i) {
          KateLineLayoutPtr rangeptr(new KateLineLayout(doc));
          rangeptr->setLine(i);
          renderer.layoutLine(rangeptr, (int)maxWidth, false);
          totalLines += rangeptr->viewLineCount();
        }
        int totalPages = (totalLines / linesPerPage)
                      + ((totalLines % linesPerPage) > 0 ? 1 : 0);
//         kDebug() << "_______ pages:" << (totalLines / linesPerPage);
//         kDebug() << "________ rest:" << (totalLines % linesPerPage);

        // TODO: add space for guide if required
//         if ( useGuide )
//           _lt += (guideHeight + (fontHeight /2)) / fontHeight;

        // substitute both tag lists
        QString re("%P");
        QStringList::Iterator it;
        for ( it=headerTagList.begin(); it!=headerTagList.end(); ++it )
          (*it).replace( re, QString( "%1" ).arg( totalPages ) );
        for ( it=footerTagList.begin(); it!=footerTagList.end(); ++it )
          (*it).replace( re, QString( "%1" ).arg( totalPages ) );
      }
    } // end prepare block

     /*
        On to draw something :-)
     */
    while (  lineCount <= lastline  )
    {
      startCol = 0;
      endCol = 0;

      if ( y + fontHeight > maxHeight )
      {
        kDebug(13020)<<"Starting new page,"<<lineCount<<"lines up to now.";
        printer.newPage();
        paint.resetTransform();
        currentPage++;
        pageStarted = true;
        y=0;
      }

      if ( pageStarted )
      {
        if ( useHeader )
        {
          paint.setPen(headerFgColor);
          paint.setFont(headerFont);
          if ( headerDrawBg )
            paint.fillRect(0, 0, headerWidth, headerHeight, headerBgColor);
          if (headerTagList.count() == 3)
          {
            int valign = ( (useBox||headerDrawBg||useBackground) ?
            Qt::AlignVCenter : Qt::AlignTop );
            int align = valign|Qt::AlignLeft;
            int marg = ( useBox || headerDrawBg ) ? innerMargin : 0;
            if ( useBox ) marg += boxWidth;
            QString s;
            for (int i=0; i<3; i++)
            {
              s = headerTagList[i];
              if (s.indexOf("%p") != -1) s.replace("%p", QString::number(currentPage));
              paint.drawText(marg, 0, headerWidth-(marg*2), headerHeight, align, s);
              align = valign|(i == 0 ? Qt::AlignHCenter : Qt::AlignRight);
            }
          }
          if ( ! ( headerDrawBg || useBox || useBackground ) ) // draw a 1 px (!?) line to separate header from contents
          {
            paint.drawLine( 0, headerHeight-1, headerWidth, headerHeight-1 );
            //y += 1; now included in headerHeight
          }
          y += headerHeight + innerMargin;
        }

        if ( useFooter )
        {
          paint.setPen(footerFgColor);
          if ( ! ( footerDrawBg || useBox || useBackground ) ) // draw a 1 px (!?) line to separate footer from contents
            paint.drawLine( 0, maxHeight + innerMargin - 1, headerWidth, maxHeight + innerMargin - 1 );
          if ( footerDrawBg )
            paint.fillRect(0, maxHeight+innerMargin+boxWidth, headerWidth, footerHeight, footerBgColor);
          if (footerTagList.count() == 3)
          {
            int align = Qt::AlignVCenter|Qt::AlignLeft;
            int marg = ( useBox || footerDrawBg ) ? innerMargin : 0;
            if ( useBox ) marg += boxWidth;
            QString s;
            for (int i=0; i<3; i++)
            {
              s = footerTagList[i];
              if (s.indexOf("%p") != -1) s.replace("%p", QString::number(currentPage));
              paint.drawText(marg, maxHeight+innerMargin, headerWidth-(marg*2), footerHeight, align, s);
              align = Qt::AlignVCenter|(i == 0 ? Qt::AlignHCenter : Qt::AlignRight);
            }
          }
        } // done footer

        if ( useBackground )
        {
          // If we have a box, or the header/footer has backgrounds, we want to paint
          // to the border of those. Otherwise just the contents area.
          int _y = y, _h = maxHeight - y;
          if ( useBox )
          {
            _y -= innerMargin;
            _h += 2 * innerMargin;
          }
          else
          {
            if ( headerDrawBg )
            {
              _y -= innerMargin;
              _h += innerMargin;
            }
            if ( footerDrawBg )
            {
              _h += innerMargin;
            }
          }
          paint.fillRect( 0, _y, pdmWidth, _h, renderer.config()->backgroundColor());
        }

        if ( useBox )
        {
          paint.setPen(QPen(boxColor, boxWidth));
          paint.drawRect(0, 0, pdmWidth, pdmHeight);
          if (useHeader)
            paint.drawLine(0, headerHeight, headerWidth, headerHeight);
          else
            y += innerMargin;

          if ( useFooter ) // drawline is not trustable, grr.
            paint.fillRect( 0, maxHeight+innerMargin, headerWidth, boxWidth, boxColor );
        }

        if ( useGuide && currentPage == 1 )
        {  // FIXME - this may span more pages...
          // draw a box unless we have boxes, in which case we end with a box line
          int _ystart = y;
          QString _hlName = doc->highlight()->name();

          QList<KateExtendedAttribute::Ptr> _attributes; // list of highlight attributes for the legend
          doc->highlight()->getKateExtendedAttributeList(kpl->colorScheme(), _attributes);

          KateAttributeList _defaultAttributes;
          KateHlManager::self()->getDefaults ( renderer.config()->schema(), _defaultAttributes );

          QColor _defaultPen = _defaultAttributes.at(0)->foreground().color();
          paint.setPen(_defaultPen);

          int _marg = 0;
          if ( useBox )
            _marg += (2*boxWidth) + (2*innerMargin);
          else
          {
            if ( useBackground )
              _marg += 2*innerMargin;
            _marg += 1;
            y += 1 + innerMargin;
          }

          // draw a title string
          QFont _titleFont = renderer.config()->font();
          _titleFont.setBold(true);
          paint.setFont( _titleFont );
          QRect _r;
          paint.drawText( QRect(_marg, y, pdmWidth-(2*_marg), maxHeight - y),
            Qt::AlignTop|Qt::AlignHCenter,
            i18n("Typographical Conventions for %1", _hlName ), &_r );
          int _w = pdmWidth - (_marg*2) - (innerMargin*2);
          int _x = _marg + innerMargin;
          y += _r.height() + innerMargin;
          paint.drawLine( _x, y, _x + _w, y );
          y += 1 + innerMargin;

          int _widest( 0 );
          foreach (const KateExtendedAttribute::Ptr &attribute, _attributes)
            _widest = qMax(QFontMetrics(attribute->font()).width(attribute->name().section(':',1,1)), _widest);

          int _guideCols = _w/( _widest + innerMargin );

          // draw attrib names using their styles
          int _cw = _w/_guideCols;
          int _i(0);

          _titleFont.setUnderline(true);
          QString _currentHlName;
          foreach (const KateExtendedAttribute::Ptr &attribute, _attributes)
          {
            QString _hl = attribute->name().section(':',0,0);
            QString _name = attribute->name().section(':',1,1);
            if ( _hl != _hlName && _hl != _currentHlName ) {
              _currentHlName = _hl;
              if ( _i%_guideCols )
                y += fontHeight;
              y += innerMargin;
              paint.setFont(_titleFont);
              paint.setPen(_defaultPen);
              paint.drawText( _x, y, _w, fontHeight, Qt::AlignTop, _hl + ' ' + i18n("text") );
              y += fontHeight;
              _i = 0;
            }

            KTextEditor::Attribute _attr =  *_defaultAttributes[attribute->defaultStyleIndex()];
            _attr += *attribute;
            paint.setPen( _attr.foreground().color() );
            paint.setFont( _attr.font() );

            if (_attr.hasProperty(QTextFormat::BackgroundBrush) ) {
              QRect _rect = QFontMetrics(_attr.font()).boundingRect(_name);
              _rect.moveTo(_x + ((_i%_guideCols)*_cw), y);
               paint.fillRect(_rect, _attr.background() );
            }

            paint.drawText(( _x + ((_i%_guideCols)*_cw)), y, _cw, fontHeight, Qt::AlignTop, _name );

            _i++;
            if ( _i && ! ( _i%_guideCols ) )
              y += fontHeight;
          }

          if ( _i%_guideCols )
            y += fontHeight;// last row not full

          // draw a box around the legend
          paint.setPen ( _defaultPen );
          if ( useBox )
            paint.fillRect( 0, y+innerMargin, headerWidth, boxWidth, boxColor );
          else
          {
            _marg -=1;
            paint.drawRect( _marg, _ystart, pdmWidth-(2*_marg), y-_ystart+innerMargin );
          }

          y += ( useBox ? boxWidth : 1 ) + (innerMargin*2);
        } // useGuide

        paint.translate(xstart,y);
        pageStarted = false;
      } // pageStarted; move on to contents:)
Beispiel #27
0
bool Commands::exec(KTextEditor::View *view, const QString &_cmd,
                    QString &msg, const KTextEditor::Range &range)
{
    Q_UNUSED(range)
    // cast it hardcore, we know that it is really a kateview :)
    KTextEditor::ViewPrivate *v = static_cast<KTextEditor::ViewPrivate *>(view);

    if (!v) {
        msg = i18n("Could not access view");
        return false;
    }

    //create a list of args
    QStringList args(_cmd.split(QRegExp(QLatin1String("\\s+")), QString::SkipEmptyParts));
    QString cmd(args.takeFirst());

    // ALL commands that takes no arguments.
    if (mappingCommands().contains(cmd)) {
        if (cmd.endsWith(QLatin1String("unmap"))) {
            if (args.count() == 1) {
                m_viGlobal->mappings()->remove(modeForMapCommand(cmd), args.at(0));
                return true;
            } else {
                msg = i18n("Missing argument. Usage: %1 <from>",  cmd);
                return false;
            }
        }
        if (args.count() == 1) {
            msg = m_viGlobal->mappings()->get(modeForMapCommand(cmd), args.at(0), true);
            if (msg.isEmpty()) {
                msg = i18n("No mapping found for \"%1\"", args.at(0));
                return false;
            } else {
                msg = i18n("\"%1\" is mapped to \"%2\"", args.at(0), msg);
            }
        } else if (args.count() == 2) {
            Mappings::MappingRecursion mappingRecursion = (isMapCommandRecursive(cmd)) ? Mappings::Recursive : Mappings::NonRecursive;
            m_viGlobal->mappings()->add(modeForMapCommand(cmd), args.at(0), args.at(1), mappingRecursion);
        } else {
            msg = i18n("Missing argument(s). Usage: %1 <from> [<to>]",  cmd);
            return false;
        }

        return true;
    }

    NormalViMode *nm = m_viInputModeManager->getViNormalMode();

    if (cmd == QLatin1String("d") || cmd == QLatin1String("delete") || cmd == QLatin1String("j") ||
            cmd == QLatin1String("c") || cmd == QLatin1String("change") ||  cmd == QLatin1String("<") || cmd == QLatin1String(">") ||
            cmd == QLatin1String("y") || cmd == QLatin1String("yank")) {

        KTextEditor::Cursor start_cursor_position = v->cursorPosition();

        int count = 1;
        if (range.isValid()) {
            count = qAbs(range.end().line() - range.start().line()) + 1;
            v->setCursorPosition(KTextEditor::Cursor(qMin(range.start().line(),
                                 range.end().line()), 0));
        }

        QRegExp number(QLatin1String("^(\\d+)$"));
        for (int i = 0; i < args.count(); i++) {
            if (number.indexIn(args.at(i)) != -1) {
                count += number.cap().toInt() - 1;
            }

            QChar r = args.at(i).at(0);
            if (args.at(i).size() == 1 && ((r >= QLatin1Char('a') && r <= QLatin1Char('z')) || r == QLatin1Char('_') || r == QLatin1Char('+') || r == QLatin1Char('*'))) {
                nm->setRegister(r);
            }
        }

        nm->setCount(count);

        if (cmd == QLatin1String("d") || cmd == QLatin1String("delete")) {
            nm->commandDeleteLine();
        }
        if (cmd == QLatin1String("j")) {
            nm->commandJoinLines();
        }
        if (cmd == QLatin1String("c") || cmd == QLatin1String("change")) {
            nm->commandChangeLine();
        }
        if (cmd == QLatin1String("<")) {
            nm->commandUnindentLine();
        }
        if (cmd == QLatin1String(">")) {
            nm->commandIndentLine();
        }
        if (cmd == QLatin1String("y") || cmd == QLatin1String("yank")) {
            nm->commandYankLine();
            v->setCursorPosition(start_cursor_position);
        }

        // TODO - should we resetParser, here? We'd have to make it public, if so.
        // Or maybe synthesise a KateViCommand to execute instead ... ?
        nm->setCount(0);

        return true;
    }

    if (cmd == QLatin1String("mark") || cmd == QLatin1String("ma") || cmd == QLatin1String("k")) {
        if (args.count() == 0) {
            if (cmd == QLatin1String("mark")) {
                // TODO: show up mark list;
            } else {
                msg = i18n("Wrong arguments");
                return false;
            }
        } else if (args.count() == 1) {

            QChar r = args.at(0).at(0);
            int line;
            if ((r >= QLatin1Char('a') && r <= QLatin1Char('z')) || r == QLatin1Char('_') || r == QLatin1Char('+') || r == QLatin1Char('*')) {
                if (range.isValid()) {
                    line = qMax(range.end().line(), range.start().line());
                } else {
                    line = v->cursorPosition().line();
                }

                m_viInputModeManager->marks()->setUserMark(r, KTextEditor::Cursor(line, 0));
            }
        } else {
            msg = i18n("Wrong arguments");
            return false;
        }
        return true;
    }

    // should not happen :)
    msg = i18n("Unknown command '%1'", cmd);
    return false;
}
Beispiel #28
0
void ExporterPluginView::exportData(const bool useSelection, QTextStream &output)
{
  const KTextEditor::Range range = useSelection ? m_view->selectionRange() : m_view->document()->documentRange();
  const bool blockwise = useSelection ? m_view->blockSelection() : false;

  if ( (blockwise || range.onSingleLine()) && (range.start().column() > range.end().column() ) ) {
    return;
  }

  //outputStream.setEncoding(QTextStream::UnicodeUTF8);
  output.setCodec(QTextCodec::codecForName("UTF-8"));

  ///TODO: add more exporters
  AbstractExporter* exporter;

  exporter = new HTMLExporter(m_view, output, !useSelection);

  KTextEditor::HighlightInterface* hiface = qobject_cast<KTextEditor::HighlightInterface*>(m_view->document());

  const KTextEditor::Attribute::Ptr noAttrib(0);

  for (int i = range.start().line(); (i <= range.end().line()) && (i < m_view->document()->lines()); ++i)
  {
    const QString &line = m_view->document()->line(i);

    QList<KTextEditor::HighlightInterface::AttributeBlock> attribs;
    if ( hiface ) {
      attribs = hiface->lineAttributes(i);
    }

    int lineStart = 0;
    int remainingChars = line.length();
    if ( blockwise || range.onSingleLine() ) {
      lineStart = range.start().column();
      remainingChars = range.columnWidth();
    } else if ( i == range.start().line() ) {
      lineStart = range.start().column();
    } else if ( i == range.end().line() ) {
      remainingChars = range.end().column();
    }

    int handledUntil = lineStart;

    foreach ( const KTextEditor::HighlightInterface::AttributeBlock& block, attribs ) {
      // honor (block-) selections
      if ( block.start + block.length <= lineStart ) {
        continue;
      } else if ( block.start >= lineStart + remainingChars ) {
        break;
      }
      int start = qMax(block.start, lineStart);
      if ( start > handledUntil ) {
        exporter->exportText( line.mid( handledUntil, start - handledUntil ), noAttrib );
      }
      int length = qMin(block.length, remainingChars);
      exporter->exportText( line.mid( start, length ), block.attribute);
      handledUntil = start + length;
    }

    if ( handledUntil < lineStart + remainingChars ) {
      exporter->exportText( line.mid( handledUntil, remainingChars ), noAttrib );
    }

    exporter->closeLine(i == range.end().line());
  }

  delete exporter;

  output.flush();
}
Beispiel #29
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 #30
0
QString HighlighterByKate::exportDocument(KTextEditor::Document* note)
{
    QString ret("");
    KTextEditor::Range range;
  
    range = note->documentRange();
  
    KTextEditor::HighlightInterface* hiface = qobject_cast<KTextEditor::HighlightInterface*>(note);

    const KTextEditor::Attribute::Ptr noAttrib(0);
    
    for (int i = 0; i < note->lines(); ++i)
    {
        QString content("");
        const QString &line = note->line(i);

        QList<KTextEditor::HighlightInterface::AttributeBlock> attribs;
        if ( hiface ) {
            attribs = hiface->lineAttributes(i);
        }

        int lineStart = 0;
        int remainingChars = line.length();
        if ( range.onSingleLine() ) {
            lineStart = range.start().column();
            remainingChars = range.columnWidth();
        } else if ( i == range.start().line() ) {
            lineStart = range.start().column();
        } else if ( i == range.end().line() ) {
            remainingChars = range.end().column();
        }

        int handledUntil = lineStart;

        foreach ( const KTextEditor::HighlightInterface::AttributeBlock& block, attribs ) {
            // honor (block-) selections
            if ( block.start + block.length <= lineStart ) {
                continue;
            } else if ( block.start >= lineStart + remainingChars ) {
                break;
            }
            int start = qMax(block.start, lineStart);
            if ( start > handledUntil ) {
                exportText(content, line.mid( handledUntil, start - handledUntil ), noAttrib );
            }
            int length = qMin(block.length, remainingChars);
            exportText(content, line.mid( start, length ), block.attribute);
            handledUntil = start + length;
        }

        if ( handledUntil < lineStart + remainingChars ) {
            exportText(content, line.mid( handledUntil, remainingChars ), noAttrib );
        }
        
        if (i != range.end().line()) {
            ret.append(content.isEmpty() ? "\n" : content);
            ret.append("\n");
        }
    }
    return ret;
}