tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.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 tools applications 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 "qtgroupboxpropertybrowser.h"
       
    43 #include <QtCore/QSet>
       
    44 #include <QtGui/QGridLayout>
       
    45 #include <QtGui/QLabel>
       
    46 #include <QtGui/QGroupBox>
       
    47 #include <QtCore/QTimer>
       
    48 #include <QtCore/QMap>
       
    49 
       
    50 QT_BEGIN_NAMESPACE
       
    51 
       
    52 class QtGroupBoxPropertyBrowserPrivate
       
    53 {
       
    54     QtGroupBoxPropertyBrowser *q_ptr;
       
    55     Q_DECLARE_PUBLIC(QtGroupBoxPropertyBrowser)
       
    56 public:
       
    57 
       
    58     void init(QWidget *parent);
       
    59 
       
    60     void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex);
       
    61     void propertyRemoved(QtBrowserItem *index);
       
    62     void propertyChanged(QtBrowserItem *index);
       
    63     QWidget *createEditor(QtProperty *property, QWidget *parent) const
       
    64         { return q_ptr->createEditor(property, parent); }
       
    65 
       
    66     void slotEditorDestroyed();
       
    67     void slotUpdate();
       
    68 
       
    69     struct WidgetItem
       
    70     {
       
    71         WidgetItem() : widget(0), label(0), widgetLabel(0),
       
    72                 groupBox(0), layout(0), line(0), parent(0) { }
       
    73         QWidget *widget; // can be null
       
    74         QLabel *label;
       
    75         QLabel *widgetLabel;
       
    76         QGroupBox *groupBox;
       
    77         QGridLayout *layout;
       
    78         QFrame *line;
       
    79         WidgetItem *parent;
       
    80         QList<WidgetItem *> children;
       
    81     };
       
    82 private:
       
    83     void updateLater();
       
    84     void updateItem(WidgetItem *item);
       
    85     void insertRow(QGridLayout *layout, int row) const;
       
    86     void removeRow(QGridLayout *layout, int row) const;
       
    87 
       
    88     bool hasHeader(WidgetItem *item) const;
       
    89 
       
    90     QMap<QtBrowserItem *, WidgetItem *> m_indexToItem;
       
    91     QMap<WidgetItem *, QtBrowserItem *> m_itemToIndex;
       
    92     QMap<QWidget *, WidgetItem *> m_widgetToItem;
       
    93     QGridLayout *m_mainLayout;
       
    94     QList<WidgetItem *> m_children;
       
    95     QList<WidgetItem *> m_recreateQueue;
       
    96 };
       
    97 
       
    98 void QtGroupBoxPropertyBrowserPrivate::init(QWidget *parent)
       
    99 {
       
   100     m_mainLayout = new QGridLayout();
       
   101     parent->setLayout(m_mainLayout);
       
   102     QLayoutItem *item = new QSpacerItem(0, 0,
       
   103                 QSizePolicy::Fixed, QSizePolicy::Expanding);
       
   104     m_mainLayout->addItem(item, 0, 0);
       
   105 }
       
   106 
       
   107 void QtGroupBoxPropertyBrowserPrivate::slotEditorDestroyed()
       
   108 {
       
   109     QWidget *editor = qobject_cast<QWidget *>(q_ptr->sender());
       
   110     if (!editor)
       
   111         return;
       
   112     if (!m_widgetToItem.contains(editor))
       
   113         return;
       
   114     m_widgetToItem[editor]->widget = 0;
       
   115     m_widgetToItem.remove(editor);
       
   116 }
       
   117 
       
   118 void QtGroupBoxPropertyBrowserPrivate::slotUpdate()
       
   119 {
       
   120     QListIterator<WidgetItem *> itItem(m_recreateQueue);
       
   121     while (itItem.hasNext()) {
       
   122         WidgetItem *item = itItem.next();
       
   123 
       
   124         WidgetItem *par = item->parent;
       
   125         QWidget *w = 0;
       
   126         QGridLayout *l = 0;
       
   127         int oldRow = -1;
       
   128         if (!par) {
       
   129             w = q_ptr;
       
   130             l = m_mainLayout;
       
   131             oldRow = m_children.indexOf(item);
       
   132         } else {
       
   133             w = par->groupBox;
       
   134             l = par->layout;
       
   135             oldRow = par->children.indexOf(item);
       
   136             if (hasHeader(par))
       
   137                 oldRow += 2;
       
   138         }
       
   139 
       
   140         if (item->widget) {
       
   141             item->widget->setParent(w);
       
   142         } else if (item->widgetLabel) {
       
   143             item->widgetLabel->setParent(w);
       
   144         } else {
       
   145             item->widgetLabel = new QLabel(w);
       
   146         }
       
   147         int span = 1;
       
   148         if (item->widget)
       
   149             l->addWidget(item->widget, oldRow, 1, 1, 1);
       
   150         else if (item->widgetLabel)
       
   151             l->addWidget(item->widgetLabel, oldRow, 1, 1, 1);
       
   152         else
       
   153             span = 2;
       
   154         item->label = new QLabel(w);
       
   155         item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
       
   156         l->addWidget(item->label, oldRow, 0, 1, span);
       
   157 
       
   158         updateItem(item);
       
   159     }
       
   160     m_recreateQueue.clear();
       
   161 }
       
   162 
       
   163 void QtGroupBoxPropertyBrowserPrivate::updateLater()
       
   164 {
       
   165     QTimer::singleShot(0, q_ptr, SLOT(slotUpdate()));
       
   166 }
       
   167 
       
   168 void QtGroupBoxPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex)
       
   169 {
       
   170     WidgetItem *afterItem = m_indexToItem.value(afterIndex);
       
   171     WidgetItem *parentItem = m_indexToItem.value(index->parent());
       
   172 
       
   173     WidgetItem *newItem = new WidgetItem();
       
   174     newItem->parent = parentItem;
       
   175 
       
   176     QGridLayout *layout = 0;
       
   177     QWidget *parentWidget = 0;
       
   178     int row = -1;
       
   179     if (!afterItem) {
       
   180         row = 0;
       
   181         if (parentItem)
       
   182             parentItem->children.insert(0, newItem);
       
   183         else
       
   184             m_children.insert(0, newItem);
       
   185     } else {
       
   186         if (parentItem) {
       
   187             row = parentItem->children.indexOf(afterItem) + 1;
       
   188             parentItem->children.insert(row, newItem);
       
   189         } else {
       
   190             row = m_children.indexOf(afterItem) + 1;
       
   191             m_children.insert(row, newItem);
       
   192         }
       
   193     }
       
   194     if (parentItem && hasHeader(parentItem))
       
   195         row += 2;
       
   196 
       
   197     if (!parentItem) {
       
   198         layout = m_mainLayout;
       
   199         parentWidget = q_ptr;;
       
   200     } else {
       
   201         if (!parentItem->groupBox) {
       
   202             m_recreateQueue.removeAll(parentItem);
       
   203             WidgetItem *par = parentItem->parent;
       
   204             QWidget *w = 0;
       
   205             QGridLayout *l = 0;
       
   206             int oldRow = -1;
       
   207             if (!par) {
       
   208                 w = q_ptr;
       
   209                 l = m_mainLayout;
       
   210                 oldRow = m_children.indexOf(parentItem);
       
   211             } else {
       
   212                 w = par->groupBox;
       
   213                 l = par->layout;
       
   214                 oldRow = par->children.indexOf(parentItem);
       
   215                 if (hasHeader(par))
       
   216                     oldRow += 2;
       
   217             }
       
   218             parentItem->groupBox = new QGroupBox(w);
       
   219             parentItem->layout = new QGridLayout();
       
   220             parentItem->groupBox->setLayout(parentItem->layout);
       
   221             if (parentItem->label) {
       
   222                 l->removeWidget(parentItem->label);
       
   223                 delete parentItem->label;
       
   224                 parentItem->label = 0;
       
   225             }
       
   226             if (parentItem->widget) {
       
   227                 l->removeWidget(parentItem->widget);
       
   228                 parentItem->widget->setParent(parentItem->groupBox);
       
   229                 parentItem->layout->addWidget(parentItem->widget, 0, 0, 1, 2);
       
   230                 parentItem->line = new QFrame(parentItem->groupBox);
       
   231             } else if (parentItem->widgetLabel) {
       
   232                 l->removeWidget(parentItem->widgetLabel);
       
   233                 delete parentItem->widgetLabel;
       
   234                 parentItem->widgetLabel = 0;
       
   235             }
       
   236             if (parentItem->line) {
       
   237                 parentItem->line->setFrameShape(QFrame::HLine);
       
   238                 parentItem->line->setFrameShadow(QFrame::Sunken);
       
   239                 parentItem->layout->addWidget(parentItem->line, 1, 0, 1, 2);
       
   240             }
       
   241             l->addWidget(parentItem->groupBox, oldRow, 0, 1, 2);
       
   242             updateItem(parentItem);
       
   243         }
       
   244         layout = parentItem->layout;
       
   245         parentWidget = parentItem->groupBox;
       
   246     }
       
   247 
       
   248     newItem->label = new QLabel(parentWidget);
       
   249     newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
       
   250     newItem->widget = createEditor(index->property(), parentWidget);
       
   251     if (!newItem->widget) {
       
   252         newItem->widgetLabel = new QLabel(parentWidget);
       
   253     } else {
       
   254         QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed()));
       
   255         m_widgetToItem[newItem->widget] = newItem;
       
   256     }
       
   257 
       
   258     insertRow(layout, row);
       
   259     int span = 1;
       
   260     if (newItem->widget)
       
   261         layout->addWidget(newItem->widget, row, 1);
       
   262     else if (newItem->widgetLabel)
       
   263         layout->addWidget(newItem->widgetLabel, row, 1);
       
   264     else
       
   265         span = 2;
       
   266     layout->addWidget(newItem->label, row, 0, 1, span);
       
   267 
       
   268     m_itemToIndex[newItem] = index;
       
   269     m_indexToItem[index] = newItem;
       
   270 
       
   271     updateItem(newItem);
       
   272 }
       
   273 
       
   274 void QtGroupBoxPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index)
       
   275 {
       
   276     WidgetItem *item = m_indexToItem.value(index);
       
   277 
       
   278     m_indexToItem.remove(index);
       
   279     m_itemToIndex.remove(item);
       
   280 
       
   281     WidgetItem *parentItem = item->parent;
       
   282 
       
   283     int row = -1;
       
   284 
       
   285     if (parentItem) {
       
   286         row = parentItem->children.indexOf(item);
       
   287         parentItem->children.removeAt(row);
       
   288         if (hasHeader(parentItem))
       
   289             row += 2;
       
   290     } else {
       
   291         row = m_children.indexOf(item);
       
   292         m_children.removeAt(row);
       
   293     }
       
   294 
       
   295     if (item->widget)
       
   296         delete item->widget;
       
   297     if (item->label)
       
   298         delete item->label;
       
   299     if (item->widgetLabel)
       
   300         delete item->widgetLabel;
       
   301     if (item->groupBox)
       
   302         delete item->groupBox;
       
   303 
       
   304     if (!parentItem) {
       
   305         removeRow(m_mainLayout, row);
       
   306     } else if (parentItem->children.count() != 0) {
       
   307         removeRow(parentItem->layout, row);
       
   308     } else {
       
   309         WidgetItem *par = parentItem->parent;
       
   310         QWidget *w = 0;
       
   311         QGridLayout *l = 0;
       
   312         int oldRow = -1;
       
   313         if (!par) {
       
   314             w = q_ptr;
       
   315             l = m_mainLayout;
       
   316             oldRow = m_children.indexOf(parentItem);
       
   317         } else {
       
   318             w = par->groupBox;
       
   319             l = par->layout;
       
   320             oldRow = par->children.indexOf(parentItem);
       
   321             if (hasHeader(par))
       
   322                 oldRow += 2;
       
   323         }
       
   324 
       
   325         if (parentItem->widget) {
       
   326             parentItem->widget->hide();
       
   327             parentItem->widget->setParent(0);
       
   328         } else if (parentItem->widgetLabel) {
       
   329             parentItem->widgetLabel->hide();
       
   330             parentItem->widgetLabel->setParent(0);
       
   331         } else {
       
   332             //parentItem->widgetLabel = new QLabel(w);
       
   333         }
       
   334         l->removeWidget(parentItem->groupBox);
       
   335         delete parentItem->groupBox;
       
   336         parentItem->groupBox = 0;
       
   337         parentItem->line = 0;
       
   338         parentItem->layout = 0;
       
   339         if (!m_recreateQueue.contains(parentItem))
       
   340             m_recreateQueue.append(parentItem);
       
   341         updateLater();
       
   342     }
       
   343     m_recreateQueue.removeAll(item);
       
   344 
       
   345     delete item;
       
   346 }
       
   347 
       
   348 void QtGroupBoxPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const
       
   349 {
       
   350     QMap<QLayoutItem *, QRect> itemToPos;
       
   351     int idx = 0;
       
   352     while (idx < layout->count()) {
       
   353         int r, c, rs, cs;
       
   354         layout->getItemPosition(idx, &r, &c, &rs, &cs);
       
   355         if (r >= row) {
       
   356             itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs);
       
   357         } else {
       
   358             idx++;
       
   359         }
       
   360     }
       
   361 
       
   362     const QMap<QLayoutItem *, QRect>::ConstIterator icend = itemToPos.constEnd();
       
   363     for (QMap<QLayoutItem *, QRect>::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) {
       
   364         const QRect r = it.value();
       
   365         layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
       
   366     }
       
   367 }
       
   368 
       
   369 void QtGroupBoxPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const
       
   370 {
       
   371     QMap<QLayoutItem *, QRect> itemToPos;
       
   372     int idx = 0;
       
   373     while (idx < layout->count()) {
       
   374         int r, c, rs, cs;
       
   375         layout->getItemPosition(idx, &r, &c, &rs, &cs);
       
   376         if (r > row) {
       
   377             itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs);
       
   378         } else {
       
   379             idx++;
       
   380         }
       
   381     }
       
   382 
       
   383     const QMap<QLayoutItem *, QRect>::ConstIterator icend = itemToPos.constEnd();
       
   384     for (QMap<QLayoutItem *, QRect>::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) {
       
   385         const QRect r = it.value();
       
   386         layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
       
   387     }
       
   388 }
       
   389 
       
   390 bool QtGroupBoxPropertyBrowserPrivate::hasHeader(WidgetItem *item) const
       
   391 {
       
   392     if (item->widget)
       
   393         return true;
       
   394     return false;
       
   395 }
       
   396 
       
   397 void QtGroupBoxPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index)
       
   398 {
       
   399     WidgetItem *item = m_indexToItem.value(index);
       
   400 
       
   401     updateItem(item);
       
   402 }
       
   403 
       
   404 void QtGroupBoxPropertyBrowserPrivate::updateItem(WidgetItem *item)
       
   405 {
       
   406     QtProperty *property = m_itemToIndex[item]->property();
       
   407     if (item->groupBox) {
       
   408         QFont font = item->groupBox->font();
       
   409         font.setUnderline(property->isModified());
       
   410         item->groupBox->setFont(font);
       
   411         item->groupBox->setTitle(property->propertyName());
       
   412         item->groupBox->setToolTip(property->toolTip());
       
   413         item->groupBox->setStatusTip(property->statusTip());
       
   414         item->groupBox->setWhatsThis(property->whatsThis());
       
   415         item->groupBox->setEnabled(property->isEnabled());
       
   416     }
       
   417     if (item->label) {
       
   418         QFont font = item->label->font();
       
   419         font.setUnderline(property->isModified());
       
   420         item->label->setFont(font);
       
   421         item->label->setText(property->propertyName());
       
   422         item->label->setToolTip(property->toolTip());
       
   423         item->label->setStatusTip(property->statusTip());
       
   424         item->label->setWhatsThis(property->whatsThis());
       
   425         item->label->setEnabled(property->isEnabled());
       
   426     }
       
   427     if (item->widgetLabel) {
       
   428         QFont font = item->widgetLabel->font();
       
   429         font.setUnderline(false);
       
   430         item->widgetLabel->setFont(font);
       
   431         item->widgetLabel->setText(property->valueText());
       
   432         item->widgetLabel->setEnabled(property->isEnabled());
       
   433     }
       
   434     if (item->widget) {
       
   435         QFont font = item->widget->font();
       
   436         font.setUnderline(false);
       
   437         item->widget->setFont(font);
       
   438         item->widget->setEnabled(property->isEnabled());
       
   439         item->widget->setToolTip(property->valueText());
       
   440     }
       
   441     //item->setIcon(1, property->valueIcon());
       
   442 }
       
   443 
       
   444 
       
   445 
       
   446 /*!
       
   447     \class QtGroupBoxPropertyBrowser
       
   448     \internal
       
   449     \inmodule QtDesigner
       
   450     \since 4.4
       
   451 
       
   452     \brief The QtGroupBoxPropertyBrowser class provides a QGroupBox
       
   453     based property browser.
       
   454 
       
   455     A property browser is a widget that enables the user to edit a
       
   456     given set of properties. Each property is represented by a label
       
   457     specifying the property's name, and an editing widget (e.g. a line
       
   458     edit or a combobox) holding its value. A property can have zero or
       
   459     more subproperties.
       
   460 
       
   461     QtGroupBoxPropertyBrowser provides group boxes for all nested
       
   462     properties, i.e. subproperties are enclosed by a group box with
       
   463     the parent property's name as its title. For example:
       
   464 
       
   465     \image qtgroupboxpropertybrowser.png
       
   466 
       
   467     Use the QtAbstractPropertyBrowser API to add, insert and remove
       
   468     properties from an instance of the QtGroupBoxPropertyBrowser
       
   469     class. The properties themselves are created and managed by
       
   470     implementations of the QtAbstractPropertyManager class.
       
   471 
       
   472     \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser
       
   473 */
       
   474 
       
   475 /*!
       
   476     Creates a property browser with the given \a parent.
       
   477 */
       
   478 QtGroupBoxPropertyBrowser::QtGroupBoxPropertyBrowser(QWidget *parent)
       
   479     : QtAbstractPropertyBrowser(parent), d_ptr(new QtGroupBoxPropertyBrowserPrivate)
       
   480 {
       
   481     d_ptr->q_ptr = this;
       
   482 
       
   483     d_ptr->init(this);
       
   484 }
       
   485 
       
   486 /*!
       
   487     Destroys this property browser.
       
   488 
       
   489     Note that the properties that were inserted into this browser are
       
   490     \e not destroyed since they may still be used in other
       
   491     browsers. The properties are owned by the manager that created
       
   492     them.
       
   493 
       
   494     \sa QtProperty, QtAbstractPropertyManager
       
   495 */
       
   496 QtGroupBoxPropertyBrowser::~QtGroupBoxPropertyBrowser()
       
   497 {
       
   498     const QMap<QtGroupBoxPropertyBrowserPrivate::WidgetItem *, QtBrowserItem *>::ConstIterator icend = d_ptr->m_itemToIndex.constEnd();
       
   499     for (QMap<QtGroupBoxPropertyBrowserPrivate::WidgetItem *, QtBrowserItem *>::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it)
       
   500         delete it.key();
       
   501 }
       
   502 
       
   503 /*!
       
   504     \reimp
       
   505 */
       
   506 void QtGroupBoxPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem)
       
   507 {
       
   508     d_ptr->propertyInserted(item, afterItem);
       
   509 }
       
   510 
       
   511 /*!
       
   512     \reimp
       
   513 */
       
   514 void QtGroupBoxPropertyBrowser::itemRemoved(QtBrowserItem *item)
       
   515 {
       
   516     d_ptr->propertyRemoved(item);
       
   517 }
       
   518 
       
   519 /*!
       
   520     \reimp
       
   521 */
       
   522 void QtGroupBoxPropertyBrowser::itemChanged(QtBrowserItem *item)
       
   523 {
       
   524     d_ptr->propertyChanged(item);
       
   525 }
       
   526 
       
   527 QT_END_NAMESPACE
       
   528 
       
   529 #include "moc_qtgroupboxpropertybrowser.cpp"