PDA

View Full Version : Qt 5 "highlight current line" doesn't render properly after "undo"



CmdrMoozy
3rd November 2013, 10:27
I'm working on creating a simple editing component, and one of the things I've added so far is the ability to highlight the current line (just like the CodeEditor demo shows), as well as the ability to indent a group of lines when "Tab" is pressed. However, I have encountered a bug which I simply cannot figure out how to solve - in fact, I'm beginning to suspect that it is a but in Qt's rendering of extra text selections. Here is the simplest example I could write which reproduces this bug:



#include <QApplication>
#include <QMainWindow>
#include <QPlainTextEdit>

#include "HBPlainTextEdit.h"

class HBWindow : public QMainWindow
{
public:
HBWindow(QWidget *p = 0, Qt::WindowFlags f = 0)
: QMainWindow(p, f)
{
editor = new HBPlainTextEdit(this);
setCentralWidget(editor);
}

virtual ~HBWindow()
{
}

private:
HBPlainTextEdit *editor;
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

HBWindow w;
w.show();

return app.exec();
}




#ifndef INCLUDE_HB_PLAIN_TEXT_EDIT_H
#define INCLUDE_HB_PLAIN_TEXT_EDIT_H

#include <QPlainTextEdit>

class QKeyEvent;

class HBPlainTextEdit : public QPlainTextEdit
{
Q_OBJECT

public:
HBPlainTextEdit(QWidget *p = 0);
virtual ~HBPlainTextEdit();

protected:
virtual void keyPressEvent(QKeyEvent *e);

private:
void increaseSelectionIndent();

private slots:
void highlightCurrentLine();
};

#endif




#include "HBPlainTextEdit.h"

#include <QKeyEvent>
#include <QTextBlock>

HBPlainTextEdit::HBPlainTextEdit(QWidget *p)
: QPlainTextEdit(p)
{
QObject::connect( this, SIGNAL( cursorPositionChanged() ),
this, SLOT( highlightCurrentLine() ) );

highlightCurrentLine();
}

HBPlainTextEdit::~HBPlainTextEdit()
{
}

void HBPlainTextEdit::keyPressEvent(QKeyEvent *e)
{
if( (e->modifiers() == Qt::NoModifier) &&
(e->key() == Qt::Key_Tab) &&
textCursor().hasSelection() )
{
e->accept();
increaseSelectionIndent();
}
else
{
QPlainTextEdit::keyPressEvent(e);
}
}

void HBPlainTextEdit::increaseSelectionIndent()
{ /* SLOT */

QTextCursor curs = textCursor();

// Do nothing if we don't have a selection.

if(!curs.hasSelection())
return;

// Get the first and count of lines to indent.

int spos = curs.anchor(), epos = curs.position();

if(spos > epos)
{
int hold = spos;
spos = epos;
epos = hold;
}

curs.setPosition(spos, QTextCursor::MoveAnchor);
int sblock = curs.block().blockNumber();

curs.setPosition(epos, QTextCursor::MoveAnchor);
int eblock = curs.block().blockNumber();

// Do the indent.

curs.setPosition(spos, QTextCursor::MoveAnchor);

curs.beginEditBlock();

for(int i = 0; i <= (eblock - sblock); ++i)
{
curs.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);

curs.insertText("\t");

curs.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor);
}

curs.endEditBlock();

// Set our cursor's selection to span all of the involved lines.

curs.setPosition(spos, QTextCursor::MoveAnchor);
curs.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);

while(curs.block().blockNumber() < eblock)
{
curs.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
}

curs.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);

// Done!

setTextCursor(curs);

}

void HBPlainTextEdit::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> es;
QTextEdit::ExtraSelection selection;

selection.format.setBackground(QColor(175, 175, 175));
selection.format.setProperty(QTextFormat::FullWidt hSelection, true);

selection.cursor = textCursor();
selection.cursor.clearSelection();

es.append(selection);
setExtraSelections(es);
}


So, to reproduce this bug, the following steps should be taken after running this example program:


Select two or more lines of text that have been entered
Press "tab" to indent all of the lines
Press CTRL+Z to undo the previous action
Note that the highlight on the last line no longer extends the full width of the editor


The highlighting can be "fixed" by:


Adding any characters to the broken line
Resizing the window in any way


Does anyone have any insight into what is going wrong, or whether I should be filing a bug on Qt's bug tracker?

CmdrMoozy
3rd December 2013, 03:19
No-one has seen this bug before? :(