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