Reputation: 3811
I have subclassed QAbstractTableModel and QTabelView (and QSortFilterProxyModel) and I'd like to allow multi-line text to be displayed to and entered by the user in text cells (currently, hitting return will confirm the edit instead of inserting a line break).
There should be some simple flag to set, I just don't know which one...
Upvotes: 1
Views: 2172
Reputation: 1997
QItemDelegate
can actually draw the text over multiple lines (if it contains explicit '\n' characters), while the default QStyledItemDelegate
doesn't do that (at least not on Linux, I didn't test other platforms). So we'll need to use QItemDelegate
for the rendering.
But we also need to change the widget used for editing, which can't be a QLineEdit
anymore, it needs to be a QPlainTextEdit
. So we'll have to derive from QItemDelegate
and change the type of widget being created for editing.
#ifndef MULTILINEDELEGATE_H
#define MULTILINEDELEGATE_H
#include <QItemDelegate>
class MultilineDelegate : public QItemDelegate
{
Q_OBJECT
public:
using QItemDelegate::QItemDelegate;
public:
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
};
#endif
#include "multilinedelegate.h"
#include <QPlainTextEdit>
QWidget *MultilineDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
return new QPlainTextEdit(parent);
}
void MultilineDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if (auto *textEdit = qobject_cast<QPlainTextEdit *>(editor)) {
textEdit->setPlainText(index.data(Qt::EditRole).toString());
} else {
QItemDelegate::setEditorData(editor, index);
}
}
void MultilineDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if (auto *textEdit = qobject_cast<QPlainTextEdit *>(editor)) {
model->setData(index, textEdit->toPlainText());
} else {
QItemDelegate::setModelData(editor, model, index);
}
}
And now all that remains to be done is using that delegate on the appropriate columns. For instance tableView->setItemDelegateForColumn(MyModel::AddressColumn, new MultilineDelegate(this));
This also looks better if the rows grow vertically as needed:
tableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
Tested with Qt 5.15, hopefully it should work with Qt 6 as well.
Upvotes: 2
Reputation: 2829
Not entirely sure what you are asking but I'll assume you already have your cell set up with a widget that can accept multi-line input (i.e. QTextEdit
using setItem
on your QTableView
).
If you have that, I believe you would want to create a custom QItemDelegate
derived class and override the default Enter behaviour to insert a line break rather than committing the delegate's data as is the default behaviour
See http://qt-project.org/doc/qt-4.8/qitemdelegate.html#eventFilter to get you started in the right direction.
Upvotes: 1