void MessagesDialog::sinkMessage( const MsgEvent *msg ) { QMutexLocker locker( &messageLocker ); QPlainTextEdit *messages = ui.messages; /* Only scroll if the viewport is at the end. Don't bug user by auto-changing/losing viewport on insert(). */ bool b_autoscroll = ( messages->verticalScrollBar()->value() + messages->verticalScrollBar()->pageStep() >= messages->verticalScrollBar()->maximum() ); /* Copy selected text to the clipboard */ if( messages->textCursor().hasSelection() ) messages->copy(); /* Fix selected text bug */ if( !messages->textCursor().atEnd() || messages->textCursor().anchor() != messages->textCursor().position() ) messages->moveCursor( QTextCursor::End ); /* Start a new logic block so we can hide it on-demand */ messages->textCursor().insertBlock(); QString buf = QString( "<i><font color='darkblue'>%1</font>" ).arg( msg->module ); switch ( msg->priority ) { case VLC_MSG_INFO: buf += "<font color='blue'> info: </font>"; break; case VLC_MSG_ERR: buf += "<font color='red'> error: </font>"; break; case VLC_MSG_WARN: buf += "<font color='green'> warning: </font>"; break; case VLC_MSG_DBG: default: buf += "<font color='grey'> debug: </font>"; break; } /* Insert the prefix */ messages->textCursor().insertHtml( buf /* + "</i>" */ ); /* Insert the message */ messages->textCursor().insertHtml( msg->text ); /* Pass the new message thru the filter */ QTextBlock b = messages->document()->lastBlock(); b.setVisible( matchFilter( b.text() ) ); /* Tell the QTextDocument to recompute the size of the given area */ messages->document()->markContentsDirty( b.position(), b.length() ); if ( b_autoscroll ) messages->ensureCursorVisible(); }
void CCodeEditor::foldBlocks( int line_start , int line_end ){ QTextBlock bstart = document()->findBlockByLineNumber( line_start ); if( !bstart.isValid()) return; for(int i=line_start; i<line_end && bstart.isValid() ;i++){ bstart.setVisible( false ); bstart = bstart.next(); } viewport()->update(); lineNumberArea->update(); m_foldArea->update(); }
void JSEdit::unfold(int line) { QTextBlock startBlock = document()->findBlockByNumber(line - 1); int endPos = findClosingConstruct(startBlock); QTextBlock block = startBlock.next(); while (block.isValid() && !block.isVisible()) { block.setVisible(true); block.setLineCount(block.layout()->lineCount()); endPos = block.position() + block.length(); block = block.next(); } document()->markContentsDirty(startBlock.position(), endPos - startBlock.position() + 1); updateSidebar(); update(); JSDocLayout *layout = reinterpret_cast<JSDocLayout*>(document()->documentLayout()); layout->forceUpdate(); }
void MessagesDialog::filterMessages() { QMutexLocker locker( &messageLocker ); QPlainTextEdit *messages = ui.messages; QTextBlock block = messages->document()->firstBlock(); while( block.isValid() ) { block.setVisible( matchFilter( block.text().toLower() ) ); block = block.next(); } /* Consider the whole QTextDocument as dirty now */ messages->document()->markContentsDirty( 0, messages->document()->characterCount() ); /* FIXME This solves a bug (Qt?) with the viewport not resizing the vertical scroll bar when one or more QTextBlock are hidden */ QSize vsize = messages->viewport()->size(); messages->viewport()->resize( vsize + QSize( 1, 1 ) ); messages->viewport()->resize( vsize ); }
void BaseTextDocumentLayout::FoldValidator::process(QTextBlock block) { if (!m_layout) return; const QTextBlock &previous = block.previous(); if (!previous.isValid()) return; if ((BaseTextDocumentLayout::isFolded(previous) && !BaseTextDocumentLayout::canFold(previous)) || (!BaseTextDocumentLayout::isFolded(previous) && BaseTextDocumentLayout::canFold(previous) && !block.isVisible())) { BaseTextDocumentLayout::setFolded(previous, !BaseTextDocumentLayout::isFolded(previous)); } if (BaseTextDocumentLayout::isFolded(previous) && !m_insideFold) m_insideFold = BaseTextDocumentLayout::foldingIndent(block); bool toggleVisibility = false; if (m_insideFold) { if (BaseTextDocumentLayout::foldingIndent(block) >= m_insideFold) { if (block.isVisible()) toggleVisibility = true; } else { m_insideFold = 0; if (!block.isVisible()) toggleVisibility = true; } } else if (!block.isVisible()) { toggleVisibility = true; } if (toggleVisibility) { block.setVisible(!block.isVisible()); block.setLineCount(block.isVisible() ? qMax(1, block.layout()->lineCount()) : 0); m_requestDocUpdate = true; } }
void NCEdit::fold(int line) { QTextBlock startBlock = document()->findBlockByNumber(line - 1); int endPos = findClosingConstruct(startBlock); if (endPos < 0) return; QTextBlock endBlock = document()->findBlock(endPos); QTextBlock block = startBlock.next(); while (block.isValid() && block != endBlock) { block.setVisible(false); block.setLineCount(0); block = block.next(); } document()->markContentsDirty(startBlock.position(), endPos - startBlock.position() + 1); updateSidebar(); update(); NCDocLayout *layout = reinterpret_cast<NCDocLayout*>(document()->documentLayout()); layout->forceUpdate(); }
void BaseTextDocumentLayout::doFoldOrUnfold(const QTextBlock& block, bool unfold) { if (!canFold(block)) return; QTextBlock b = block.next(); int indent = foldingIndent(block); while (b.isValid() && foldingIndent(b) > indent && (unfold || b.next().isValid())) { b.setVisible(unfold); b.setLineCount(unfold? qMax(1, b.layout()->lineCount()) : 0); if (unfold) { // do not unfold folded sub-blocks if (isFolded(b) && b.next().isValid()) { int jndent = foldingIndent(b); b = b.next(); while (b.isValid() && foldingIndent(b) > jndent) b = b.next(); continue; } } b = b.next(); } setFolded(block, !unfold); }
void CodeEditor::contentsChange(int pos, int, int) { QTextBlock block = textCursor().block(); // сдвиг блока клавишей Return // состояние предыдущего блока может быть не верным if (block.userState() == Empty) block.setUserState(block.previous().userState() | Rehighligh); block = document()->findBlock(pos); int startBlockNum = block.blockNumber(); bool forceUnfold = false; while (block.isValid()) { int previousState = block.userState(); int state = setBlockState(block); if (!(previousState & Error) && !(state & Error) && previousState & Comment && state & Comment) { QTextBlock next = block.next(); int nextBlockState = next.userState(); setBlockState(next); next.setUserState(nextBlockState); // в начальное состояние // правильное состояние комментария известно // только после обработки последующей строки state = block.userState(); } if (state != previousState) { if (!forceUnfold) { // разворачиваем предыдущие блоки QTextBlock previous = block.previous(); while (previous.isValid()) { int state = previous.userState(); if (!(state & Error) && state & Folded) previous.setUserState(state & ~Folded); if (state & Error || !(state & Nested) || previous.isVisible()) break; previous.setVisible(true); previous = previous.previous(); } } forceUnfold = true; } else if (block.blockNumber() > startBlockNum && // не начальный блок state & Begin && !(state & Nested)) { // (state & Begin ...) пропускаем End главного блока break; // без state & Error, иначе срабатывает между блоками } // при первом обновлении if (forceUnfold) { // разворачиваем последующие блоки if (!(state & Error) && state & Folded) state &= ~Folded; block.setVisible(true); } block.setUserState(state | Rehighligh); block = block.next(); } }
void TextBlockUserData::doCollapse(const QTextBlock& block, bool visible) { QTextBlock info = block; if (block.userData() && static_cast<TextBlockUserData*>(block.userData())->collapseMode() == CollapseAfter) ; else if (block.next().userData() && static_cast<TextBlockUserData*>(block.next().userData())->collapseMode() == TextBlockUserData::CollapseThis) info = block.next(); else { if (visible && !block.next().isVisible()) { // no match, at least unfold! QTextBlock b = block.next(); while (b.isValid() && !b.isVisible()) { b.setVisible(true); b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0); b = b.next(); } } return; } int pos = static_cast<TextBlockUserData*>(info.userData())->collapseAtPos(); if (pos < 0) return; QTextCursor cursor(info); cursor.setPosition(cursor.position() + pos); if (matchCursorForward(&cursor) != Match) { if (visible) { // no match, at least unfold! QTextBlock b = block.next(); while (b.isValid() && !b.isVisible()) { b.setVisible(true); b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0); b = b.next(); } } return; } QTextBlock b = block.next(); while (b < cursor.block()) { b.setVisible(visible); b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0); if (visible) { TextBlockUserData *data = canCollapse(b); if (data && data->collapsed()) { QTextBlock end = testCollapse(b); if (data->collapseIncludesClosure()) end = end.next(); if (end.isValid()) { b = end; continue; } } } b = b.next(); } bool collapseIncludesClosure = hasClosingCollapseAtEnd(b); if (collapseIncludesClosure) { b.setVisible(visible); b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0); } static_cast<TextBlockUserData*>(info.userData())->setCollapseIncludesClosure(collapseIncludesClosure); static_cast<TextBlockUserData*>(info.userData())->setCollapsed(!block.next().isVisible()); }