2011-04-27 10:05:43 +00:00
/****************************************************************************
* *
* * Copyright ( C ) 2011 Nokia Corporation and / or its subsidiary ( - ies ) .
* * All rights reserved .
* * Contact : Nokia Corporation ( qt - info @ nokia . com )
* *
* * This file is part of the Qt Designer of the Qt Toolkit .
* *
* * $ QT_BEGIN_LICENSE : LGPL $
* * GNU Lesser General Public License Usage
2011-05-24 09:34:08 +00:00
* * This file may be used under the terms of the GNU Lesser General Public
* * License version 2.1 as published by the Free Software Foundation and
* * appearing in the file LICENSE . LGPL included in the packaging of this
* * file . Please review the following information to ensure the GNU Lesser
* * General Public License version 2.1 requirements will be met :
* * http : //www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2011-04-27 10:05:43 +00:00
* *
* * In addition , as a special exception , Nokia gives you certain additional
2011-05-24 09:34:08 +00:00
* * rights . These rights are described in the Nokia Qt LGPL Exception
2011-04-27 10:05:43 +00:00
* * version 1.1 , included in the file LGPL_EXCEPTION . txt in this package .
* *
2011-05-24 09:34:08 +00:00
* * GNU General Public License Usage
* * Alternatively , this file may be used under the terms of the GNU General
* * Public License version 3.0 as published by the Free Software Foundation
* * and appearing in the file LICENSE . GPL included in the packaging of this
* * file . Please review the following information to ensure the GNU General
* * Public License version 3.0 requirements will be met :
* * http : //www.gnu.org/copyleft/gpl.html.
2011-04-27 10:05:43 +00:00
* *
2011-05-24 09:34:08 +00:00
* * Other Usage
* * Alternatively , this file may be used in accordance with the terms and
* * conditions contained in a signed written agreement between you and Nokia .
2011-04-27 10:05:43 +00:00
* *
* *
* *
* *
* *
* * $ QT_END_LICENSE $
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "customwidget.h"
# include "formbuilder.h"
# include "formbuilderextra_p.h"
# include "ui4_p.h"
# include <QtGui/QtGui>
2011-05-07 20:25:30 +00:00
# include <QtWidgets/QtWidgets>
2011-04-27 10:05:43 +00:00
# include <QtCore/QCoreApplication>
QT_BEGIN_NAMESPACE
# ifdef QFORMINTERNAL_NAMESPACE
namespace QFormInternal {
# endif
/*!
\ class QFormBuilder
\ brief The QFormBuilder class is used to dynamically construct
user interfaces from UI files at run - time .
\ inmodule QtDesigner
The QFormBuilder class provides a mechanism for dynamically
creating user interfaces at run - time , based on UI files
created with \ QD . For example :
\ snippet doc / src / snippets / code / tools_designer_src_lib_uilib_formbuilder . cpp 0
By including the user interface in the example ' s resources ( \ c
myForm . qrc ) , we ensure that it will be present when the example is
run :
\ snippet doc / src / snippets / code / tools_designer_src_lib_uilib_formbuilder . cpp 1
QFormBuilder extends the QAbstractFormBuilder base class with a
number of functions that are used to support custom widget
plugins :
\ list
\ o pluginPaths ( ) returns the list of paths that the form builder
searches when loading custom widget plugins .
\ o addPluginPath ( ) allows additional paths to be registered with
the form builder .
\ o setPluginPath ( ) is used to replace the existing list of paths
with a list obtained from some other source .
\ o clearPluginPaths ( ) removes all paths registered with the form
builder .
\ o customWidgets ( ) returns a list of interfaces to plugins that
can be used to create new instances of registered custom widgets .
\ endlist
The QFormBuilder class is typically used by custom components and
applications that embed \ QD . Standalone applications that need to
dynamically generate user interfaces at run - time use the
QUiLoader class , found in the QtUiTools module .
\ sa QAbstractFormBuilder , { QtUiTools Module }
*/
/*!
\ fn QFormBuilder : : QFormBuilder ( )
Constructs a new form builder .
*/
2011-05-04 14:19:35 +00:00
QFormBuilder : : QFormBuilder ( )
2011-04-27 10:05:43 +00:00
{
}
/*!
Destroys the form builder .
*/
QFormBuilder : : ~ QFormBuilder ( )
{
}
/*!
\ internal
*/
QWidget * QFormBuilder : : create ( DomWidget * ui_widget , QWidget * parentWidget )
{
2011-05-04 14:19:35 +00:00
if ( ! d - > parentWidgetIsSet ( ) )
d - > setParentWidget ( parentWidget ) ;
2011-04-27 10:05:43 +00:00
// Is this a QLayoutWidget with a margin of 0: Not a known page-based
// container and no method for adding pages registered.
2011-05-04 14:19:35 +00:00
d - > setProcessingLayoutWidget ( false ) ;
2011-04-27 10:05:43 +00:00
if ( ui_widget - > attributeClass ( ) = = QFormBuilderStrings : : instance ( ) . qWidgetClass & & ! ui_widget - > hasAttributeNative ( )
& & parentWidget
# ifndef QT_NO_MAINWINDOW
& & ! qobject_cast < QMainWindow * > ( parentWidget )
# endif
# ifndef QT_NO_TOOLBOX
& & ! qobject_cast < QToolBox * > ( parentWidget )
# endif
# ifndef QT_NO_STACKEDWIDGET
& & ! qobject_cast < QStackedWidget * > ( parentWidget )
# endif
# ifndef QT_NO_STACKEDWIDGET
& & ! qobject_cast < QTabWidget * > ( parentWidget )
# endif
# ifndef QT_NO_SCROLLAREA
& & ! qobject_cast < QScrollArea * > ( parentWidget )
# endif
# ifndef QT_NO_MDIAREA
& & ! qobject_cast < QMdiArea * > ( parentWidget )
# endif
# ifndef QT_NO_DOCKWIDGET
& & ! qobject_cast < QDockWidget * > ( parentWidget )
# endif
) {
const QString parentClassName = QLatin1String ( parentWidget - > metaObject ( ) - > className ( ) ) ;
2011-05-04 14:19:35 +00:00
if ( ! d - > isCustomWidgetContainer ( parentClassName ) )
d - > setProcessingLayoutWidget ( true ) ;
2011-04-27 10:05:43 +00:00
}
return QAbstractFormBuilder : : create ( ui_widget , parentWidget ) ;
}
/*!
\ internal
*/
QWidget * QFormBuilder : : createWidget ( const QString & widgetName , QWidget * parentWidget , const QString & name )
{
if ( widgetName . isEmpty ( ) ) {
//: Empty class name passed to widget factory method
qWarning ( ) < < QCoreApplication : : translate ( " QFormBuilder " , " An empty class name was passed on to %1 (object name: '%2'). " ) . arg ( QString : : fromUtf8 ( Q_FUNC_INFO ) , name ) ;
return 0 ;
}
QWidget * w = 0 ;
# ifndef QT_NO_TABWIDGET
if ( qobject_cast < QTabWidget * > ( parentWidget ) )
parentWidget = 0 ;
# endif
# ifndef QT_NO_STACKEDWIDGET
if ( qobject_cast < QStackedWidget * > ( parentWidget ) )
parentWidget = 0 ;
# endif
# ifndef QT_NO_TOOLBOX
if ( qobject_cast < QToolBox * > ( parentWidget ) )
parentWidget = 0 ;
# endif
// ### special-casing for Line (QFrame) -- fix for 4.2
do {
if ( widgetName = = QFormBuilderStrings : : instance ( ) . lineClass ) {
w = new QFrame ( parentWidget ) ;
static_cast < QFrame * > ( w ) - > setFrameStyle ( QFrame : : HLine | QFrame : : Sunken ) ;
break ;
}
const QByteArray widgetNameBA = widgetName . toUtf8 ( ) ;
const char * widgetNameC = widgetNameBA . constData ( ) ;
if ( w ) { // symmetry for macro
}
# define DECLARE_LAYOUT(L, C)
# define DECLARE_COMPAT_WIDGET(W, C)
# define DECLARE_WIDGET(W, C) else if (!qstrcmp(widgetNameC, #W)) { Q_ASSERT(w == 0); w = new W(parentWidget); }
# define DECLARE_WIDGET_1(W, C) else if (!qstrcmp(widgetNameC, #W)) { Q_ASSERT(w == 0); w = new W(0, parentWidget); }
# include "widgets.table"
# undef DECLARE_COMPAT_WIDGET
# undef DECLARE_LAYOUT
# undef DECLARE_WIDGET
# undef DECLARE_WIDGET_1
if ( w )
break ;
// try with a registered custom widget
2011-05-04 14:19:35 +00:00
QDesignerCustomWidgetInterface * factory = d - > m_customWidgets . value ( widgetName ) ;
2011-04-27 10:05:43 +00:00
if ( factory ! = 0 )
w = factory - > createWidget ( parentWidget ) ;
} while ( false ) ;
if ( w = = 0 ) { // Attempt to instantiate base class of promoted/custom widgets
2011-05-04 14:19:35 +00:00
const QString baseClassName = d - > customWidgetBaseClass ( widgetName ) ;
2011-04-27 10:05:43 +00:00
if ( ! baseClassName . isEmpty ( ) ) {
qWarning ( ) < < QCoreApplication : : translate ( " QFormBuilder " , " QFormBuilder was unable to create a custom widget of the class '%1'; defaulting to base class '%2'. " ) . arg ( widgetName , baseClassName ) ;
return createWidget ( baseClassName , parentWidget , name ) ;
}
}
if ( w = = 0 ) { // nothing to do
qWarning ( ) < < QCoreApplication : : translate ( " QFormBuilder " , " QFormBuilder was unable to create a widget of the class '%1'. " ) . arg ( widgetName ) ;
return 0 ;
}
w - > setObjectName ( name ) ;
if ( qobject_cast < QDialog * > ( w ) )
w - > setParent ( parentWidget ) ;
return w ;
}
/*!
\ internal
*/
QLayout * QFormBuilder : : createLayout ( const QString & layoutName , QObject * parent , const QString & name )
{
QLayout * l = 0 ;
QWidget * parentWidget = qobject_cast < QWidget * > ( parent ) ;
QLayout * parentLayout = qobject_cast < QLayout * > ( parent ) ;
Q_ASSERT ( parentWidget | | parentLayout ) ;
# define DECLARE_WIDGET(W, C)
# define DECLARE_COMPAT_WIDGET(W, C)
# define DECLARE_LAYOUT(L, C) \
if ( layoutName = = QLatin1String ( # L ) ) { \
Q_ASSERT ( l = = 0 ) ; \
l = parentLayout \
? new L ( ) \
: new L ( parentWidget ) ; \
}
# include "widgets.table"
# undef DECLARE_LAYOUT
# undef DECLARE_COMPAT_WIDGET
# undef DECLARE_WIDGET
if ( l ) {
l - > setObjectName ( name ) ;
} else {
qWarning ( ) < < QCoreApplication : : translate ( " QFormBuilder " , " The layout type `%1' is not supported. " ) . arg ( layoutName ) ;
}
return l ;
}
/*!
\ internal
*/
bool QFormBuilder : : addItem ( DomLayoutItem * ui_item , QLayoutItem * item , QLayout * layout )
{
return QAbstractFormBuilder : : addItem ( ui_item , item , layout ) ;
}
/*!
\ internal
*/
bool QFormBuilder : : addItem ( DomWidget * ui_widget , QWidget * widget , QWidget * parentWidget )
{
return QAbstractFormBuilder : : addItem ( ui_widget , widget , parentWidget ) ;
}
/*!
\ internal
*/
QWidget * QFormBuilder : : widgetByName ( QWidget * topLevel , const QString & name )
{
Q_ASSERT ( topLevel ) ;
if ( topLevel - > objectName ( ) = = name )
return topLevel ;
return topLevel - > findChild < QWidget * > ( name ) ;
}
static QObject * objectByName ( QWidget * topLevel , const QString & name )
{
Q_ASSERT ( topLevel ) ;
if ( topLevel - > objectName ( ) = = name )
return topLevel ;
return topLevel - > findChild < QObject * > ( name ) ;
}
/*!
\ internal
*/
void QFormBuilder : : createConnections ( DomConnections * ui_connections , QWidget * widget )
{
typedef QList < DomConnection * > DomConnectionList ;
Q_ASSERT ( widget ! = 0 ) ;
if ( ui_connections = = 0 )
return ;
const DomConnectionList connections = ui_connections - > elementConnection ( ) ;
if ( ! connections . empty ( ) ) {
const DomConnectionList : : const_iterator cend = connections . constEnd ( ) ;
for ( DomConnectionList : : const_iterator it = connections . constBegin ( ) ; it ! = cend ; + + it ) {
QObject * sender = objectByName ( widget , ( * it ) - > elementSender ( ) ) ;
QObject * receiver = objectByName ( widget , ( * it ) - > elementReceiver ( ) ) ;
if ( ! sender | | ! receiver )
continue ;
QByteArray sig = ( * it ) - > elementSignal ( ) . toUtf8 ( ) ;
sig . prepend ( " 2 " ) ;
QByteArray sl = ( * it ) - > elementSlot ( ) . toUtf8 ( ) ;
sl . prepend ( " 1 " ) ;
QObject : : connect ( sender , sig , receiver , sl ) ;
}
}
}
/*!
\ internal
*/
QWidget * QFormBuilder : : create ( DomUI * ui , QWidget * parentWidget )
{
return QAbstractFormBuilder : : create ( ui , parentWidget ) ;
}
/*!
\ internal
*/
QLayout * QFormBuilder : : create ( DomLayout * ui_layout , QLayout * layout , QWidget * parentWidget )
{
// Is this a temporary layout widget used to represent QLayout hierarchies in Designer?
// Set its margins to 0.
2011-05-04 14:19:35 +00:00
bool layoutWidget = d - > processingLayoutWidget ( ) ;
2011-04-27 10:05:43 +00:00
QLayout * l = QAbstractFormBuilder : : create ( ui_layout , layout , parentWidget ) ;
if ( layoutWidget ) {
const QFormBuilderStrings & strings = QFormBuilderStrings : : instance ( ) ;
int left , top , right , bottom ;
left = top = right = bottom = 0 ;
const DomPropertyHash properties = propertyMap ( ui_layout - > elementProperty ( ) ) ;
if ( DomProperty * prop = properties . value ( strings . leftMarginProperty ) )
left = prop - > elementNumber ( ) ;
if ( DomProperty * prop = properties . value ( strings . topMarginProperty ) )
top = prop - > elementNumber ( ) ;
if ( DomProperty * prop = properties . value ( strings . rightMarginProperty ) )
right = prop - > elementNumber ( ) ;
if ( DomProperty * prop = properties . value ( strings . bottomMarginProperty ) )
bottom = prop - > elementNumber ( ) ;
l - > setContentsMargins ( left , top , right , bottom ) ;
2011-05-04 14:19:35 +00:00
d - > setProcessingLayoutWidget ( false ) ;
2011-04-27 10:05:43 +00:00
}
return l ;
}
/*!
\ internal
*/
QLayoutItem * QFormBuilder : : create ( DomLayoutItem * ui_layoutItem , QLayout * layout , QWidget * parentWidget )
{
return QAbstractFormBuilder : : create ( ui_layoutItem , layout , parentWidget ) ;
}
/*!
\ internal
*/
QAction * QFormBuilder : : create ( DomAction * ui_action , QObject * parent )
{
return QAbstractFormBuilder : : create ( ui_action , parent ) ;
}
/*!
\ internal
*/
QActionGroup * QFormBuilder : : create ( DomActionGroup * ui_action_group , QObject * parent )
{
return QAbstractFormBuilder : : create ( ui_action_group , parent ) ;
}
/*!
Returns the list of paths the form builder searches for plugins .
\ sa addPluginPath ( )
*/
QStringList QFormBuilder : : pluginPaths ( ) const
{
2011-05-04 14:19:35 +00:00
return d - > m_pluginPaths ;
2011-04-27 10:05:43 +00:00
}
/*!
Clears the list of paths that the form builder uses to search for
custom widget plugins .
\ sa pluginPaths ( )
*/
void QFormBuilder : : clearPluginPaths ( )
{
2011-05-04 14:19:35 +00:00
d - > m_pluginPaths . clear ( ) ;
2011-04-27 10:05:43 +00:00
updateCustomWidgets ( ) ;
}
/*!
Adds a new plugin path specified by \ a pluginPath to the list of
paths that will be searched by the form builder when loading a
custom widget plugin .
\ sa setPluginPath ( ) , clearPluginPaths ( )
*/
void QFormBuilder : : addPluginPath ( const QString & pluginPath )
{
2011-05-04 14:19:35 +00:00
d - > m_pluginPaths . append ( pluginPath ) ;
2011-04-27 10:05:43 +00:00
updateCustomWidgets ( ) ;
}
/*!
Sets the list of plugin paths to the list specified by \ a pluginPaths .
\ sa addPluginPath ( )
*/
void QFormBuilder : : setPluginPath ( const QStringList & pluginPaths )
{
2011-05-04 14:19:35 +00:00
d - > m_pluginPaths = pluginPaths ;
2011-04-27 10:05:43 +00:00
updateCustomWidgets ( ) ;
}
static void insertPlugins ( QObject * o , QMap < QString , QDesignerCustomWidgetInterface * > * customWidgets )
{
// step 1) try with a normal plugin
if ( QDesignerCustomWidgetInterface * iface = qobject_cast < QDesignerCustomWidgetInterface * > ( o ) ) {
customWidgets - > insert ( iface - > name ( ) , iface ) ;
return ;
}
// step 2) try with a collection of plugins
if ( QDesignerCustomWidgetCollectionInterface * c = qobject_cast < QDesignerCustomWidgetCollectionInterface * > ( o ) ) {
foreach ( QDesignerCustomWidgetInterface * iface , c - > customWidgets ( ) )
customWidgets - > insert ( iface - > name ( ) , iface ) ;
}
}
/*!
\ internal
*/
void QFormBuilder : : updateCustomWidgets ( )
{
2011-05-04 14:19:35 +00:00
d - > m_customWidgets . clear ( ) ;
2011-04-27 10:05:43 +00:00
2011-05-04 14:19:35 +00:00
foreach ( const QString & path , d - > m_pluginPaths ) {
2011-04-27 10:05:43 +00:00
const QDir dir ( path ) ;
const QStringList candidates = dir . entryList ( QDir : : Files ) ;
foreach ( const QString & plugin , candidates ) {
if ( ! QLibrary : : isLibrary ( plugin ) )
continue ;
QString loaderPath = path ;
loaderPath + = QLatin1Char ( ' / ' ) ;
loaderPath + = plugin ;
QPluginLoader loader ( loaderPath ) ;
if ( loader . load ( ) )
2011-05-04 14:19:35 +00:00
insertPlugins ( loader . instance ( ) , & d - > m_customWidgets ) ;
2011-04-27 10:05:43 +00:00
}
}
// Check statically linked plugins
const QObjectList staticPlugins = QPluginLoader : : staticInstances ( ) ;
if ( ! staticPlugins . empty ( ) )
foreach ( QObject * o , staticPlugins )
2011-05-04 14:19:35 +00:00
insertPlugins ( o , & d - > m_customWidgets ) ;
2011-04-27 10:05:43 +00:00
}
/*!
\ fn QList < QDesignerCustomWidgetInterface * > QFormBuilder : : customWidgets ( ) const
Returns a list of the available plugins .
*/
QList < QDesignerCustomWidgetInterface * > QFormBuilder : : customWidgets ( ) const
{
2011-05-04 14:19:35 +00:00
return d - > m_customWidgets . values ( ) ;
2011-04-27 10:05:43 +00:00
}
/*!
\ internal
*/
void QFormBuilder : : applyProperties ( QObject * o , const QList < DomProperty * > & properties )
{
typedef QList < DomProperty * > DomPropertyList ;
if ( properties . empty ( ) )
return ;
const QFormBuilderStrings & strings = QFormBuilderStrings : : instance ( ) ;
const DomPropertyList : : const_iterator cend = properties . constEnd ( ) ;
for ( DomPropertyList : : const_iterator it = properties . constBegin ( ) ; it ! = cend ; + + it ) {
const QVariant v = toVariant ( o - > metaObject ( ) , * it ) ;
if ( v . isNull ( ) )
continue ;
const QString attributeName = ( * it ) - > attributeName ( ) ;
const bool isWidget = o - > isWidgetType ( ) ;
2011-05-04 14:19:35 +00:00
if ( isWidget & & o - > parent ( ) = = d - > parentWidget ( ) & & attributeName = = strings . geometryProperty ) {
2011-04-27 10:05:43 +00:00
// apply only the size part of a geometry for the root widget
static_cast < QWidget * > ( o ) - > resize ( qvariant_cast < QRect > ( v ) . size ( ) ) ;
2011-05-04 14:19:35 +00:00
} else if ( d - > applyPropertyInternally ( o , attributeName , v ) ) {
2011-04-27 10:05:43 +00:00
} else if ( isWidget & & ! qstrcmp ( " QFrame " , o - > metaObject ( ) - > className ( ) ) & & attributeName = = strings . orientationProperty ) {
// ### special-casing for Line (QFrame) -- try to fix me
o - > setProperty ( " frameShape " , v ) ; // v is of QFrame::Shape enum
} else {
o - > setProperty ( attributeName . toUtf8 ( ) , v ) ;
}
}
}
# ifdef QFORMINTERNAL_NAMESPACE
} // namespace QFormInternal
# endif
QT_END_NAMESPACE