[Interest] QAbstractTableModel: ItemDelegate for both display and edit role
Filip Piechocki
fpiechocki at gmail.com
Fri Jun 6 15:29:50 CEST 2014
But persistent editors are quite heavy. Another way is to paint the
"screenshot" of your editor in the cell with in a paint() method of your
delegate. So you can have just one hidden instance of your widget, set data
to it and use QWidget::render() to paint it in the cell.
BR,
Filip Piechocki
On Fri, Jun 6, 2014 at 3:16 PM, Adam Light <aclight at gmail.com> wrote:
> [Replying to the list this time as well]
>
>
> On Thu, Jun 5, 2014 at 7:38 PM, Christian Gagneraud <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();
>
> }
>
>
>
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20140606/b77b7b85/attachment.html>
More information about the Interest
mailing list