Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdatawidgetmapper.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
8#include "qmetaobject.h"
9#include "qwidget.h"
11
12#include "private/qobject_p.h"
13#include "private/qabstractitemmodel_p.h"
14#include <QtCore/qpointer.h>
15
16#include <array>
17#include <iterator>
18
19QT_BEGIN_NAMESPACE
20
21class QDataWidgetMapperPrivate: public QObjectPrivate
22{
23public:
24 Q_DECLARE_PUBLIC(QDataWidgetMapper)
25
26 QDataWidgetMapperPrivate()
27 : model(QAbstractItemModelPrivate::staticEmptyModel()), delegate(nullptr),
28 orientation(Qt::Horizontal), submitPolicy(QDataWidgetMapper::AutoSubmit)
29 {
30 }
31
32 QAbstractItemModel *model;
33 QAbstractItemDelegate *delegate;
34 Qt::Orientation orientation;
35 QDataWidgetMapper::SubmitPolicy submitPolicy;
36 QPersistentModelIndex rootIndex;
37 QPersistentModelIndex currentTopLeft;
38
39 inline int itemCount()
40 {
41 return orientation == Qt::Horizontal
42 ? model->rowCount(rootIndex)
43 : model->columnCount(rootIndex);
44 }
45
46 inline int currentIdx() const
47 {
48 return orientation == Qt::Horizontal ? currentTopLeft.row() : currentTopLeft.column();
49 }
50
51 inline QModelIndex indexAt(int itemPos)
52 {
53 return orientation == Qt::Horizontal
54 ? model->index(currentIdx(), itemPos, rootIndex)
55 : model->index(itemPos, currentIdx(), rootIndex);
56 }
57
58 void flipEventFilters(QAbstractItemDelegate *oldDelegate,
59 QAbstractItemDelegate *newDelegate) const
60 {
61 for (const WidgetMapper &e : widgetMap) {
62 QWidget *w = e.widget;
63 if (!w)
64 continue;
65 w->removeEventFilter(oldDelegate);
66 w->installEventFilter(newDelegate);
67 }
68 }
69
70 void populate();
71
72 // private slots
73 void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
74 const QList<int> &);
75 void commitData(QWidget *);
76 void closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint);
77 void modelDestroyed();
78
79 void disconnectModel()
80 {
81 for (const QMetaObject::Connection &connection : modelConnections)
82 QObject::disconnect(connection);
83 }
84 void disconnectDelegate()
85 {
86 for (const QMetaObject::Connection &connection : delegateConnections)
87 QObject::disconnect(connection);
88 }
89
90 struct WidgetMapper
91 {
92 QPointer<QWidget> widget;
93 int section;
94 QPersistentModelIndex currentIndex;
95 QByteArray property;
96 };
97
98 void populate(WidgetMapper &m);
99 int findWidget(QWidget *w) const;
100
101 bool commit(const WidgetMapper &m);
102
103 std::vector<WidgetMapper> widgetMap;
104 std::array<QMetaObject::Connection, 2> modelConnections;
105 std::array<QMetaObject::Connection, 2> delegateConnections;
106};
107Q_DECLARE_TYPEINFO(QDataWidgetMapperPrivate::WidgetMapper, Q_RELOCATABLE_TYPE);
108
109int QDataWidgetMapperPrivate::findWidget(QWidget *w) const
110{
111 for (const WidgetMapper &e : widgetMap) {
112 if (e.widget == w)
113 return int(&e - &widgetMap.front());
114 }
115 return -1;
116}
117
118bool QDataWidgetMapperPrivate::commit(const WidgetMapper &m)
119{
120 if (m.widget.isNull())
121 return true; // just ignore
122
123 if (!m.currentIndex.isValid())
124 return false;
125
126 // Create copy to avoid passing the widget mappers data
127 QModelIndex idx = m.currentIndex;
128 if (m.property.isEmpty())
129 delegate->setModelData(m.widget, model, idx);
130 else
131 model->setData(idx, m.widget->property(m.property), Qt::EditRole);
132
133 return true;
134}
135
136void QDataWidgetMapperPrivate::populate(WidgetMapper &m)
137{
138 if (m.widget.isNull())
139 return;
140
141 m.currentIndex = indexAt(m.section);
142 if (m.property.isEmpty())
143 delegate->setEditorData(m.widget, m.currentIndex);
144 else
145 m.widget->setProperty(m.property, m.currentIndex.data(Qt::EditRole));
146}
147
148void QDataWidgetMapperPrivate::populate()
149{
150 for (WidgetMapper &e : widgetMap)
151 populate(e);
152}
153
154static bool qContainsIndex(const QModelIndex &idx, const QModelIndex &topLeft,
155 const QModelIndex &bottomRight)
156{
157 return idx.row() >= topLeft.row() && idx.row() <= bottomRight.row()
158 && idx.column() >= topLeft.column() && idx.column() <= bottomRight.column();
159}
160
161void QDataWidgetMapperPrivate::dataChanged(const QModelIndex &topLeft,
162 const QModelIndex &bottomRight, const QList<int> &)
163{
164 if (topLeft.parent() != rootIndex)
165 return; // not in our hierarchy
166
167 for (WidgetMapper &e : widgetMap) {
168 if (qContainsIndex(e.currentIndex, topLeft, bottomRight))
169 populate(e);
170 }
171}
172
173void QDataWidgetMapperPrivate::commitData(QWidget *w)
174{
175 if (submitPolicy == QDataWidgetMapper::ManualSubmit)
176 return;
177
178 int idx = findWidget(w);
179 if (idx == -1)
180 return; // not our widget
181
182 commit(widgetMap[idx]);
183}
184
185void QDataWidgetMapperPrivate::closeEditor(QWidget *w, QAbstractItemDelegate::EndEditHint hint)
186{
187 int idx = findWidget(w);
188 if (idx == -1)
189 return; // not our widget
190
191 switch (hint) {
192 case QAbstractItemDelegate::RevertModelCache: {
193 populate(widgetMap[idx]);
194 break; }
195 case QAbstractItemDelegate::EditNextItem:
196 w->focusNextChild();
197 break;
198 case QAbstractItemDelegate::EditPreviousItem:
199 w->focusPreviousChild();
200 break;
201 case QAbstractItemDelegate::SubmitModelCache:
202 case QAbstractItemDelegate::NoHint:
203 // nothing
204 break;
205 }
206}
207
208void QDataWidgetMapperPrivate::modelDestroyed()
209{
210 Q_Q(QDataWidgetMapper);
211
212 model = nullptr;
213 q->setModel(QAbstractItemModelPrivate::staticEmptyModel());
214}
215
216/*!
217 \class QDataWidgetMapper
218 \brief The QDataWidgetMapper class provides mapping between a section
219 of a data model to widgets.
220 \ingroup model-view
221 \ingroup advanced
222 \inmodule QtWidgets
223
224 QDataWidgetMapper can be used to create data-aware widgets by mapping
225 them to sections of an item model. A section is a column of a model
226 if the orientation is horizontal (the default), otherwise a row.
227
228 Every time the current index changes, each widget is updated with data
229 from the model via the property specified when its mapping was made.
230 If the user edits the contents of a widget, the changes are read using
231 the same property and written back to the model.
232 By default, each widget's \l{Q_PROPERTY()}{user property} is used to
233 transfer data between the model and the widget. Since Qt 4.3, an
234 additional addMapping() function enables a named property to be used
235 instead of the default user property.
236
237 It is possible to set an item delegate to support custom widgets. By default,
238 a QStyledItemDelegate is used to synchronize the model with the widgets.
239
240 Let us assume that we have an item model named \c{model} with the following contents:
241
242 \table
243 \row \li 1 \li Qt Norway \li Oslo
244 \row \li 2 \li Qt Australia \li Brisbane
245 \row \li 3 \li Qt USA \li Palo Alto
246 \row \li 4 \li Qt China \li Beijing
247 \row \li 5 \li Qt Germany \li Berlin
248 \endtable
249
250 The following code will map the columns of the model to widgets called \c mySpinBox,
251 \c myLineEdit and \c{myCountryChooser}:
252
253 \snippet code/src_gui_itemviews_qdatawidgetmapper.cpp 0
254
255 After the call to toFirst(), \c mySpinBox displays the value \c{1}, \c myLineEdit
256 displays \c{Qt Norway} and \c myCountryChooser displays \c{Oslo}. The
257 navigational functions toFirst(), toNext(), toPrevious(), toLast() and setCurrentIndex()
258 can be used to navigate in the model and update the widgets with contents from
259 the model.
260
261 The setRootIndex() function enables a particular item in a model to be
262 specified as the root index - children of this item will be mapped to
263 the relevant widgets in the user interface.
264
265 QDataWidgetMapper supports two submit policies, \c AutoSubmit and \c{ManualSubmit}.
266 \c AutoSubmit will update the model as soon as the current widget loses focus,
267 \c ManualSubmit will not update the model unless submit() is called. \c ManualSubmit
268 is useful when displaying a dialog that lets the user cancel all modifications.
269 Also, other views that display the model won't update until the user finishes
270 all their modifications and submits.
271
272 Note that QDataWidgetMapper keeps track of external modifications. If the contents
273 of the model are updated in another module of the application, the widgets are
274 updated as well.
275
276 \sa QAbstractItemModel, QAbstractItemDelegate
277 */
278
279/*! \enum QDataWidgetMapper::SubmitPolicy
280
281 This enum describes the possible submit policies a QDataWidgetMapper
282 supports.
283
284 \value AutoSubmit Whenever a widget loses focus, the widget's current
285 value is set to the item model.
286 \value ManualSubmit The model is not updated until submit() is called.
287 */
288
289/*!
290 \fn void QDataWidgetMapper::currentIndexChanged(int index)
291
292 This signal is emitted after the current index has changed and
293 all widgets were populated with new data. \a index is the new
294 current index.
295
296 \sa currentIndex(), setCurrentIndex()
297 */
298
299/*!
300 Constructs a new QDataWidgetMapper with parent object \a parent.
301 By default, the orientation is horizontal and the submit policy
302 is \c{AutoSubmit}.
303
304 \sa setOrientation(), setSubmitPolicy()
305 */
306QDataWidgetMapper::QDataWidgetMapper(QObject *parent)
307 : QObject(*new QDataWidgetMapperPrivate, parent)
308{
309 setItemDelegate(new QStyledItemDelegate(this));
310}
311
312/*!
313 Destroys the object.
314 */
315QDataWidgetMapper::~QDataWidgetMapper()
316{
317 Q_D(QDataWidgetMapper);
318 d->disconnectModel();
319 d->disconnectDelegate();
320}
321
322/*!
323 Sets the current model to \a model. If another model was set,
324 all mappings to that old model are cleared.
325
326 \sa model()
327 */
328void QDataWidgetMapper::setModel(QAbstractItemModel *model)
329{
330 Q_D(QDataWidgetMapper);
331
332 if (d->model == model)
333 return;
334
335 d->disconnectModel();
336 clearMapping();
337 d->rootIndex = QModelIndex();
338 d->currentTopLeft = QModelIndex();
339
340 d->model = model;
341
342 d->modelConnections = {
343 QObjectPrivate::connect(model, &QAbstractItemModel::dataChanged,
344 d, &QDataWidgetMapperPrivate::dataChanged),
345 QObjectPrivate::connect(model, &QAbstractItemModel::destroyed,
346 d, &QDataWidgetMapperPrivate::modelDestroyed)
347 };
348}
349
350/*!
351 Returns the current model.
352
353 \sa setModel()
354 */
355QAbstractItemModel *QDataWidgetMapper::model() const
356{
357 Q_D(const QDataWidgetMapper);
358 return d->model == QAbstractItemModelPrivate::staticEmptyModel()
359 ? static_cast<QAbstractItemModel *>(nullptr)
360 : d->model;
361}
362
363/*!
364 Sets the item delegate to \a delegate. The delegate will be used to write
365 data from the model into the widget and from the widget to the model,
366 using QAbstractItemDelegate::setEditorData() and QAbstractItemDelegate::setModelData().
367
368 Any existing delegate will be removed, but not deleted. QDataWidgetMapper
369 does not take ownership of \a delegate.
370
371 The delegate also decides when to apply data and when to change the editor,
372 using QAbstractItemDelegate::commitData() and QAbstractItemDelegate::closeEditor().
373
374 \warning You should not share the same instance of a delegate between widget mappers
375 or views. Doing so can cause incorrect or unintuitive editing behavior since each
376 view connected to a given delegate may receive the \l{QAbstractItemDelegate::}{closeEditor()}
377 signal, and attempt to access, modify or close an editor that has already been closed.
378 */
379void QDataWidgetMapper::setItemDelegate(QAbstractItemDelegate *delegate)
380{
381 Q_D(QDataWidgetMapper);
382 QAbstractItemDelegate *oldDelegate = d->delegate;
383 d->disconnectDelegate();
384
385 d->delegate = delegate;
386
387 if (delegate) {
388 d->delegateConnections = {
389 QObjectPrivate::connect(delegate, &QAbstractItemDelegate::commitData,
390 d, &QDataWidgetMapperPrivate::commitData),
391 QObjectPrivate::connect(delegate, &QAbstractItemDelegate::closeEditor,
392 d, &QDataWidgetMapperPrivate::closeEditor)
393 };
394 }
395
396 d->flipEventFilters(oldDelegate, delegate);
397}
398
399/*!
400 Returns the current item delegate.
401 */
402QAbstractItemDelegate *QDataWidgetMapper::itemDelegate() const
403{
404 Q_D(const QDataWidgetMapper);
405 return d->delegate;
406}
407
408/*!
409 Sets the root item to \a index. This can be used to display
410 a branch of a tree. Pass an invalid model index to display
411 the top-most branch.
412
413 \sa rootIndex()
414 */
415void QDataWidgetMapper::setRootIndex(const QModelIndex &index)
416{
417 Q_D(QDataWidgetMapper);
418 d->rootIndex = index;
419}
420
421/*!
422 Returns the current root index.
423
424 \sa setRootIndex()
425*/
426QModelIndex QDataWidgetMapper::rootIndex() const
427{
428 Q_D(const QDataWidgetMapper);
429 return QModelIndex(d->rootIndex);
430}
431
432/*!
433 Adds a mapping between a \a widget and a \a section from the model.
434 The \a section is a column in the model if the orientation is
435 horizontal (the default), otherwise a row.
436
437 For the following example, we assume a model \c myModel that
438 has two columns: the first one contains the names of people in a
439 group, and the second column contains their ages. The first column
440 is mapped to the QLineEdit \c nameLineEdit, and the second is
441 mapped to the QSpinBox \c{ageSpinBox}:
442
443 \snippet code/src_gui_itemviews_qdatawidgetmapper.cpp 1
444
445 \b{Notes:}
446 \list
447 \li If the \a widget is already mapped to a section, the
448 old mapping will be replaced by the new one.
449 \li Only one-to-one mappings between sections and widgets are allowed.
450 It is not possible to map a single section to multiple widgets, or to
451 map a single widget to multiple sections.
452 \endlist
453
454 \sa removeMapping(), mappedSection(), clearMapping()
455 */
456void QDataWidgetMapper::addMapping(QWidget *widget, int section)
457{
458 Q_D(QDataWidgetMapper);
459
460 removeMapping(widget);
461 d->widgetMap.push_back({widget, section, d->indexAt(section), QByteArray()});
462 widget->installEventFilter(d->delegate);
463}
464
465/*!
466 Essentially the same as addMapping(), but adds the possibility to specify
467 the property to use specifying \a propertyName.
468
469 \sa addMapping()
470*/
471
472void QDataWidgetMapper::addMapping(QWidget *widget, int section, const QByteArray &propertyName)
473{
474 Q_D(QDataWidgetMapper);
475
476 removeMapping(widget);
477 d->widgetMap.push_back({widget, section, d->indexAt(section), propertyName});
478 widget->installEventFilter(d->delegate);
479}
480
481/*!
482 Removes the mapping for the given \a widget.
483
484 \sa addMapping(), clearMapping()
485 */
486void QDataWidgetMapper::removeMapping(QWidget *widget)
487{
488 Q_D(QDataWidgetMapper);
489
490 int idx = d->findWidget(widget);
491 if (idx == -1)
492 return;
493
494 d->widgetMap.erase(d->widgetMap.begin() + idx);
495 widget->removeEventFilter(d->delegate);
496}
497
498/*!
499 Returns the section the \a widget is mapped to or -1
500 if the widget is not mapped.
501
502 \sa addMapping(), removeMapping()
503 */
504int QDataWidgetMapper::mappedSection(QWidget *widget) const
505{
506 Q_D(const QDataWidgetMapper);
507
508 int idx = d->findWidget(widget);
509 if (idx == -1)
510 return -1;
511
512 return d->widgetMap[idx].section;
513}
514
515/*!
516 Returns the name of the property that is used when mapping
517 data to the given \a widget.
518
519 \sa mappedSection(), addMapping(), removeMapping()
520*/
521
522QByteArray QDataWidgetMapper::mappedPropertyName(QWidget *widget) const
523{
524 Q_D(const QDataWidgetMapper);
525
526 int idx = d->findWidget(widget);
527 if (idx == -1)
528 return QByteArray();
529 const auto &m = d->widgetMap[idx];
530 if (m.property.isEmpty())
531 return m.widget->metaObject()->userProperty().name();
532 else
533 return m.property;
534}
535
536/*!
537 Returns the widget that is mapped at \a section, or
538 0 if no widget is mapped at that section.
539
540 \sa addMapping(), removeMapping()
541 */
542QWidget *QDataWidgetMapper::mappedWidgetAt(int section) const
543{
544 Q_D(const QDataWidgetMapper);
545
546 for (auto &e : d->widgetMap) {
547 if (e.section == section)
548 return e.widget;
549 }
550
551 return nullptr;
552}
553
554/*!
555 Repopulates all widgets with the current data of the model.
556 All unsubmitted changes will be lost.
557
558 \sa submit(), setSubmitPolicy()
559 */
560void QDataWidgetMapper::revert()
561{
562 Q_D(QDataWidgetMapper);
563
564 d->populate();
565}
566
567/*!
568 Submits all changes from the mapped widgets to the model.
569
570 For every mapped section, the item delegate reads the current
571 value from the widget and sets it in the model. Finally, the
572 model's \l {QAbstractItemModel::}{submit()} method is invoked.
573
574 Returns \c true if all the values were submitted, otherwise false.
575
576 Note: For database models, QSqlQueryModel::lastError() can be
577 used to retrieve the last error.
578
579 \sa revert(), setSubmitPolicy()
580 */
581bool QDataWidgetMapper::submit()
582{
583 Q_D(QDataWidgetMapper);
584
585 for (auto &e : d->widgetMap) {
586 if (!d->commit(e))
587 return false;
588 }
589
590 return d->model->submit();
591}
592
593/*!
594 Populates the widgets with data from the first row of the model
595 if the orientation is horizontal (the default), otherwise
596 with data from the first column.
597
598 This is equivalent to calling \c setCurrentIndex(0).
599
600 \sa toLast(), setCurrentIndex()
601 */
602void QDataWidgetMapper::toFirst()
603{
604 setCurrentIndex(0);
605}
606
607/*!
608 Populates the widgets with data from the last row of the model
609 if the orientation is horizontal (the default), otherwise
610 with data from the last column.
611
612 Calls setCurrentIndex() internally.
613
614 \sa toFirst(), setCurrentIndex()
615 */
616void QDataWidgetMapper::toLast()
617{
618 Q_D(QDataWidgetMapper);
619 setCurrentIndex(d->itemCount() - 1);
620}
621
622
623/*!
624 Populates the widgets with data from the next row of the model
625 if the orientation is horizontal (the default), otherwise
626 with data from the next column.
627
628 Calls setCurrentIndex() internally. Does nothing if there is
629 no next row in the model.
630
631 \sa toPrevious(), setCurrentIndex()
632 */
633void QDataWidgetMapper::toNext()
634{
635 Q_D(QDataWidgetMapper);
636 setCurrentIndex(d->currentIdx() + 1);
637}
638
639/*!
640 Populates the widgets with data from the previous row of the model
641 if the orientation is horizontal (the default), otherwise
642 with data from the previous column.
643
644 Calls setCurrentIndex() internally. Does nothing if there is
645 no previous row in the model.
646
647 \sa toNext(), setCurrentIndex()
648 */
649void QDataWidgetMapper::toPrevious()
650{
651 Q_D(QDataWidgetMapper);
652 setCurrentIndex(d->currentIdx() - 1);
653}
654
655/*!
656 \property QDataWidgetMapper::currentIndex
657 \brief the current row or column
658
659 The widgets are populated with with data from the row at \a index
660 if the orientation is horizontal (the default), otherwise with
661 data from the column at \a index.
662
663 \sa setCurrentModelIndex(), toFirst(), toNext(), toPrevious(), toLast()
664*/
665void QDataWidgetMapper::setCurrentIndex(int index)
666{
667 Q_D(QDataWidgetMapper);
668
669 if (index < 0 || index >= d->itemCount())
670 return;
671 d->currentTopLeft = d->orientation == Qt::Horizontal
672 ? d->model->index(index, 0, d->rootIndex)
673 : d->model->index(0, index, d->rootIndex);
674 d->populate();
675
676 emit currentIndexChanged(index);
677}
678
679int QDataWidgetMapper::currentIndex() const
680{
681 Q_D(const QDataWidgetMapper);
682 return d->currentIdx();
683}
684
685/*!
686 Sets the current index to the row of the \a index if the
687 orientation is horizontal (the default), otherwise to the
688 column of the \a index.
689
690 Calls setCurrentIndex() internally. This convenience slot can be
691 connected to the signal \l
692 {QItemSelectionModel::}{currentRowChanged()} or \l
693 {QItemSelectionModel::}{currentColumnChanged()} of another view's
694 \l {QItemSelectionModel}{selection model}.
695
696 The following example illustrates how to update all widgets
697 with new data whenever the selection of a QTableView named
698 \c myTableView changes:
699
700 \snippet code/src_gui_itemviews_qdatawidgetmapper.cpp 2
701
702 \sa currentIndex()
703*/
704void QDataWidgetMapper::setCurrentModelIndex(const QModelIndex &index)
705{
706 Q_D(QDataWidgetMapper);
707
708 if (!index.isValid()
709 || index.model() != d->model
710 || index.parent() != d->rootIndex)
711 return;
712
713 setCurrentIndex(d->orientation == Qt::Horizontal ? index.row() : index.column());
714}
715
716/*!
717 Clears all mappings.
718
719 \sa addMapping(), removeMapping()
720 */
721void QDataWidgetMapper::clearMapping()
722{
723 Q_D(QDataWidgetMapper);
724
725 decltype(d->widgetMap) copy;
726 d->widgetMap.swap(copy); // a C++98 move
727 for (auto it = copy.crbegin(), end = copy.crend(); it != end; ++it) {
728 if (it->widget)
729 it->widget->removeEventFilter(d->delegate);
730 }
731}
732
733/*!
734 \property QDataWidgetMapper::orientation
735 \brief the orientation of the model
736
737 If the orientation is Qt::Horizontal (the default), a widget is
738 mapped to a column of a data model. The widget will be populated
739 with the model's data from its mapped column and the row that
740 currentIndex() points at.
741
742 Use Qt::Horizontal for tabular data that looks like this:
743
744 \table
745 \row \li 1 \li Qt Norway \li Oslo
746 \row \li 2 \li Qt Australia \li Brisbane
747 \row \li 3 \li Qt USA \li Silicon Valley
748 \row \li 4 \li Qt China \li Beijing
749 \row \li 5 \li Qt Germany \li Berlin
750 \endtable
751
752 If the orientation is set to Qt::Vertical, a widget is mapped to
753 a row. Calling setCurrentIndex() will change the current column.
754 The widget will be populates with the model's data from its
755 mapped row and the column that currentIndex() points at.
756
757 Use Qt::Vertical for tabular data that looks like this:
758
759 \table
760 \row \li 1 \li 2 \li 3 \li 4 \li 5
761 \row \li Qt Norway \li Qt Australia \li Qt USA \li Qt China \li Qt Germany
762 \row \li Oslo \li Brisbane \li Silicon Valley \li Beijing \li Berlin
763 \endtable
764
765 Changing the orientation clears all existing mappings.
766*/
767void QDataWidgetMapper::setOrientation(Qt::Orientation orientation)
768{
769 Q_D(QDataWidgetMapper);
770
771 if (d->orientation == orientation)
772 return;
773
774 clearMapping();
775 d->orientation = orientation;
776}
777
778Qt::Orientation QDataWidgetMapper::orientation() const
779{
780 Q_D(const QDataWidgetMapper);
781 return d->orientation;
782}
783
784/*!
785 \property QDataWidgetMapper::submitPolicy
786 \brief the current submit policy
787
788 Changing the current submit policy will revert all widgets
789 to the current data from the model.
790*/
791void QDataWidgetMapper::setSubmitPolicy(SubmitPolicy policy)
792{
793 Q_D(QDataWidgetMapper);
794 if (policy == d->submitPolicy)
795 return;
796
797 revert();
798 d->submitPolicy = policy;
799}
800
801QDataWidgetMapper::SubmitPolicy QDataWidgetMapper::submitPolicy() const
802{
803 Q_D(const QDataWidgetMapper);
804 return d->submitPolicy;
805}
806
807QT_END_NAMESPACE
808
809#include "moc_qdatawidgetmapper.cpp"
\inmodule QtCore
static bool qContainsIndex(const QModelIndex &idx, const QModelIndex &topLeft, const QModelIndex &bottomRight)
Q_DECLARE_TYPEINFO(QDataWidgetMapperPrivate::WidgetMapper, Q_RELOCATABLE_TYPE)