src/gui/itemviews/qitemeditorfactory.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    58 QT_BEGIN_NAMESPACE
       
    59 
       
    60 
       
    61 #ifndef QT_NO_COMBOBOX
       
    62 
       
    63 class QBooleanComboBox : public QComboBox
       
    64 {
       
    65     Q_OBJECT
       
    66     Q_PROPERTY(bool value READ value WRITE setValue USER true)
       
    67 
       
    68 public:
       
    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 */
       
   133 QWidget *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 */
       
   146 QByteArray 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 */
       
   159 QItemEditorFactory::~QItemEditorFactory()
       
   160 {
       
   161     //we make sure we delete all the QItemEditorCreatorBase
       
   162     //this has to be done only once, hence the QSet
       
   163     QSet<QItemEditorCreatorBase*> set = creatorMap.values().toSet();
       
   164     qDeleteAll(set);
       
   165 }
       
   166 
       
   167 /*!
       
   168     Registers an item editor creator specified by \a creator for the given \a type of data.
       
   169 
       
   170     \bold{Note:} The factory takes ownership of the item editor creator and will destroy
       
   171     it if a new creator for the same type is registered later.
       
   172 
       
   173     \sa createEditor()
       
   174 */
       
   175 void QItemEditorFactory::registerEditor(QVariant::Type type, QItemEditorCreatorBase *creator)
       
   176 {
       
   177     QHash<QVariant::Type, QItemEditorCreatorBase *>::iterator it = creatorMap.find(type);
       
   178     if (it != creatorMap.end()) {
       
   179         QItemEditorCreatorBase *oldCreator = it.value();
       
   180         Q_ASSERT(oldCreator);
       
   181         creatorMap.erase(it);
       
   182         if (!creatorMap.values().contains(oldCreator))
       
   183             delete oldCreator; // if it is no more in use we can delete it
       
   184     }
       
   185 
       
   186     creatorMap[type] = creator;
       
   187 }
       
   188 
       
   189 class QDefaultItemEditorFactory : public QItemEditorFactory
       
   190 {
       
   191 public:
       
   192     inline QDefaultItemEditorFactory() {}
       
   193     QWidget *createEditor(QVariant::Type type, QWidget *parent) const;
       
   194     QByteArray valuePropertyName(QVariant::Type) const;
       
   195 };
       
   196 
       
   197 QWidget *QDefaultItemEditorFactory::createEditor(QVariant::Type type, QWidget *parent) const
       
   198 {
       
   199     switch (type) {
       
   200 #ifndef QT_NO_COMBOBOX
       
   201     case QVariant::Bool: {
       
   202         QBooleanComboBox *cb = new QBooleanComboBox(parent);
       
   203         cb->setFrame(false);
       
   204         return cb; }
       
   205 #endif
       
   206 #ifndef QT_NO_SPINBOX
       
   207     case QVariant::UInt: {
       
   208         QSpinBox *sb = new QSpinBox(parent);
       
   209         sb->setFrame(false);
       
   210         sb->setMaximum(INT_MAX);
       
   211         return sb; }
       
   212     case QVariant::Int: {
       
   213         QSpinBox *sb = new QSpinBox(parent);
       
   214         sb->setFrame(false);
       
   215         sb->setMinimum(INT_MIN);
       
   216         sb->setMaximum(INT_MAX);
       
   217         return sb; }
       
   218 #endif
       
   219 #ifndef QT_NO_DATETIMEEDIT
       
   220     case QVariant::Date: {
       
   221         QDateTimeEdit *ed = new QDateEdit(parent);
       
   222         ed->setFrame(false);
       
   223         return ed; }
       
   224     case QVariant::Time: {
       
   225         QDateTimeEdit *ed = new QTimeEdit(parent);
       
   226         ed->setFrame(false);
       
   227         return ed; }
       
   228     case QVariant::DateTime: {
       
   229         QDateTimeEdit *ed = new QDateTimeEdit(parent);
       
   230         ed->setFrame(false);
       
   231         return ed; }
       
   232 #endif
       
   233     case QVariant::Pixmap:
       
   234         return new QLabel(parent);
       
   235 #ifndef QT_NO_SPINBOX
       
   236     case QVariant::Double: {
       
   237         QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
       
   238         sb->setFrame(false);
       
   239         sb->setMinimum(-DBL_MAX);
       
   240         sb->setMaximum(DBL_MAX);
       
   241         return sb; }
       
   242 #endif
       
   243 #ifndef QT_NO_LINEEDIT
       
   244     case QVariant::String:
       
   245     default: {
       
   246         // the default editor is a lineedit
       
   247         QExpandingLineEdit *le = new QExpandingLineEdit(parent);
       
   248         le->setFrame(le->style()->styleHint(QStyle::SH_ItemView_DrawDelegateFrame, 0, le));
       
   249         if (!le->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, 0, le))
       
   250             le->setWidgetOwnsGeometry(true);
       
   251         return le; }
       
   252 #else
       
   253     default:
       
   254         break;
       
   255 #endif
       
   256     }
       
   257     return 0;
       
   258 }
       
   259 
       
   260 QByteArray QDefaultItemEditorFactory::valuePropertyName(QVariant::Type type) const
       
   261 {
       
   262     switch (type) {
       
   263 #ifndef QT_NO_COMBOBOX
       
   264     case QVariant::Bool:
       
   265         return "currentIndex";
       
   266 #endif
       
   267 #ifndef QT_NO_SPINBOX
       
   268     case QVariant::UInt:
       
   269     case QVariant::Int:
       
   270     case QVariant::Double:
       
   271         return "value";
       
   272 #endif
       
   273 #ifndef QT_NO_DATETIMEEDIT
       
   274     case QVariant::Date:
       
   275         return "date";
       
   276     case QVariant::Time:
       
   277         return "time";
       
   278     case QVariant::DateTime:
       
   279         return "dateTime";
       
   280 #endif
       
   281     case QVariant::String:
       
   282     default:
       
   283         // the default editor is a lineedit
       
   284         return "text";
       
   285     }
       
   286 }
       
   287 
       
   288 static QItemEditorFactory *q_default_factory = 0;
       
   289 struct QDefaultFactoryCleaner
       
   290 {
       
   291     inline QDefaultFactoryCleaner() {}
       
   292     ~QDefaultFactoryCleaner() { delete q_default_factory; q_default_factory = 0; }
       
   293 };
       
   294 
       
   295 /*!
       
   296     Returns the default item editor factory.
       
   297 
       
   298     \sa setDefaultFactory()
       
   299 */
       
   300 const QItemEditorFactory *QItemEditorFactory::defaultFactory()
       
   301 {
       
   302     static const QDefaultItemEditorFactory factory;
       
   303     if (q_default_factory)
       
   304         return q_default_factory;
       
   305     return &factory;
       
   306 }
       
   307 
       
   308 /*!
       
   309     Sets the default item editor factory to the given \a factory.
       
   310     Both new and existing delegates will use the new factory.
       
   311 
       
   312     \sa defaultFactory()
       
   313 */
       
   314 void QItemEditorFactory::setDefaultFactory(QItemEditorFactory *factory)
       
   315 {
       
   316     static const QDefaultFactoryCleaner cleaner;
       
   317     delete q_default_factory;
       
   318     q_default_factory = factory;
       
   319 }
       
   320 
       
   321 /*!
       
   322     \class QItemEditorCreatorBase
       
   323     \brief The QItemEditorCreatorBase class provides an abstract base class that
       
   324     must be subclassed when implementing new item editor creators.
       
   325     \since 4.2
       
   326     \ingroup model-view
       
   327 
       
   328     QItemEditorCreatorBase objects are specialized widget factories that
       
   329     provide editor widgets for one particular QVariant data type. They
       
   330     are used by QItemEditorFactory to create editors for
       
   331     \l{QItemDelegate}s. Creator bases must be registered with
       
   332     QItemEditorFactory::registerEditor().
       
   333 
       
   334     An editor should provide a user property for the data it edits.
       
   335     QItemDelagates can then access the property using Qt's
       
   336     \l{Meta-Object System}{meta-object system} to set and retrieve the
       
   337     editing data. A property is set as the user property with the USER
       
   338     keyword:
       
   339 
       
   340     \snippet doc/src/snippets/code/src_gui_itemviews_qitemeditorfactory.cpp 0
       
   341 
       
   342     If the editor does not provide a user property, it must return the
       
   343     name of the property from valuePropertyName(); delegates will then
       
   344     use the name to access the property. If a user property exists,
       
   345     item delegates will not call valuePropertyName().
       
   346 
       
   347     QStandardItemEditorCreator is a convenience template class that can be used
       
   348     to register widgets without the need to subclass QItemEditorCreatorBase.
       
   349 
       
   350     \sa QStandardItemEditorCreator, QItemEditorFactory,
       
   351     {Model/View Programming}, {Color Editor Factory Example}
       
   352 */
       
   353 
       
   354 /*!
       
   355     \fn QItemEditorCreatorBase::~QItemEditorCreatorBase()
       
   356 
       
   357     Destroys the editor creator object.
       
   358 */
       
   359 
       
   360 /*!
       
   361     \fn QWidget *QItemEditorCreatorBase::createWidget(QWidget *parent) const
       
   362 
       
   363     Returns an editor widget with the given \a parent.
       
   364 
       
   365     When implementing this function in subclasses of this class, you must
       
   366     construct and return new editor widgets with the parent widget specified.
       
   367 */
       
   368 
       
   369 /*!
       
   370     \fn QByteArray QItemEditorCreatorBase::valuePropertyName() const
       
   371 
       
   372     Returns the name of the property used to get and set values in the creator's
       
   373     editor widgets.
       
   374 
       
   375     When implementing this function in subclasses, you must ensure that the
       
   376     editor widget's property specified by this function can accept the type
       
   377     the creator is registered for. For example, a creator which constructs
       
   378     QCheckBox widgets to edit boolean values would return the
       
   379     \l{QCheckBox::checkable}{checkable} property name from this function,
       
   380     and must be registered in the item editor factory for the QVariant::Bool
       
   381     type.
       
   382 
       
   383     Note: Since Qt 4.2 the item delegates query the user property of widgets,
       
   384     and only call this function if the widget has no user property. You can
       
   385     override this behavior by reimplementing QAbstractItemDelegate::setModelData()
       
   386     and QAbstractItemDelegate::setEditorData().
       
   387 
       
   388     \sa QMetaObject::userProperty(), QItemEditorFactory::registerEditor()
       
   389 */
       
   390 
       
   391 /*!
       
   392     \class QItemEditorCreator
       
   393     \brief The QItemEditorCreator class makes it possible to create
       
   394 	   item editor creator bases without subclassing
       
   395 	   QItemEditorCreatorBase.
       
   396 
       
   397     \since 4.2
       
   398     \ingroup model-view
       
   399 
       
   400     QItemEditorCreator is a convenience template class. It uses
       
   401     the template class to create editors for QItemEditorFactory.
       
   402     This way, it is not necessary to subclass
       
   403     QItemEditorCreatorBase.
       
   404 
       
   405     \snippet doc/src/snippets/code/src_gui_itemviews_qitemeditorfactory.cpp 1
       
   406 
       
   407     The constructor takes the name of the property that contains the
       
   408     editing data. QItemDelegate can then access the property by name
       
   409     when it sets and retrieves editing data. Only use this class if
       
   410     your editor does not define a user property (using the USER
       
   411     keyword in the Q_PROPERTY macro).  If the widget has a user
       
   412     property, you should use QStandardItemEditorCreator instead.
       
   413 
       
   414     \sa QItemEditorCreatorBase, QStandardItemEditorCreator,
       
   415 	QItemEditorFactory, {Color Editor Factory Example}
       
   416 */
       
   417 
       
   418 /*!
       
   419     \fn QItemEditorCreator::QItemEditorCreator(const QByteArray &valuePropertyName)
       
   420 
       
   421     Constructs an editor creator object using \a valuePropertyName
       
   422     as the name of the property to be used for editing. The
       
   423     property name is used by QItemDelegate when setting and
       
   424     getting editor data.
       
   425 
       
   426     Note that the \a valuePropertyName is only used if the editor
       
   427     widget does not have a user property defined.
       
   428 */
       
   429 
       
   430 /*!
       
   431     \fn QWidget *QItemEditorCreator::createWidget(QWidget *parent) const
       
   432     \reimp
       
   433 */
       
   434 
       
   435 /*!
       
   436     \fn QByteArray QItemEditorCreator::valuePropertyName() const
       
   437     \reimp
       
   438 */
       
   439 
       
   440 /*!
       
   441     \class QStandardItemEditorCreator
       
   442 
       
   443     \brief The QStandardItemEditorCreator class provides the
       
   444     possibility to register widgets without having to subclass
       
   445     QItemEditorCreatorBase.
       
   446 
       
   447     \since 4.2
       
   448     \ingroup model-view
       
   449 
       
   450     This convenience template class makes it possible to register widgets without
       
   451     having to subclass QItemEditorCreatorBase.
       
   452 
       
   453     Example:
       
   454 
       
   455     \snippet doc/src/snippets/code/src_gui_itemviews_qitemeditorfactory.cpp 2
       
   456 
       
   457     Setting the \c editorFactory created above in an item delegate via
       
   458     QItemDelegate::setItemEditorFactory() makes sure that all values of type
       
   459     QVariant::DateTime will be edited in \c{MyFancyDateTimeEdit}.
       
   460 
       
   461     The editor must provide a user property that will contain the
       
   462     editing data. The property is used by \l{QItemDelegate}s to set
       
   463     and retrieve the data (using Qt's \l{Meta-Object
       
   464     System}{meta-object system}). You set the user property with
       
   465     the USER keyword:
       
   466 
       
   467     \snippet doc/src/snippets/code/src_gui_itemviews_qitemeditorfactory.cpp 3
       
   468 
       
   469     \sa QItemEditorCreatorBase, QItemEditorCreator,
       
   470 	QItemEditorFactory, QItemDelegate, {Color Editor Factory Example}
       
   471 */
       
   472 
       
   473 /*!
       
   474     \fn QStandardItemEditorCreator::QStandardItemEditorCreator()
       
   475 
       
   476     Constructs an editor creator object.
       
   477 */
       
   478 
       
   479 /*!
       
   480     \fn QWidget *QStandardItemEditorCreator::createWidget(QWidget *parent) const
       
   481     \reimp
       
   482 */
       
   483 
       
   484 /*!
       
   485     \fn QByteArray QStandardItemEditorCreator::valuePropertyName() const
       
   486     \reimp
       
   487 */
       
   488 
       
   489 #ifndef QT_NO_LINEEDIT
       
   490 
       
   491 QExpandingLineEdit::QExpandingLineEdit(QWidget *parent)
       
   492     : QLineEdit(parent), originalWidth(-1), widgetOwnsGeometry(false)
       
   493 {
       
   494     connect(this, SIGNAL(textChanged(QString)), this, SLOT(resizeToContents()));
       
   495     updateMinimumWidth();
       
   496 }
       
   497 
       
   498 void QExpandingLineEdit::changeEvent(QEvent *e)
       
   499 {
       
   500     switch (e->type())
       
   501     {
       
   502     case QEvent::FontChange:
       
   503     case QEvent::StyleChange:
       
   504     case QEvent::ContentsRectChange:
       
   505         updateMinimumWidth();
       
   506         break;
       
   507     default:
       
   508         break;
       
   509     }
       
   510 
       
   511     QLineEdit::changeEvent(e);
       
   512 }
       
   513 
       
   514 void QExpandingLineEdit::updateMinimumWidth()
       
   515 {
       
   516     int left, right;
       
   517     getTextMargins(&left, 0, &right, 0);
       
   518     int width = left + right + 4 /*horizontalMargin in qlineedit.cpp*/;
       
   519     getContentsMargins(&left, 0, &right, 0);
       
   520     width += left + right;
       
   521 
       
   522     QStyleOptionFrameV2 opt;
       
   523     initStyleOption(&opt);
       
   524     
       
   525     int minWidth = style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(width, 0).
       
   526                                       expandedTo(QApplication::globalStrut()), this).width();
       
   527     setMinimumWidth(minWidth);
       
   528 }
       
   529 
       
   530 void QExpandingLineEdit::resizeToContents()
       
   531 {
       
   532     int oldWidth = width();
       
   533     if (originalWidth == -1)
       
   534         originalWidth = oldWidth;
       
   535     if (QWidget *parent = parentWidget()) {
       
   536         QPoint position = pos();
       
   537         int hintWidth = minimumWidth() + fontMetrics().width(displayText());
       
   538         int parentWidth = parent->width();
       
   539         int maxWidth = isRightToLeft() ? position.x() + oldWidth : parentWidth - position.x();
       
   540         int newWidth = qBound(originalWidth, hintWidth, maxWidth);
       
   541         if (widgetOwnsGeometry)
       
   542             setMaximumWidth(newWidth);
       
   543         if (isRightToLeft())
       
   544             move(position.x() - newWidth + oldWidth, position.y());
       
   545         resize(newWidth, height());
       
   546     }
       
   547 }
       
   548 
       
   549 #endif // QT_NO_LINEEDIT
       
   550 
       
   551 #ifndef QT_NO_COMBOBOX
       
   552 
       
   553 QBooleanComboBox::QBooleanComboBox(QWidget *parent)
       
   554     : QComboBox(parent)
       
   555 {
       
   556     addItem(QComboBox::tr("False"));
       
   557     addItem(QComboBox::tr("True"));
       
   558 }
       
   559 
       
   560 void QBooleanComboBox::setValue(bool value)
       
   561 {
       
   562     setCurrentIndex(value ? 1 : 0);
       
   563 }
       
   564 
       
   565 bool QBooleanComboBox::value() const
       
   566 {
       
   567     return (currentIndex() == 1);
       
   568 }
       
   569 
       
   570 #endif // QT_NO_COMBOBOX
       
   571 
       
   572 QT_END_NAMESPACE
       
   573 
       
   574 #if !defined(QT_NO_LINEEDIT) || !defined(QT_NO_COMBOBOX)
       
   575 #include "qitemeditorfactory.moc"
       
   576 #endif
       
   577 
       
   578 #endif // QT_NO_ITEMVIEWS