source: trunk/src/gui/itemviews/qitemeditorfactory.cpp@ 112

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

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

File size: 17.3 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 <qplatformdefs.h>
43#include "qitemeditorfactory.h"
44#include "qitemeditorfactory_p.h"
45
46#ifndef QT_NO_ITEMVIEWS
47
48#include <qcombobox.h>
49#include <qdatetimeedit.h>
50#include <qlabel.h>
51#include <qlineedit.h>
52#include <qspinbox.h>
53#include <limits.h>
54#include <float.h>
55#include <qapplication.h>
56#include <qdebug.h>
57
58QT_BEGIN_NAMESPACE
59
60
61#ifndef QT_NO_COMBOBOX
62
63class QBooleanComboBox : public QComboBox
64{
65 Q_OBJECT
66 Q_PROPERTY(bool value READ value WRITE setValue USER true)
67
68public:
69 QBooleanComboBox(QWidget *parent);
70 void setValue(bool);
71 bool value() const;
72};
73
74#endif // QT_NO_COMBOBOX
75
76/*!
77 \class QItemEditorFactory
78 \brief The QItemEditorFactory class provides widgets for editing item data
79 in views and delegates.
80 \since 4.2
81 \ingroup model-view
82
83 When editing data in an item view, editors are created and
84 displayed by a delegate. QItemDelegate, which is the delegate by
85 default installed on Qt's item views, uses a QItemEditorFactory to
86 create editors for it. A default unique instance provided by
87 QItemEditorFactory is used by all item delegates. If you set a
88 new default factory with setDefaultFactory(), the new factory will
89 be used by existing and new delegates.
90
91 A factory keeps a collection of QItemEditorCreatorBase
92 instances, which are specialized editors that produce editors
93 for one particular QVariant data type (All Qt models store
94 their data in \l{QVariant}s).
95
96 \section1 Standard Editing Widgets
97
98 The standard factory implementation provides editors for a variety of data
99 types. These are created whenever a delegate needs to provide an editor for
100 data supplied by a model. The following table shows the relationship between
101 types and the standard editors provided.
102
103 \table
104 \header \o Type \o Editor Widget
105 \row \o bool \o QComboBox
106 \row \o double \o QDoubleSpinBox
107 \row \o int \o{1,2} QSpinBox
108 \row \o unsigned int
109 \row \o QDate \o QDateEdit
110 \row \o QDateTime \o QDateTimeEdit
111 \row \o QPixmap \o QLabel
112 \row \o QString \o QLineEdit
113 \row \o QTime \o QTimeEdit
114 \endtable
115
116 Additional editors can be registered with the registerEditor() function.
117
118 \sa QItemDelegate, {Model/View Programming}, {Color Editor Factory Example}
119*/
120
121/*!
122 \fn QItemEditorFactory::QItemEditorFactory()
123
124 Constructs a new item editor factory.
125*/
126
127/*!
128 Creates an editor widget with the given \a parent for the specified \a type of data,
129 and returns it as a QWidget.
130
131 \sa registerEditor()
132*/
133QWidget *QItemEditorFactory::createEditor(QVariant::Type type, QWidget *parent) const
134{
135 QItemEditorCreatorBase *creator = creatorMap.value(type, 0);
136 if (!creator) {
137 const QItemEditorFactory *dfactory = defaultFactory();
138 return dfactory == this ? 0 : dfactory->createEditor(type, parent);
139 }
140 return creator->createWidget(parent);
141}
142
143/*!
144 Returns the property name used to access data for the given \a type of data.
145*/
146QByteArray QItemEditorFactory::valuePropertyName(QVariant::Type type) const
147{
148 QItemEditorCreatorBase *creator = creatorMap.value(type, 0);
149 if (!creator) {
150 const QItemEditorFactory *dfactory = defaultFactory();
151 return dfactory == this ? QByteArray() : dfactory->valuePropertyName(type);
152 }
153 return creator->valuePropertyName();
154}
155
156/*!
157 Destroys the item editor factory.
158*/
159QItemEditorFactory::~QItemEditorFactory()
160{
161}
162
163/*!
164 Registers an item editor creator specified by \a creator for the given \a type of data.
165
166 \bold{Note:} The factory takes ownership of the item editor creator and will destroy
167 it if a new creator for the same type is registered later.
168
169 \sa createEditor()
170*/
171void QItemEditorFactory::registerEditor(QVariant::Type type, QItemEditorCreatorBase *creator)
172{
173 delete creatorMap.value(type, 0);
174 creatorMap[type] = creator;
175}
176
177class QDefaultItemEditorFactory : public QItemEditorFactory
178{
179public:
180 inline QDefaultItemEditorFactory() {}
181 QWidget *createEditor(QVariant::Type type, QWidget *parent) const;
182 QByteArray valuePropertyName(QVariant::Type) const;
183};
184
185QWidget *QDefaultItemEditorFactory::createEditor(QVariant::Type type, QWidget *parent) const
186{
187 switch (type) {
188#ifndef QT_NO_COMBOBOX
189 case QVariant::Bool: {
190 QBooleanComboBox *cb = new QBooleanComboBox(parent);
191 cb->setFrame(false);
192 return cb; }
193#endif
194#ifndef QT_NO_SPINBOX
195 case QVariant::UInt: {
196 QSpinBox *sb = new QSpinBox(parent);
197 sb->setFrame(false);
198 sb->setMaximum(INT_MAX);
199 return sb; }
200 case QVariant::Int: {
201 QSpinBox *sb = new QSpinBox(parent);
202 sb->setFrame(false);
203 sb->setMinimum(INT_MIN);
204 sb->setMaximum(INT_MAX);
205 return sb; }
206#endif
207#ifndef QT_NO_DATETIMEEDIT
208 case QVariant::Date: {
209 QDateTimeEdit *ed = new QDateEdit(parent);
210 ed->setFrame(false);
211 return ed; }
212 case QVariant::Time: {
213 QDateTimeEdit *ed = new QTimeEdit(parent);
214 ed->setFrame(false);
215 return ed; }
216 case QVariant::DateTime: {
217 QDateTimeEdit *ed = new QDateTimeEdit(parent);
218 ed->setFrame(false);
219 return ed; }
220#endif
221 case QVariant::Pixmap:
222 return new QLabel(parent);
223#ifndef QT_NO_SPINBOX
224 case QVariant::Double: {
225 QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
226 sb->setFrame(false);
227 sb->setMinimum(-DBL_MAX);
228 sb->setMaximum(DBL_MAX);
229 return sb; }
230#endif
231#ifndef QT_NO_LINEEDIT
232 case QVariant::String:
233 default: {
234 // the default editor is a lineedit
235 QExpandingLineEdit *le = new QExpandingLineEdit(parent);
236 le->setFrame(le->style()->styleHint(QStyle::SH_ItemView_DrawDelegateFrame, 0, le));
237 if (!le->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, 0, le))
238 le->setWidgetOwnsGeometry(true);
239 return le; }
240#else
241 default:
242 break;
243#endif
244 }
245 return 0;
246}
247
248QByteArray QDefaultItemEditorFactory::valuePropertyName(QVariant::Type type) const
249{
250 switch (type) {
251#ifndef QT_NO_COMBOBOX
252 case QVariant::Bool:
253 return "currentIndex";
254#endif
255#ifndef QT_NO_SPINBOX
256 case QVariant::UInt:
257 case QVariant::Int:
258 case QVariant::Double:
259 return "value";
260#endif
261#ifndef QT_NO_DATETIMEEDIT
262 case QVariant::Date:
263 return "date";
264 case QVariant::Time:
265 return "time";
266 case QVariant::DateTime:
267 return "dateTime";
268#endif
269 case QVariant::String:
270 default:
271 // the default editor is a lineedit
272 return "text";
273 }
274}
275
276static QItemEditorFactory *q_default_factory = 0;
277struct QDefaultFactoryCleaner
278{
279 inline QDefaultFactoryCleaner() {}
280 ~QDefaultFactoryCleaner() { delete q_default_factory; q_default_factory = 0; }
281};
282
283/*!
284 Returns the default item editor factory.
285
286 \sa setDefaultFactory()
287*/
288const QItemEditorFactory *QItemEditorFactory::defaultFactory()
289{
290 static const QDefaultItemEditorFactory factory;
291 if (q_default_factory)
292 return q_default_factory;
293 return &factory;
294}
295
296/*!
297 Sets the default item editor factory to the given \a factory.
298 Both new and existing delegates will use the new factory.
299
300 \sa defaultFactory()
301*/
302void QItemEditorFactory::setDefaultFactory(QItemEditorFactory *factory)
303{
304 static const QDefaultFactoryCleaner cleaner;
305 delete q_default_factory;
306 q_default_factory = factory;
307}
308
309/*!
310 \class QItemEditorCreatorBase
311 \brief The QItemEditorCreatorBase class provides an abstract base class that
312 must be subclassed when implementing new item editor creators.
313 \since 4.2
314 \ingroup model-view
315
316 QItemEditorCreatorBase objects are specialized widget factories that
317 provide editor widgets for one particular QVariant data type. They
318 are used by QItemEditorFactory to create editors for
319 \l{QItemDelegate}s. Creator bases must be registered with
320 QItemEditorFactory::registerEditor().
321
322 An editor should provide a user property for the data it edits.
323 QItemDelagates can then access the property using Qt's
324 \l{Meta-Object System}{meta-object system} to set and retrieve the
325 editing data. A property is set as the user property with the USER
326 keyword:
327
328 \snippet doc/src/snippets/code/src_gui_itemviews_qitemeditorfactory.cpp 0
329
330 If the editor does not provide a user property, it must return the
331 name of the property from valuePropertyName(); delegates will then
332 use the name to access the property. If a user property exists,
333 item delegates will not call valuePropertyName().
334
335 QStandardItemEditorCreator is a convenience template class that can be used
336 to register widgets without the need to subclass QItemEditorCreatorBase.
337
338 \sa QStandardItemEditorCreator, QItemEditorFactory,
339 {Model/View Programming}, {Color Editor Factory Example}
340*/
341
342/*!
343 \fn QItemEditorCreatorBase::~QItemEditorCreatorBase()
344
345 Destroys the editor creator object.
346*/
347
348/*!
349 \fn QWidget *QItemEditorCreatorBase::createWidget(QWidget *parent) const
350
351 Returns an editor widget with the given \a parent.
352
353 When implementing this function in subclasses of this class, you must
354 construct and return new editor widgets with the parent widget specified.
355*/
356
357/*!
358 \fn QByteArray QItemEditorCreatorBase::valuePropertyName() const
359
360 Returns the name of the property used to get and set values in the creator's
361 editor widgets.
362
363 When implementing this function in subclasses, you must ensure that the
364 editor widget's property specified by this function can accept the type
365 the creator is registered for. For example, a creator which constructs
366 QCheckBox widgets to edit boolean values would return the
367 \l{QCheckBox::checkable}{checkable} property name from this function,
368 and must be registered in the item editor factory for the QVariant::Bool
369 type.
370
371 Note: Since Qt 4.2 the item delegates query the user property of widgets,
372 and only call this function if the widget has no user property. You can
373 override this behavior by reimplementing QAbstractItemDelegate::setModelData()
374 and QAbstractItemDelegate::setEditorData().
375
376 \sa QMetaObject::userProperty(), QItemEditorFactory::registerEditor()
377*/
378
379/*!
380 \class QItemEditorCreator
381 \brief The QItemEditorCreator class makes it possible to create
382 item editor creator bases without subclassing
383 QItemEditorCreatorBase.
384
385 \since 4.2
386 \ingroup model-view
387
388 QItemEditorCreator is a convenience template class. It uses
389 the template class to create editors for QItemEditorFactory.
390 This way, it is not necessary to subclass
391 QItemEditorCreatorBase.
392
393 \snippet doc/src/snippets/code/src_gui_itemviews_qitemeditorfactory.cpp 1
394
395 The constructor takes the name of the property that contains the
396 editing data. QItemDelegate can then access the property by name
397 when it sets and retrieves editing data. Only use this class if
398 your editor does not define a user property (using the USER
399 keyword in the Q_PROPERTY macro). If the widget has a user
400 property, you should use QStandardItemEditorCreator instead.
401
402 \sa QItemEditorCreatorBase, QStandardItemEditorCreator,
403 QItemEditorFactory, {Color Editor Factory Example}
404*/
405
406/*!
407 \fn QItemEditorCreator::QItemEditorCreator(const QByteArray &valuePropertyName)
408
409 Constructs an editor creator object using \a valuePropertyName
410 as the name of the property to be used for editing. The
411 property name is used by QItemDelegate when setting and
412 getting editor data.
413
414 Note that the \a valuePropertyName is only used if the editor
415 widget does not have a user property defined.
416*/
417
418/*!
419 \fn QWidget *QItemEditorCreator::createWidget(QWidget *parent) const
420 \reimp
421*/
422
423/*!
424 \fn QByteArray QItemEditorCreator::valuePropertyName() const
425 \reimp
426*/
427
428/*!
429 \class QStandardItemEditorCreator
430
431 \brief The QStandardItemEditorCreator class provides the
432 possibility to register widgets without having to subclass
433 QItemEditorCreatorBase.
434
435 \since 4.2
436 \ingroup model-view
437
438 This convenience template class makes it possible to register widgets without
439 having to subclass QItemEditorCreatorBase.
440
441 Example:
442
443 \snippet doc/src/snippets/code/src_gui_itemviews_qitemeditorfactory.cpp 2
444
445 Setting the \c editorFactory created above in an item delegate via
446 QItemDelegate::setItemEditorFactory() makes sure that all values of type
447 QVariant::DateTime will be edited in \c{MyFancyDateTimeEdit}.
448
449 The editor must provide a user property that will contain the
450 editing data. The property is used by \l{QItemDelegate}s to set
451 and retrieve the data (using Qt's \l{Meta-Object
452 System}{meta-object system}). You set the user property with
453 the USER keyword:
454
455 \snippet doc/src/snippets/code/src_gui_itemviews_qitemeditorfactory.cpp 3
456
457 \sa QItemEditorCreatorBase, QItemEditorCreator,
458 QItemEditorFactory, QItemDelegate, {Color Editor Factory Example}
459*/
460
461/*!
462 \fn QStandardItemEditorCreator::QStandardItemEditorCreator()
463
464 Constructs an editor creator object.
465*/
466
467/*!
468 \fn QWidget *QStandardItemEditorCreator::createWidget(QWidget *parent) const
469 \reimp
470*/
471
472/*!
473 \fn QByteArray QStandardItemEditorCreator::valuePropertyName() const
474 \reimp
475*/
476
477#ifndef QT_NO_LINEEDIT
478
479QExpandingLineEdit::QExpandingLineEdit(QWidget *parent)
480 : QLineEdit(parent), originalWidth(-1), widgetOwnsGeometry(false)
481{
482 connect(this, SIGNAL(textChanged(QString)), this, SLOT(resizeToContents()));
483 updateMinimumWidth();
484}
485
486void QExpandingLineEdit::changeEvent(QEvent *e)
487{
488 switch (e->type())
489 {
490 case QEvent::FontChange:
491 case QEvent::StyleChange:
492 case QEvent::ContentsRectChange:
493 updateMinimumWidth();
494 break;
495 default:
496 break;
497 }
498
499 QLineEdit::changeEvent(e);
500}
501
502void QExpandingLineEdit::updateMinimumWidth()
503{
504 int left, right;
505 getTextMargins(&left, 0, &right, 0);
506 int width = left + right + 4 /*horizontalMargin in qlineedit.cpp*/;
507 getContentsMargins(&left, 0, &right, 0);
508 width += left + right;
509
510 QStyleOptionFrameV2 opt;
511 initStyleOption(&opt);
512
513 int minWidth = style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(width, 0).
514 expandedTo(QApplication::globalStrut()), this).width();
515 setMinimumWidth(minWidth);
516}
517
518void QExpandingLineEdit::resizeToContents()
519{
520 int oldWidth = width();
521 if (originalWidth == -1)
522 originalWidth = oldWidth;
523 if (QWidget *parent = parentWidget()) {
524 QPoint position = pos();
525 int hintWidth = minimumWidth() + fontMetrics().width(displayText());
526 int parentWidth = parent->width();
527 int maxWidth = isRightToLeft() ? position.x() + oldWidth : parentWidth - position.x();
528 int newWidth = qBound(originalWidth, hintWidth, maxWidth);
529 if (widgetOwnsGeometry)
530 setMaximumWidth(newWidth);
531 if (isRightToLeft())
532 move(position.x() - newWidth + oldWidth, position.y());
533 resize(newWidth, height());
534 }
535}
536
537#endif // QT_NO_LINEEDIT
538
539#ifndef QT_NO_COMBOBOX
540
541QBooleanComboBox::QBooleanComboBox(QWidget *parent)
542 : QComboBox(parent)
543{
544 addItem(QComboBox::tr("False"));
545 addItem(QComboBox::tr("True"));
546}
547
548void QBooleanComboBox::setValue(bool value)
549{
550 setCurrentIndex(value ? 1 : 0);
551}
552
553bool QBooleanComboBox::value() const
554{
555 return (currentIndex() == 1);
556}
557
558#endif // QT_NO_COMBOBOX
559
560QT_END_NAMESPACE
561
562#if !defined(QT_NO_LINEEDIT) || !defined(QT_NO_COMBOBOX)
563#include "qitemeditorfactory.moc"
564#endif
565
566#endif // QT_NO_ITEMVIEWS
Note: See TracBrowser for help on using the repository browser.