[Interest] QAbstractTableModel: ItemDelegate for both display and edit role
Ch'Gans
chgans at gna.org
Sun Jun 8 03:55:48 CEST 2014
Hi Adam,
Thank you for your code snip, I used the persistent editor approach, as
my table will never contains more than a dozen rows, I think this is OK.
Another thing I have been fighting with, was to have my editor centered
in the table cells, I found 2 interesting results [1], [2] But I didn't
like them (too much code). My solution is amazingly more simple and
gives me perfect result, I only override updateEditorGeometry() and
paint() in my ItemDelegate this way:
void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
Q_UNUSED(index)
// Center the editor in the cell
QRect geom = QStyle::alignedRect(option.direction, Qt::AlignCenter,
editor->sizeHint(),
option.rect);
editor->setGeometry(geom);
}
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
// Don't paint anything
Q_UNUSED(painter)
Q_UNUSED(option)
Q_UNUSED(index)
return;
}
Krys,
[1]
https://stackoverflow.com/questions/2785434/how-to-interact-with-checkbox-actions-qtableview-with-qstandarditemmodel/4451324#4451324
[2]
https://qt-project.org/faq/answer/how_can_i_align_the_checkboxes_in_a_view
On 07/06/14 01:16, Adam Light wrote:
> [Replying to the list this time as well]
>
>
> On Thu, Jun 5, 2014 at 7:38 PM, Christian Gagneraud <chgans at gna.org
> <mailto:chgans at gna.org>> wrote:
>
> Hi all,
>
> I would like to use item delegates to both display and edit items using
> QAbstractTableModel/QTableView.
> I was able to get my specialised widget used when the user *edit* the
> field but I would like to have the same widget used for displaying the
> field as well.
>
> My QStyledItemDelegate based delegated reimplements these functions:
> - createEditor
> - setEditorData
> - setModelData
> - updateEditorGeometry
>
> I would like to know if the only way to have my widget used for both the
> display role and the edit role is to reimplement as well paint() and
> sizeHint(). If not, can anyone point me at docs or example?
>
>
> You could do what we do in our application and set all cells (or certain
> cells) of the view to use persistent editors
> (http://qt-project.org/doc/qt-4.8/qabstractitemview.html#openPersistentEditor).
>
> If you go that way, it's a bit tricky because you need to call
> openPersistentEditor() in a number of different situations. Here are
> some methods from WMTableView, a relatively simple QTableView subclass
> we use in our application to handle this situation:
>
> /**
>
> \brief Constructs a WMTableView with with parent \a parent.
>
> */
>
> WMTableView::WMTableView(QWidget* parent) :
>
> QTableView(parent),
>
> _nextAndPreviousMoveToEditableCell(true),
>
> _persistentEditorUpdateTimerStarted(false),
>
> _updatingPersistentEditorColumns(false)
>
> {
>
> // Set a style sheet to provide a bit of spacing between cells. This is necessary
>
> // so that the error frame around any widgets in the table is not covered
>
> // up on Windows by widgets in adjacent cells.
>
> setStyleSheet(QLatin1String("WMTableView::item {margin: 2px;}"));
>
>
> // Force the persistence of editors in each cell to update when
>
> // the number of rows or columns changes or the model is reset.
>
> connect(verticalHeader(), SIGNAL(sectionCountChanged(int,int)), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> connect(horizontalHeader(), SIGNAL(sectionCountChanged(int,int)), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> }
>
>
> /**
>
> \brief Sets all columns in \a colList to use persistently open editors.
>
>
> All columns not in \a colList will be treated as not persistently open editors.
>
> */
>
> void WMTableView::setPersistentEditorColumns(const QList<int> colList) {
>
> _persistentEditorColumns = colList;
>
> _scheduleUpdateOfPersistentEditorColumns();
>
> }
>
>
> /**
>
> \reimp
>
> */
>
> void WMTableView::setModel(QAbstractItemModel *newModel) {
>
> // We need to make sure that _scheduleUpdateOfPersistentEditorColumns() is called
>
> // when the model is reset.
>
>
> QAbstractItemModel* oldModel = model();
>
>
> if (newModel == oldModel) {
>
> return;
>
> }
>
>
> QTableView::setModel(newModel);
>
>
> // Disconnect, if necessary.
>
> if (oldModel) {
>
> // Disconnect connections to old model.
>
> disconnect(oldModel, SIGNAL(modelReset()), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> disconnect(oldModel, SIGNAL(layoutChanged()), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> disconnect(oldModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> disconnect(oldModel, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> disconnect(oldModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(_onModelsDataChanged(QModelIndex,QModelIndex)));
>
> }
>
>
> // Make new connections, if necessary.
>
> if (newModel) {
>
> connect(newModel, SIGNAL(modelReset()), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> connect(newModel, SIGNAL(layoutChanged()), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> connect(newModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> connect(newModel, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(_scheduleUpdateOfPersistentEditorColumns()));
>
> connect(newModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(_onModelsDataChanged(QModelIndex,QModelIndex)));
>
> }
>
> }
>
>
> /**
>
> \brief Opens or closes persistent editors in each cell of the view as appropriate.
>
>
> Do not call this method directly. Call _scheduleUpdateOfPersistentEditorColumns() instead.
>
> */
>
> void WMTableView::_updatePersistentEditorColumns() {
>
> // This slot should only be called by the single shot timer created
>
> // in _scheduleUpdateOfPersistentEditorColumns() to
>
> // improve performance and try to prevent crashes.
>
> Q_ASSERT(_persistentEditorUpdateTimerStarted);
>
>
> _persistentEditorUpdateTimerStarted = false;
>
>
> if (_updatingPersistentEditorColumns) {
>
> // Block recursion, though this should never happen (I think).
>
> // If this does happen, then the single shot timer that calls this method needs to be recreated.
>
> Q_ASSERT(0);
>
> return;
>
> }
>
>
> _updatingPersistentEditorColumns = true;
>
> QAbstractItemModel* theModel = model();
>
> if (theModel) {
>
> int numRows = model()->rowCount(rootIndex());
>
> int numCols = model()->columnCount(rootIndex());
>
> for (int colNum = 0; colNum < numCols; ++colNum) {
>
> int columnXPosition = columnViewportPosition(colNum);
>
> bool columnIsPersistent = _persistentEditorColumns.contains(colNum);
>
> for (int rowNum = 0; rowNum < numRows; ++rowNum) {
>
> QPoint cellPoint(columnXPosition, rowViewportPosition(rowNum));
>
> QModelIndex childIndex = indexAt(cellPoint);
>
> if (childIndex.isValid()) {
>
> if (columnIsPersistent && ((childIndex.flags() & Qt::ItemIsEditable) != 0)) {
>
> openPersistentEditor(childIndex);
>
> QWidget* editor = indexWidget(childIndex);
>
> QLineEdit* le = qobject_cast<QLineEdit*>(editor);
>
> if (le) {
>
> if (currentIndex() != childIndex) {
>
> le->deselect();
>
> }
>
> }
>
> }
>
> else {
>
> closePersistentEditor(childIndex);
>
> }
>
> }
>
> }
>
> }
>
> }
>
> _updatingPersistentEditorColumns = false;
>
> }
>
>
> /**
>
> \brief Schedules/queues an update of the persistent editor columns
>
> if one is not already scheduled.
>
>
> Calling this slot instead of _updatePersistentEditorColumns() directly
>
> is more efficient and can prevent crashes that can result when
>
> _updatePersistentEditorColumns() is called multiple times in a row.
>
> */
>
> void WMTableView::_scheduleUpdateOfPersistentEditorColumns() {
>
> if (!_persistentEditorUpdateTimerStarted) {
>
> QTimer::singleShot(0, this, SLOT(_updatePersistentEditorColumns()));
>
> _persistentEditorUpdateTimerStarted = true;
>
> }
>
> }
>
>
> /**
>
> \brief Opens/closes or updates persistent editors throughout the view.
>
> */
>
> void WMTableView::_onModelsDataChanged(const QModelIndex &first, const QModelIndex &last) {
>
> Q_UNUSED(first);
>
> Q_UNUSED(last);
>
> _scheduleUpdateOfPersistentEditorColumns();
>
> }
>
>
>
--
QtCreator/qmakeparser.cpp:42
////////// Parser ///////////
#define fL1S(s) QString::fromLatin1(s)
namespace { // MSVC2010 doesn't seem to know the semantics of "static" ...
More information about the Interest
mailing list