tools/designer/src/uitools/quiloader.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 Qt Designer 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 
       
    43 #include "quiloader.h"
       
    44 #include "quiloader_p.h"
       
    45 #include "customwidget.h"
       
    46 
       
    47 #include <formbuilder.h>
       
    48 #include <formbuilderextra_p.h>
       
    49 #include <textbuilder_p.h>
       
    50 #include <ui4_p.h>
       
    51 
       
    52 #include <QtCore/qdebug.h>
       
    53 #include <QtGui/QAction>
       
    54 #include <QtGui/QActionGroup>
       
    55 #include <QtGui/QApplication>
       
    56 #include <QtCore/QDir>
       
    57 #include <QtCore/QLibraryInfo>
       
    58 #include <QtGui/QLayout>
       
    59 #include <QtGui/QWidget>
       
    60 #include <QtCore/QMap>
       
    61 #include <QtGui/QTabWidget>
       
    62 #include <QtGui/QTreeWidget>
       
    63 #include <QtGui/QListWidget>
       
    64 #include <QtGui/QTableWidget>
       
    65 #include <QtGui/QToolBox>
       
    66 #include <QtGui/QComboBox>
       
    67 #include <QtGui/QFontComboBox>
       
    68 
       
    69 QT_BEGIN_NAMESPACE
       
    70 
       
    71 typedef QMap<QString, bool> widget_map;
       
    72 Q_GLOBAL_STATIC(widget_map, g_widgets)
       
    73 
       
    74 class QUiLoader;
       
    75 class QUiLoaderPrivate;
       
    76 
       
    77 #ifdef QFORMINTERNAL_NAMESPACE
       
    78 namespace QFormInternal
       
    79 {
       
    80 #endif
       
    81 
       
    82 class TranslatingTextBuilder : public QTextBuilder
       
    83 {
       
    84 public:
       
    85     TranslatingTextBuilder(bool trEnabled, const QByteArray &className) :
       
    86         m_trEnabled(trEnabled), m_className(className) {}
       
    87 
       
    88     virtual QVariant loadText(const DomProperty *icon) const;
       
    89 
       
    90     virtual QVariant toNativeValue(const QVariant &value) const;
       
    91 
       
    92 private:
       
    93     bool m_trEnabled;
       
    94     QByteArray m_className;
       
    95 };
       
    96 
       
    97 QVariant TranslatingTextBuilder::loadText(const DomProperty *text) const
       
    98 {
       
    99     const DomString *str = text->elementString();
       
   100     if (!str)
       
   101         return QVariant();
       
   102     if (str->hasAttributeNotr()) {
       
   103         const QString notr = str->attributeNotr();
       
   104         if (notr == QLatin1String("true") || notr == QLatin1String("yes"))
       
   105             return qVariantFromValue(str->text());
       
   106     }
       
   107     QUiTranslatableStringValue strVal;
       
   108     strVal.setValue(str->text().toUtf8());
       
   109     if (str->hasAttributeComment())
       
   110         strVal.setComment(str->attributeComment().toUtf8());
       
   111     return qVariantFromValue(strVal);
       
   112 }
       
   113 
       
   114 QVariant TranslatingTextBuilder::toNativeValue(const QVariant &value) const
       
   115 {
       
   116     if (qVariantCanConvert<QUiTranslatableStringValue>(value)) {
       
   117         QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(value);
       
   118         if (!m_trEnabled)
       
   119             return QString::fromUtf8(tsv.value().data());
       
   120         return qVariantFromValue(
       
   121             QApplication::translate(m_className, tsv.value(), tsv.comment(),
       
   122                                     QCoreApplication::UnicodeUTF8));
       
   123     }
       
   124     if (qVariantCanConvert<QString>(value))
       
   125         return qVariantFromValue(qVariantValue<QString>(value));
       
   126     return value;
       
   127 }
       
   128 
       
   129 // This is "exported" to linguist
       
   130 const QUiItemRolePair qUiItemRoles[] = {
       
   131     { Qt::DisplayRole, Qt::DisplayPropertyRole },
       
   132 #ifndef QT_NO_TOOLTIP
       
   133     { Qt::ToolTipRole, Qt::ToolTipPropertyRole },
       
   134 #endif
       
   135 #ifndef QT_NO_STATUSTIP
       
   136     { Qt::StatusTipRole, Qt::StatusTipPropertyRole },
       
   137 #endif
       
   138 #ifndef QT_NO_WHATSTHIS
       
   139     { Qt::WhatsThisRole, Qt::WhatsThisPropertyRole },
       
   140 #endif
       
   141     { -1 , -1 }
       
   142 };
       
   143 
       
   144 static void recursiveReTranslate(QTreeWidgetItem *item, const QByteArray &class_name)
       
   145 {
       
   146     const QUiItemRolePair *irs = qUiItemRoles;
       
   147 
       
   148     int cnt = item->columnCount();
       
   149     for (int i = 0; i < cnt; ++i) {
       
   150         for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
       
   151             QVariant v = item->data(i, irs[j].shadowRole);
       
   152             if (v.isValid()) {
       
   153                 QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v);
       
   154                 const QString text = QApplication::translate(class_name,
       
   155                                                              tsv.value(), tsv.comment(),
       
   156                                                              QCoreApplication::UnicodeUTF8);
       
   157                 item->setData(i, irs[j].realRole, text);
       
   158             }
       
   159         }
       
   160     }
       
   161 
       
   162     cnt = item->childCount();
       
   163     for (int i = 0; i < cnt; ++i)
       
   164         recursiveReTranslate(item->child(i), class_name);
       
   165 }
       
   166 
       
   167 template<typename T>
       
   168 static void reTranslateWidgetItem(T *item, const QByteArray &class_name)
       
   169 {
       
   170     const QUiItemRolePair *irs = qUiItemRoles;
       
   171 
       
   172     for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
       
   173         QVariant v = item->data(irs[j].shadowRole);
       
   174         if (v.isValid()) {
       
   175             QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v);
       
   176             const QString text = QApplication::translate(class_name,
       
   177                                                          tsv.value(), tsv.comment(),
       
   178                                                          QCoreApplication::UnicodeUTF8);
       
   179             item->setData(irs[j].realRole, text);
       
   180         }
       
   181     }
       
   182 }
       
   183 
       
   184 static void reTranslateTableItem(QTableWidgetItem *item, const QByteArray &class_name)
       
   185 {
       
   186     if (item)
       
   187         reTranslateWidgetItem(item, class_name);
       
   188 }
       
   189 
       
   190 #define RETRANSLATE_SUBWIDGET_PROP(mainWidget, setter, propName) \
       
   191     do { \
       
   192         QVariant v = mainWidget->widget(i)->property(propName); \
       
   193         if (v.isValid()) { \
       
   194             QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); \
       
   195             const QString text = QApplication::translate(m_className, \
       
   196                                                          tsv.value(), tsv.comment(), \
       
   197                                                          QCoreApplication::UnicodeUTF8); \
       
   198             mainWidget->setter(i, text); \
       
   199         } \
       
   200     } while (0)
       
   201 
       
   202 class TranslationWatcher: public QObject
       
   203 {
       
   204     Q_OBJECT
       
   205 
       
   206 public:
       
   207     TranslationWatcher(QObject *parent, const QByteArray &className):
       
   208         QObject(parent),
       
   209         m_className(className)
       
   210     {
       
   211     }
       
   212 
       
   213     virtual bool eventFilter(QObject *o, QEvent *event)
       
   214     {
       
   215         if (event->type() == QEvent::LanguageChange) {
       
   216             foreach (const QByteArray &prop, o->dynamicPropertyNames()) {
       
   217                 if (prop.startsWith(PROP_GENERIC_PREFIX)) {
       
   218                     const QByteArray propName = prop.mid(sizeof(PROP_GENERIC_PREFIX) - 1);
       
   219                     const QUiTranslatableStringValue tsv =
       
   220                                 qVariantValue<QUiTranslatableStringValue>(o->property(prop));
       
   221                     const QString text = QApplication::translate(m_className,
       
   222                                                                  tsv.value(), tsv.comment(),
       
   223                                                                  QCoreApplication::UnicodeUTF8);
       
   224                     o->setProperty(propName, text);
       
   225                 }
       
   226             }
       
   227             if (0) {
       
   228 #ifndef QT_NO_TABWIDGET
       
   229             } else if (QTabWidget *tabw = qobject_cast<QTabWidget*>(o)) {
       
   230                 const int cnt = tabw->count();
       
   231                 for (int i = 0; i < cnt; ++i) {
       
   232                     RETRANSLATE_SUBWIDGET_PROP(tabw, setTabText, PROP_TABPAGETEXT);
       
   233 # ifndef QT_NO_TOOLTIP
       
   234                     RETRANSLATE_SUBWIDGET_PROP(tabw, setTabToolTip, PROP_TABPAGETOOLTIP);
       
   235 # endif
       
   236 # ifndef QT_NO_WHATSTHIS
       
   237                     RETRANSLATE_SUBWIDGET_PROP(tabw, setTabWhatsThis, PROP_TABPAGEWHATSTHIS);
       
   238 # endif
       
   239                 }
       
   240 #endif
       
   241 #ifndef QT_NO_LISTWIDGET
       
   242             } else if (QListWidget *listw = qobject_cast<QListWidget*>(o)) {
       
   243                 const int cnt = listw->count();
       
   244                 for (int i = 0; i < cnt; ++i)
       
   245                     reTranslateWidgetItem(listw->item(i), m_className);
       
   246 #endif
       
   247 #ifndef QT_NO_TREEWIDGET
       
   248             } else if (QTreeWidget *treew = qobject_cast<QTreeWidget*>(o)) {
       
   249                 if (QTreeWidgetItem *item = treew->headerItem())
       
   250                     recursiveReTranslate(item, m_className);
       
   251                 const int cnt = treew->topLevelItemCount();
       
   252                 for (int i = 0; i < cnt; ++i) {
       
   253                     QTreeWidgetItem *item = treew->topLevelItem(i);
       
   254                     recursiveReTranslate(item, m_className);
       
   255                 }
       
   256 #endif
       
   257 #ifndef QT_NO_TABLEWIDGET
       
   258             } else if (QTableWidget *tablew = qobject_cast<QTableWidget*>(o)) {
       
   259                 const int row_cnt = tablew->rowCount();
       
   260                 const int col_cnt = tablew->columnCount();
       
   261                 for (int j = 0; j < col_cnt; ++j)
       
   262                     reTranslateTableItem(tablew->horizontalHeaderItem(j), m_className);
       
   263                 for (int i = 0; i < row_cnt; ++i) {
       
   264                     reTranslateTableItem(tablew->verticalHeaderItem(i), m_className);
       
   265                     for (int j = 0; j < col_cnt; ++j)
       
   266                         reTranslateTableItem(tablew->item(i, j), m_className);
       
   267                 }
       
   268 #endif
       
   269 #ifndef QT_NO_COMBOBOX
       
   270             } else if (QComboBox *combow = qobject_cast<QComboBox*>(o)) {
       
   271                 if (!qobject_cast<QFontComboBox*>(o)) {
       
   272                     const int cnt = combow->count();
       
   273                     for (int i = 0; i < cnt; ++i) {
       
   274                         const QVariant v = combow->itemData(i, Qt::DisplayPropertyRole);
       
   275                         if (v.isValid()) {
       
   276                             QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v);
       
   277                             const QString text = QApplication::translate(m_className,
       
   278                                                                          tsv.value(), tsv.comment(),
       
   279                                                                          QCoreApplication::UnicodeUTF8);
       
   280                             combow->setItemText(i, text);
       
   281                         }
       
   282                     }
       
   283                 }
       
   284 #endif
       
   285 #ifndef QT_NO_TOOLBOX
       
   286             } else if (QToolBox *toolw = qobject_cast<QToolBox*>(o)) {
       
   287                 const int cnt = toolw->count();
       
   288                 for (int i = 0; i < cnt; ++i) {
       
   289                     RETRANSLATE_SUBWIDGET_PROP(toolw, setItemText, PROP_TOOLITEMTEXT);
       
   290 # ifndef QT_NO_TOOLTIP
       
   291                     RETRANSLATE_SUBWIDGET_PROP(toolw, setItemToolTip, PROP_TOOLITEMTOOLTIP);
       
   292 # endif
       
   293                 }
       
   294 #endif
       
   295             }
       
   296         }
       
   297         return false;
       
   298     }
       
   299 
       
   300 private:
       
   301     QByteArray m_className;
       
   302 };
       
   303 
       
   304 class FormBuilderPrivate: public QFormBuilder
       
   305 {
       
   306     friend class QT_PREPEND_NAMESPACE(QUiLoader);
       
   307     friend class QT_PREPEND_NAMESPACE(QUiLoaderPrivate);
       
   308     typedef QFormBuilder ParentClass;
       
   309 
       
   310 public:
       
   311     QUiLoader *loader;
       
   312 
       
   313     bool dynamicTr;
       
   314     bool trEnabled;
       
   315 
       
   316     FormBuilderPrivate(): loader(0), dynamicTr(false), trEnabled(true), m_trwatch(0) {}
       
   317 
       
   318     QWidget *defaultCreateWidget(const QString &className, QWidget *parent, const QString &name)
       
   319     {
       
   320         return ParentClass::createWidget(className, parent, name);
       
   321     }
       
   322 
       
   323     QLayout *defaultCreateLayout(const QString &className, QObject *parent, const QString &name)
       
   324     {
       
   325         return ParentClass::createLayout(className, parent, name);
       
   326     }
       
   327 
       
   328     QAction *defaultCreateAction(QObject *parent, const QString &name)
       
   329     {
       
   330         return ParentClass::createAction(parent, name);
       
   331     }
       
   332 
       
   333     QActionGroup *defaultCreateActionGroup(QObject *parent, const QString &name)
       
   334     {
       
   335         return ParentClass::createActionGroup(parent, name);
       
   336     }
       
   337 
       
   338     virtual QWidget *createWidget(const QString &className, QWidget *parent, const QString &name)
       
   339     {
       
   340         if (QWidget *widget = loader->createWidget(className, parent, name)) {
       
   341             widget->setObjectName(name);
       
   342             return widget;
       
   343         }
       
   344 
       
   345         return 0;
       
   346     }
       
   347 
       
   348     virtual QLayout *createLayout(const QString &className, QObject *parent, const QString &name)
       
   349     {
       
   350         if (QLayout *layout = loader->createLayout(className, parent, name)) {
       
   351             layout->setObjectName(name);
       
   352             return layout;
       
   353         }
       
   354 
       
   355         return 0;
       
   356     }
       
   357 
       
   358     virtual QActionGroup *createActionGroup(QObject *parent, const QString &name)
       
   359     {
       
   360         if (QActionGroup *actionGroup = loader->createActionGroup(parent, name)) {
       
   361             actionGroup->setObjectName(name);
       
   362             return actionGroup;
       
   363         }
       
   364 
       
   365         return 0;
       
   366     }
       
   367 
       
   368     virtual QAction *createAction(QObject *parent, const QString &name)
       
   369     {
       
   370         if (QAction *action = loader->createAction(parent, name)) {
       
   371             action->setObjectName(name);
       
   372             return action;
       
   373         }
       
   374 
       
   375         return 0;
       
   376     }
       
   377 
       
   378     virtual void applyProperties(QObject *o, const QList<DomProperty*> &properties);
       
   379     virtual QWidget *create(DomUI *ui, QWidget *parentWidget);
       
   380     virtual QWidget *create(DomWidget *ui_widget, QWidget *parentWidget);
       
   381     virtual bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
       
   382 
       
   383 private:
       
   384     QByteArray m_class;
       
   385     TranslationWatcher *m_trwatch;
       
   386 };
       
   387 
       
   388 static QString convertTranslatable(const DomProperty *p, const QByteArray &className,
       
   389     QUiTranslatableStringValue *strVal)
       
   390 {
       
   391     if (p->kind() != DomProperty::String)
       
   392         return QString();
       
   393     const DomString *dom_str = p->elementString();
       
   394     if (!dom_str)
       
   395         return QString();
       
   396     if (dom_str->hasAttributeNotr()) {
       
   397         const QString notr = dom_str->attributeNotr();
       
   398         if (notr == QLatin1String("yes") || notr == QLatin1String("true"))
       
   399             return QString();
       
   400     }
       
   401     strVal->setValue(dom_str->text().toUtf8());
       
   402     strVal->setComment(dom_str->attributeComment().toUtf8());
       
   403     if (strVal->value().isEmpty() && strVal->comment().isEmpty())
       
   404         return QString();
       
   405     return QApplication::translate(className,
       
   406                                    strVal->value(), strVal->comment(),
       
   407                                    QCoreApplication::UnicodeUTF8);
       
   408 }
       
   409 
       
   410 void FormBuilderPrivate::applyProperties(QObject *o, const QList<DomProperty*> &properties)
       
   411 {
       
   412     typedef QList<DomProperty*> DomPropertyList;
       
   413 
       
   414     QFormBuilder::applyProperties(o, properties);
       
   415 
       
   416     if (!m_trwatch)
       
   417         m_trwatch = new TranslationWatcher(o, m_class);
       
   418 
       
   419     if (properties.empty())
       
   420         return;
       
   421 
       
   422     // Unlike string item roles, string properties are not loaded via the textBuilder
       
   423     // (as they are "shadowed" by the property sheets in designer). So do the initial
       
   424     // translation here.
       
   425     bool anyTrs = false;
       
   426     foreach (const DomProperty *p, properties) {
       
   427         QUiTranslatableStringValue strVal;
       
   428         const QString text = convertTranslatable(p, m_class, &strVal);
       
   429         if (text.isEmpty())
       
   430             continue;
       
   431         const QByteArray name = p->attributeName().toUtf8();
       
   432         if (dynamicTr) {
       
   433             o->setProperty(PROP_GENERIC_PREFIX + name, qVariantFromValue(strVal));
       
   434             anyTrs = trEnabled;
       
   435         }
       
   436         o->setProperty(name, text);
       
   437     }
       
   438     if (anyTrs)
       
   439         o->installEventFilter(m_trwatch);
       
   440 }
       
   441 
       
   442 QWidget *FormBuilderPrivate::create(DomUI *ui, QWidget *parentWidget)
       
   443 {
       
   444     m_class = ui->elementClass().toUtf8();
       
   445     m_trwatch = 0;
       
   446     setTextBuilder(new TranslatingTextBuilder(trEnabled, m_class));
       
   447     return QFormBuilder::create(ui, parentWidget);
       
   448 }
       
   449 
       
   450 QWidget *FormBuilderPrivate::create(DomWidget *ui_widget, QWidget *parentWidget)
       
   451 {
       
   452     QWidget *w = QFormBuilder::create(ui_widget, parentWidget);
       
   453     if (w == 0)
       
   454         return 0;
       
   455 
       
   456     if (0) {
       
   457 #ifndef QT_NO_TABWIDGET
       
   458     } else if (qobject_cast<QTabWidget*>(w)) {
       
   459 #endif
       
   460 #ifndef QT_NO_LISTWIDGET
       
   461     } else if (qobject_cast<QListWidget*>(w)) {
       
   462 #endif
       
   463 #ifndef QT_NO_TREEWIDGET
       
   464     } else if (qobject_cast<QTreeWidget*>(w)) {
       
   465 #endif
       
   466 #ifndef QT_NO_TABLEWIDGET
       
   467     } else if (qobject_cast<QTableWidget*>(w)) {
       
   468 #endif
       
   469 #ifndef QT_NO_COMBOBOX
       
   470     } else if (qobject_cast<QComboBox*>(w)) {
       
   471         if (qobject_cast<QFontComboBox*>(w))
       
   472             return w;
       
   473 #endif
       
   474 #ifndef QT_NO_TOOLBOX
       
   475     } else if (qobject_cast<QToolBox*>(w)) {
       
   476 #endif
       
   477     } else {
       
   478         return w;
       
   479     }
       
   480     if (dynamicTr && trEnabled)
       
   481         w->installEventFilter(m_trwatch);
       
   482     return w;
       
   483 }
       
   484 
       
   485 #define TRANSLATE_SUBWIDGET_PROP(mainWidget, attribute, setter, propName) \
       
   486     do { \
       
   487         if (const DomProperty *p##attribute = attributes.value(strings.attribute)) { \
       
   488             QUiTranslatableStringValue strVal; \
       
   489             const QString text = convertTranslatable(p##attribute, m_class, &strVal); \
       
   490             if (!text.isEmpty()) { \
       
   491                 if (dynamicTr) \
       
   492                     mainWidget->widget(i)->setProperty(propName, qVariantFromValue(strVal)); \
       
   493                 mainWidget->setter(i, text); \
       
   494             } \
       
   495         } \
       
   496     } while (0)
       
   497 
       
   498 bool FormBuilderPrivate::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
       
   499 {
       
   500     if (parentWidget == 0)
       
   501         return true;
       
   502 
       
   503     if (!ParentClass::addItem(ui_widget, widget, parentWidget))
       
   504         return false;
       
   505 
       
   506     // Check special cases. First: Custom container
       
   507     const QString className = QLatin1String(parentWidget->metaObject()->className());
       
   508     if (!QFormBuilderExtra::instance(this)->customWidgetAddPageMethod(className).isEmpty())
       
   509         return true;
       
   510 
       
   511     const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
       
   512 
       
   513     if (0) {
       
   514 #ifndef QT_NO_TABWIDGET
       
   515     } else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(parentWidget)) {
       
   516         const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
       
   517         const int i = tabWidget->count() - 1;
       
   518         TRANSLATE_SUBWIDGET_PROP(tabWidget, titleAttribute, setTabText, PROP_TABPAGETEXT);
       
   519 # ifndef QT_NO_TOOLTIP
       
   520         TRANSLATE_SUBWIDGET_PROP(tabWidget, toolTipAttribute, setTabToolTip, PROP_TABPAGETOOLTIP);
       
   521 # endif
       
   522 # ifndef QT_NO_WHATSTHIS
       
   523         TRANSLATE_SUBWIDGET_PROP(tabWidget, whatsThisAttribute, setTabWhatsThis, PROP_TABPAGEWHATSTHIS);
       
   524 # endif
       
   525 #endif
       
   526 #ifndef QT_NO_TOOLBOX
       
   527     } else if (QToolBox *toolBox = qobject_cast<QToolBox*>(parentWidget)) {
       
   528         const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
       
   529         const int i = toolBox->count() - 1;
       
   530         TRANSLATE_SUBWIDGET_PROP(toolBox, labelAttribute, setItemText, PROP_TOOLITEMTEXT);
       
   531 # ifndef QT_NO_TOOLTIP
       
   532         TRANSLATE_SUBWIDGET_PROP(toolBox, toolTipAttribute, setItemToolTip, PROP_TOOLITEMTOOLTIP);
       
   533 # endif
       
   534 #endif
       
   535     }
       
   536 
       
   537     return true;
       
   538 }
       
   539 
       
   540 #ifdef QFORMINTERNAL_NAMESPACE
       
   541 }
       
   542 #endif
       
   543 
       
   544 class QUiLoaderPrivate
       
   545 {
       
   546 public:
       
   547 #ifdef QFORMINTERNAL_NAMESPACE
       
   548     QFormInternal::FormBuilderPrivate builder;
       
   549 #else
       
   550     FormBuilderPrivate builder;
       
   551 #endif
       
   552 
       
   553     void setupWidgetMap() const;
       
   554 };
       
   555 
       
   556 void QUiLoaderPrivate::setupWidgetMap() const
       
   557 {
       
   558     if (!g_widgets()->isEmpty())
       
   559         return;
       
   560 
       
   561 #define DECLARE_WIDGET(a, b) g_widgets()->insert(QLatin1String(#a), true);
       
   562 #define DECLARE_LAYOUT(a, b)
       
   563 
       
   564 #include "widgets.table"
       
   565 
       
   566 #undef DECLARE_WIDGET
       
   567 #undef DECLARE_WIDGET_1
       
   568 #undef DECLARE_LAYOUT
       
   569 }
       
   570 
       
   571 /*!
       
   572     \class QUiLoader
       
   573     \inmodule QtUiTools
       
   574 
       
   575     \brief The QUiLoader class enables standalone applications to
       
   576     dynamically create user interfaces at run-time using the
       
   577     information stored in UI files or specified in plugin paths.
       
   578 
       
   579     In addition, you can customize or create your own user interface by
       
   580     deriving your own loader class.
       
   581 
       
   582     If you have a custom component or an application that embeds \QD, you can
       
   583     also use the QFormBuilder class provided by the QtDesigner module to create
       
   584     user interfaces from UI files.
       
   585 
       
   586     The QUiLoader class provides a collection of functions allowing you to
       
   587     create widgets based on the information stored in UI files (created
       
   588     with \QD) or available in the specified plugin paths. The specified plugin
       
   589     paths can be retrieved using the pluginPaths() function. Similarly, the
       
   590     contents of a UI file can be retrieved using the load() function. For
       
   591     example:
       
   592 
       
   593     \snippet doc/src/snippets/quiloader/mywidget.cpp 0
       
   594 
       
   595     By including the user interface in the form's resources (\c myform.qrc), we
       
   596     ensure that it will be present at run-time:
       
   597 
       
   598     \quotefile doc/src/snippets/quiloader/mywidget.qrc
       
   599 
       
   600     The availableWidgets() function returns a QStringList with the class names
       
   601     of the widgets available in the specified plugin paths. To create these
       
   602     widgets, simply use the createWidget() function. For example:
       
   603 
       
   604     \snippet doc/src/snippets/quiloader/main.cpp 0
       
   605 
       
   606     To make a custom widget available to the loader, you can use the
       
   607     addPluginPath() function; to remove all available widgets, you can call
       
   608     the clearPluginPaths() function.
       
   609 
       
   610     The createAction(), createActionGroup(), createLayout(), and createWidget()
       
   611     functions are used internally by the QUiLoader class whenever it has to
       
   612     create an action, action group, layout, or widget respectively. For that
       
   613     reason, you can subclass the QUiLoader class and reimplement these
       
   614     functions to intervene the process of constructing a user interface. For
       
   615     example, you might want to have a list of the actions created when loading
       
   616     a form or creating a custom widget.
       
   617 
       
   618     For a complete example using the QUiLoader class, see the
       
   619     \l{Calculator Builder Example}.
       
   620 
       
   621     \sa QtUiTools, QFormBuilder
       
   622 */
       
   623 
       
   624 /*!
       
   625     Creates a form loader with the given \a parent.
       
   626 */
       
   627 QUiLoader::QUiLoader(QObject *parent)
       
   628     : QObject(parent), d_ptr(new QUiLoaderPrivate)
       
   629 {
       
   630     Q_D(QUiLoader);
       
   631 
       
   632     d->builder.loader = this;
       
   633 
       
   634     QStringList paths;
       
   635     foreach (const QString &path, QApplication::libraryPaths()) {
       
   636         QString libPath = path;
       
   637         libPath  += QDir::separator();
       
   638         libPath  += QLatin1String("designer");
       
   639         paths.append(libPath);
       
   640     }
       
   641 
       
   642     d->builder.setPluginPath(paths);
       
   643 }
       
   644 
       
   645 /*!
       
   646     Destroys the loader.
       
   647 */
       
   648 QUiLoader::~QUiLoader()
       
   649 {
       
   650 }
       
   651 
       
   652 /*!
       
   653     Loads a form from the given \a device and creates a new widget with the
       
   654     given \a parentWidget to hold its contents.
       
   655 
       
   656     \sa createWidget()
       
   657 */
       
   658 QWidget *QUiLoader::load(QIODevice *device, QWidget *parentWidget)
       
   659 {
       
   660     Q_D(QUiLoader);
       
   661     // QXmlStreamReader will report errors on open failure.
       
   662     if (!device->isOpen())
       
   663         device->open(QIODevice::ReadOnly|QIODevice::Text);
       
   664     return d->builder.load(device, parentWidget);
       
   665 }
       
   666 
       
   667 /*!
       
   668     Returns a list naming the paths in which the loader will search when
       
   669     locating custom widget plugins.
       
   670 
       
   671     \sa addPluginPath(), clearPluginPaths()
       
   672 */
       
   673 QStringList QUiLoader::pluginPaths() const
       
   674 {
       
   675     Q_D(const QUiLoader);
       
   676     return d->builder.pluginPaths();
       
   677 }
       
   678 
       
   679 /*!
       
   680     Clears the list of paths in which the loader will search when locating
       
   681     plugins.
       
   682 
       
   683     \sa addPluginPath(), pluginPaths()
       
   684 */
       
   685 void QUiLoader::clearPluginPaths()
       
   686 {
       
   687     Q_D(QUiLoader);
       
   688     d->builder.clearPluginPaths();
       
   689 }
       
   690 
       
   691 /*!
       
   692     Adds the given \a path to the list of paths in which the loader will search
       
   693     when locating plugins.
       
   694 
       
   695     \sa pluginPaths(), clearPluginPaths()
       
   696 */
       
   697 void QUiLoader::addPluginPath(const QString &path)
       
   698 {
       
   699     Q_D(QUiLoader);
       
   700     d->builder.addPluginPath(path);
       
   701 }
       
   702 
       
   703 /*!
       
   704     Creates a new widget with the given \a parent and \a name using the class
       
   705     specified by \a className. You can use this function to create any of the
       
   706     widgets returned by the availableWidgets() function.
       
   707 
       
   708     The function is also used internally by the QUiLoader class whenever it
       
   709     creates a widget. Hence, you can subclass QUiLoader and reimplement this
       
   710     function to intervene process of constructing a user interface or widget.
       
   711     However, in your implementation, ensure that you call QUiLoader's version
       
   712     first.
       
   713 
       
   714     \sa availableWidgets(), load()
       
   715 */
       
   716 QWidget *QUiLoader::createWidget(const QString &className, QWidget *parent, const QString &name)
       
   717 {
       
   718     Q_D(QUiLoader);
       
   719     return d->builder.defaultCreateWidget(className, parent, name);
       
   720 }
       
   721 
       
   722 /*!
       
   723     Creates a new layout with the given \a parent and \a name using the class
       
   724     specified by \a className.
       
   725 
       
   726     The function is also used internally by the QUiLoader class whenever it
       
   727     creates a widget. Hence, you can subclass QUiLoader and reimplement this
       
   728     function to intervene process of constructing a user interface or widget.
       
   729     However, in your implementation, ensure that you call QUiLoader's version
       
   730     first.
       
   731 
       
   732     \sa createWidget(), load()
       
   733 */
       
   734 QLayout *QUiLoader::createLayout(const QString &className, QObject *parent, const QString &name)
       
   735 {
       
   736     Q_D(QUiLoader);
       
   737     return d->builder.defaultCreateLayout(className, parent, name);
       
   738 }
       
   739 
       
   740 /*!
       
   741     Creates a new action group with the given \a parent and \a name.
       
   742 
       
   743     The function is also used internally by the QUiLoader class whenever it
       
   744     creates a widget. Hence, you can subclass QUiLoader and reimplement this
       
   745     function to intervene process of constructing a user interface or widget.
       
   746     However, in your implementation, ensure that you call QUiLoader's version
       
   747     first.
       
   748 
       
   749     \sa createAction(), createWidget(), load()
       
   750  */
       
   751 QActionGroup *QUiLoader::createActionGroup(QObject *parent, const QString &name)
       
   752 {
       
   753     Q_D(QUiLoader);
       
   754     return d->builder.defaultCreateActionGroup(parent, name);
       
   755 }
       
   756 
       
   757 /*!
       
   758     Creates a new action with the given \a parent and \a name.
       
   759 
       
   760     The function is also used internally by the QUiLoader class whenever it
       
   761     creates a widget. Hence, you can subclass QUiLoader and reimplement this
       
   762     function to intervene process of constructing a user interface or widget.
       
   763     However, in your implementation, ensure that you call QUiLoader's version
       
   764     first.
       
   765 
       
   766     \sa createActionGroup(), createWidget(), load()
       
   767 */
       
   768 QAction *QUiLoader::createAction(QObject *parent, const QString &name)
       
   769 {
       
   770     Q_D(QUiLoader);
       
   771     return d->builder.defaultCreateAction(parent, name);
       
   772 }
       
   773 
       
   774 /*!
       
   775     Returns a list naming all available widgets that can be built using the
       
   776     createWidget() function, i.e all the widgets specified within the given
       
   777     plugin paths.
       
   778 
       
   779     \sa pluginPaths(), createWidget()
       
   780 
       
   781 */
       
   782 QStringList QUiLoader::availableWidgets() const
       
   783 {
       
   784     Q_D(const QUiLoader);
       
   785 
       
   786     d->setupWidgetMap();
       
   787     widget_map available = *g_widgets();
       
   788 
       
   789     foreach (QDesignerCustomWidgetInterface *plugin, d->builder.customWidgets()) {
       
   790         available.insert(plugin->name(), true);
       
   791     }
       
   792 
       
   793     return available.keys();
       
   794 }
       
   795 
       
   796 
       
   797 /*!
       
   798     \since 4.5
       
   799     Returns a list naming all available layouts that can be built using the
       
   800     createLayout() function
       
   801 
       
   802     \sa createLayout()
       
   803 */
       
   804 
       
   805 QStringList QUiLoader::availableLayouts() const
       
   806 {
       
   807     QStringList rc;
       
   808 #define DECLARE_WIDGET(a, b)
       
   809 #define DECLARE_LAYOUT(a, b) rc.push_back(QLatin1String(#a));
       
   810 
       
   811 #include "widgets.table"
       
   812 
       
   813 #undef DECLARE_WIDGET
       
   814 #undef DECLARE_LAYOUT
       
   815     return rc;
       
   816 }
       
   817 
       
   818 /*!
       
   819     Sets the working directory of the loader to \a dir. The loader will look
       
   820     for other resources, such as icons and resource files, in paths relative to
       
   821     this directory.
       
   822 
       
   823     \sa workingDirectory()
       
   824 */
       
   825 
       
   826 void QUiLoader::setWorkingDirectory(const QDir &dir)
       
   827 {
       
   828     Q_D(QUiLoader);
       
   829     d->builder.setWorkingDirectory(dir);
       
   830 }
       
   831 
       
   832 /*!
       
   833     Returns the working directory of the loader.
       
   834 
       
   835     \sa setWorkingDirectory()
       
   836 */
       
   837 
       
   838 QDir QUiLoader::workingDirectory() const
       
   839 {
       
   840     Q_D(const QUiLoader);
       
   841     return d->builder.workingDirectory();
       
   842 }
       
   843 
       
   844 /*!
       
   845     \internal
       
   846     \since 4.3
       
   847 
       
   848     If \a enabled is true, the loader will be able to execute scripts.
       
   849     Otherwise, execution of scripts will be disabled.
       
   850 
       
   851     \sa isScriptingEnabled()
       
   852 */
       
   853 
       
   854 void QUiLoader::setScriptingEnabled(bool enabled)
       
   855 {
       
   856     Q_D(QUiLoader);
       
   857     d->builder.setScriptingEnabled(enabled);
       
   858 }
       
   859 
       
   860 /*!
       
   861     \internal
       
   862     \since 4.3
       
   863 
       
   864     Returns true if execution of scripts is enabled; returns false otherwise.
       
   865 
       
   866     \sa setScriptingEnabled()
       
   867 */
       
   868 
       
   869 bool QUiLoader::isScriptingEnabled() const
       
   870 {
       
   871     Q_D(const QUiLoader);
       
   872     return d->builder.isScriptingEnabled();
       
   873 }
       
   874 
       
   875 /*!
       
   876     \since 4.5
       
   877 
       
   878     If \a enabled is true, user interfaces loaded by this loader will
       
   879     automatically retranslate themselves upon receiving a language change
       
   880     event. Otherwise, the user interfaces will not be retranslated.
       
   881 
       
   882     \sa isLanguageChangeEnabled()
       
   883 */
       
   884 
       
   885 void QUiLoader::setLanguageChangeEnabled(bool enabled)
       
   886 {
       
   887     Q_D(QUiLoader);
       
   888     d->builder.dynamicTr = enabled;
       
   889 }
       
   890 
       
   891 /*!
       
   892     \since 4.5
       
   893 
       
   894     Returns true if dynamic retranslation on language change is enabled;
       
   895     returns false otherwise.
       
   896 
       
   897     \sa setLanguageChangeEnabled()
       
   898 */
       
   899 
       
   900 bool QUiLoader::isLanguageChangeEnabled() const
       
   901 {
       
   902     Q_D(const QUiLoader);
       
   903     return d->builder.dynamicTr;
       
   904 }
       
   905 
       
   906 /*!
       
   907     \internal
       
   908     \since 4.5
       
   909 
       
   910     If \a enabled is true, user interfaces loaded by this loader will be
       
   911     translated. Otherwise, the user interfaces will not be translated.
       
   912 
       
   913     \note This is orthogonal to languageChangeEnabled.
       
   914 
       
   915     \sa isLanguageChangeEnabled(), setLanguageChangeEnabled()
       
   916 */
       
   917 
       
   918 void QUiLoader::setTranslationEnabled(bool enabled)
       
   919 {
       
   920     Q_D(QUiLoader);
       
   921     d->builder.trEnabled = enabled;
       
   922 }
       
   923 
       
   924 /*!
       
   925     \internal
       
   926     \since 4.5
       
   927 
       
   928     Returns true if translation is enabled; returns false otherwise.
       
   929 
       
   930     \sa setTranslationEnabled()
       
   931 */
       
   932 
       
   933 bool QUiLoader::isTranslationEnabled() const
       
   934 {
       
   935     Q_D(const QUiLoader);
       
   936     return d->builder.trEnabled;
       
   937 }
       
   938 
       
   939 QT_END_NAMESPACE
       
   940 
       
   941 #include "quiloader.moc"