source: trunk/src/gui/itemviews/qdatawidgetmapper.cpp@ 371

Last change on this file since 371 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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