Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Setting right the size and geometry of custom QStyledItemDelegate
Qt 6.11 is out! See what's new in the release blog

Setting right the size and geometry of custom QStyledItemDelegate

Scheduled Pinned Locked Moved Unsolved General and Desktop
1 Posts 1 Posters 2.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    panosk
    wrote on last edited by
    #1

    Hello,

    I'm trying to figure out how to set right the size and the geometry of a QStyledItemDelegate. The delegate uses a subclassed QTextEdit which adjusts its height dynamically when the users types or deletes text. This is what I've done so far:

    In the subclassed QTextEdit, I'm using the following code:

    CellEditor::CellEditor(const QModelIndex &index, QWidget *parent) :
        QTextEdit(parent), m_text(index.data(Qt::DisplayRole).toString())
    {
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        QTextDocument *doc = new QTextDocument(m_text,this);
        setDocument(doc);
        document()->setDocumentMargin(4); //I want everything to appear fine even if I change the margin...
        setFrameStyle(0);
        connect(this,SIGNAL(textChanged()),this,SLOT(updated()));
    }
    
    void CellEditor::updated()
    {
        const qreal frameBorder = frameWidth(); //currently it's 0
        const qreal requiredHeight = document()->size().height();
        const qreal availableHeight = size().height() - frameBorder;
    
        if (requiredHeight != availableHeight) {
            resize(size().width(), requiredHeight);
        }
    }
    

    In the delegate, I simply create and return the widget in the createEditor function passing the parent and index arguments, I implement the setEditorData and setModelData, and then I try to set the size and geometry like this:

    void CellEditorDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
    {
        editor->setGeometry(option.rect);
    }
    
    QSize CellEditorDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QStyleOptionViewItemV4 optionV4 = option;
        initStyleOption(&optionV4, index);
        QTextDocument doc;
        doc.setPlainText(optionV4.text);
        doc.setTextWidth(optionV4.rect.width());
        return QSize(doc.idealWidth()+2, doc.size().height()+doc.documentMargin()+2); //+2 to adjust for QTableView's grid line widths
    }
    
    void CellEditorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        if (option.state & QStyle::State_Enabled) {
            const QRect rect(option.rect.x()+4,option.rect.y()+4,option.rect.width()-6,option.rect.height()-6);
            painter->drawText(rect,Qt::TextWordWrap,index.data().toString());
            //+4 seems to adjust for the current document's margins, -6 seems to adjust for the current document margins and the QTableView's grid line widths
        } else {
            QStyledItemDelegate::paint(painter,option,index);
        }
    }
    

    In order to notify the model and the view for the size change, I use an event filter:

    bool CellEditorDelegate::eventFilter(QObject *object, QEvent *event)
    {
        bool result = QStyledItemDelegate::eventFilter(object,event);
        QWidget *editor = qobject_cast<QWidget*>(object);
        if(editor) {
            if(event->type() == QEvent::Resize) {
                emit commitData(editor);
            }
        }
        return result;
    }
    

    Here is a screenshot so I can explain better what I want to achieve and what's wrong right now:

    Image

    When the user clicks on a cell to edit the text, I want everything to stay in its current position without any glitches (e.g. slight repositioning of the QTextEdit, different word wrapping, slight overlapping on the grid line, etc). This mostly works ok right now, with the exception that in some cases, after resizing the app window, a word will appear very close to the right edge (although in the paint function it seems that I draw the text with enough margins) so when the user enters the cell the word wrapping will change creating a visual glitch.

    My concern is that I want to get rid of the hard-coded values in the paint function and generally get a better grasp of whole process.

    Many thanks in advance for any hints and advice.

    1 Reply Last reply
    0

    • Login

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved