diff options
Diffstat (limited to 'tools/designer/uilib')
-rw-r--r-- | tools/designer/uilib/qwidgetfactory.cpp | 2623 | ||||
-rw-r--r-- | tools/designer/uilib/qwidgetfactory.h | 187 | ||||
-rw-r--r-- | tools/designer/uilib/test/main.cpp | 50 | ||||
-rw-r--r-- | tools/designer/uilib/test/test.pro | 7 | ||||
-rw-r--r-- | tools/designer/uilib/uilib.pro | 30 |
5 files changed, 2897 insertions, 0 deletions
diff --git a/tools/designer/uilib/qwidgetfactory.cpp b/tools/designer/uilib/qwidgetfactory.cpp new file mode 100644 index 0000000..a1ff1c2 --- /dev/null +++ b/tools/designer/uilib/qwidgetfactory.cpp @@ -0,0 +1,2623 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt Designer. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with +** the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qwidgetfactory.h" + +#include "../interfaces/languageinterface.h" +#include "../interfaces/widgetinterface.h" + +#include <qfeatures.h> +#include "../designer/database2.h" +#include <qdom.h> +#include <qdir.h> +#include <qlayout.h> +#include <qmetaobject.h> +#include <domtool.h> +#include <uib.h> +#include <qapplication.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <qobjectlist.h> +#include <private/qpluginmanager_p.h> +#include <qmime.h> +#include <qdragobject.h> + +#ifndef QT_NO_SQL +#include <qsqlrecord.h> +#include <qsqldatabase.h> +#include <qdatatable.h> +#endif + +// include all Qt widgets we support +#include <qpushbutton.h> +#include <qtoolbutton.h> +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <qgroupbox.h> +#include <qbuttongroup.h> +#include <qiconview.h> +#include <qheader.h> +#ifndef QT_NO_TABLE +#include <qtable.h> +#endif +#include <qlistbox.h> +#include <qlistview.h> +#include <qlineedit.h> +#include <qspinbox.h> +#include <qmultilineedit.h> +#include <qlabel.h> +#include <qwidget.h> +#include <qtabwidget.h> +#include <qcombobox.h> +#include <qdialog.h> +#include <qwizard.h> +#include <qlcdnumber.h> +#include <qprogressbar.h> +#include <qtextview.h> +#include <qtextbrowser.h> +#include <qdial.h> +#include <qslider.h> +#include <qframe.h> +#include <qwidgetstack.h> +#include <qtoolbox.h> +#include <qtextedit.h> +#include <qscrollbar.h> +#include <qmainwindow.h> +#include <qsplitter.h> +#include <qaction.h> +#include <qpopupmenu.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qdatetimeedit.h> +#include <qvbox.h> +#include <qhbox.h> +#include <qgrid.h> + +#include <stdlib.h> + +class QWidgetFactoryPrivate +{ +public: + QCString translationContext; + QListViewItem *lastItem; + QDict<bool> customWidgets; +}; + +static QPtrList<QWidgetFactory> widgetFactories; +static QPluginManager<LanguageInterface> *languageInterfaceManager = 0; +static QPluginManager<WidgetInterface> *widgetInterfaceManager = 0; + +static QMap<QString, bool> *availableWidgetMap = 0; +static QStringList *availableWidgetList = 0; + +QMap<QWidget*, QString> *qwf_forms = 0; +QString *qwf_language = 0; +bool qwf_execute_code = TRUE; +bool qwf_stays_on_top = FALSE; +QString qwf_currFileName = ""; +QObject *qwf_form_object = 0; +QString *qwf_plugin_dir = 0; + +static void setupPluginDir() +{ + if ( !qwf_plugin_dir ) + qwf_plugin_dir = new QString( "/designer" ); +} + +static void setupWidgetListAndMap() +{ + if ( availableWidgetMap ) + return; + setupPluginDir(); + availableWidgetList = new QStringList; + (*availableWidgetList) << "QPushButton" << "QToolButton" << "QCheckBox" << "QRadioButton" + << "QGroupBox" << "QButtonGroup" << "QIconView" << "QTable" + << "QListBox" << "QListView" << "QLineEdit" << "QSpinBox" + << "QMultiLineEdit" << "QLabel" << "TextLabel" << "PixmapLabel" + << "QLayoutWidget" << "QTabWidget" << "QComboBox" + << "QWidget" << "QDialog" << "QWizard" << "QLCDNumber"; + // put less stress on the compiler by limiting the template nesting depth + (*availableWidgetList) << "QProgressBar" << "QTextView" << "QTextBrowser" + << "QDial" << "QSlider" << "QFrame" << "Line" << "QTextEdit" + << "QDateEdit" << "QTimeEdit" << "QDateTimeEdit" << "QScrollBar" + << "QPopupMenu" << "QWidgetStack" << "QMainWindow" + << "QDataTable" << "QDataBrowser" << "QDataView" + << "QVBox" << "QHBox" << "QGrid" << "QToolBox" << "QSplitter"; + + if ( !widgetInterfaceManager ) + widgetInterfaceManager = + new QPluginManager<WidgetInterface>( IID_Widget, QApplication::libraryPaths(), *qwf_plugin_dir ); + + QStringList l = widgetInterfaceManager->featureList(); + QStringList::Iterator it; + for ( it = l.begin(); it != l.end(); ++it ) + (*availableWidgetList) << *it; + + availableWidgetMap = new QMap<QString, bool>; + for ( it = availableWidgetList->begin(); it != availableWidgetList->end(); ++it ) + availableWidgetMap->insert( *it, TRUE ); +} + +static QImage loadImageData( const QString& format, ulong len, QByteArray data ) +{ + QImage img; + if ( format == "XPM.GZ" || format == "XBM.GZ" ) { + if ( len < data.size() * 10 ) + len = data.size() * 10; + // qUncompress() expects the first 4 bytes to be the expected length of + // the uncompressed data + QByteArray dataTmp( data.size() + 4 ); + memcpy( dataTmp.data()+4, data.data(), data.size() ); + dataTmp[0] = ( len & 0xff000000 ) >> 24; + dataTmp[1] = ( len & 0x00ff0000 ) >> 16; + dataTmp[2] = ( len & 0x0000ff00 ) >> 8; + dataTmp[3] = ( len & 0x000000ff ); + QByteArray baunzip = qUncompress( dataTmp ); + len = baunzip.size(); + img.loadFromData( (const uchar*)baunzip.data(), len, format.left(format.find('.')) ); + } else { + img.loadFromData( (const uchar*)data.data(), data.size(), format ); + } + return img; +} + +static QSizePolicy::SizeType stringToSizeType( const QString& str ) +{ + if ( str == "Fixed" ) { + return QSizePolicy::Fixed; + } else if ( str == "Minimum" ) { + return QSizePolicy::Minimum; + } else if ( str == "Maximum" ) { + return QSizePolicy::Maximum; + } else if ( str == "Preferred" ) { + return QSizePolicy::Preferred; + } else if ( str == "MinimumExpanding" ) { + return QSizePolicy::MinimumExpanding; + } else if ( str == "Expanding" ) { + return QSizePolicy::Expanding; + } else { + return QSizePolicy::Ignored; + } +} + + +/*! + \class QWidgetFactory + + \brief The QWidgetFactory class provides for the dynamic creation of widgets + from Qt Designer .ui files. + + This class basically offers two things: + + \list + + \i Dynamically creating widgets from \link designer-manual.book Qt + Designer\endlink user interface description files. + You can do this using the static function QWidgetFactory::create(). + This function also performs signal and slot connections, tab + ordering, etc., as defined in the .ui file, and returns the + top-level widget in the .ui file. After creating the widget you can + use QObject::child() and QObject::queryList() to access child + widgets of this returned widget. + + \i Adding additional widget factories to be able to create custom + widgets. See createWidget() for details. + + \endlist + + This class is not included in the Qt library itself. To use it you + must link against \c libqui.so (Unix) or \c qui.lib (Windows), which is + built into \c INSTALL/lib if you built \e{Qt Designer} (\c INSTALL is + the directory where Qt is installed ). + + If you create a QMainWindow using a QWidgetFactory, be aware that + it already has a central widget. Therefore, you need to delete this + one before setting another one. + + See the "Creating Dynamic Dialogs from .ui Files" section of the \link + designer-manual.book Qt Designer manual\endlink for an example. See + also the \l{QWidgetPlugin} class and the \link plugins-howto.html + Plugins documentation\endlink. +*/ + +/*! Constructs a QWidgetFactory. */ + +QWidgetFactory::QWidgetFactory() + : d( new QWidgetFactoryPrivate() ), dbControls( 0 ), + usePixmapCollection( FALSE ), defMargin( 11 ), defSpacing( 6 ) +{ + widgetFactories.setAutoDelete( TRUE ); + d->customWidgets.setAutoDelete( TRUE ); +} + +/*! \fn QWidgetFactory::~QWidgetFactory() + Destructor. +*/ +QWidgetFactory::~QWidgetFactory() +{ + delete d; +} + +/*! + + Loads the \e{Qt Designer} user interface description file \a uiFile + and returns the top-level widget in that description. \a parent and + \a name are passed to the constructor of the top-level widget. + + This function also performs signal and slot connections, tab + ordering, etc., as described in the .ui file. In \e{Qt Designer} it + is possible to add custom slots to a form and connect to them. If + you want these connections to be made, you must create a class + derived from QObject, which implements all these slots. Then pass an + instance of the object as \a connector to this function. If you do + this, the connections to the custom slots will be done using the \a + connector as slot. + + If something fails, 0 is returned. + + The ownership of the returned widget is passed to the caller. +*/ + +QWidget *QWidgetFactory::create( const QString &uiFile, QObject *connector, + QWidget *parent, const char *name ) +{ + setupPluginDir(); + QFile f( uiFile ); + bool failed = FALSE; + if ( !f.open( IO_ReadOnly ) ) + failed = TRUE; + if ( failed && qApp->type() == QApplication::Tty ) { + // for QSA: If we have no GUI, we have no form definition + // files, but just the code. So try if only the code exists. + f.setName( uiFile + ".qs" ); + failed = !f.open( IO_ReadOnly ); + } + if ( failed ) + return 0; + + qwf_currFileName = uiFile; + QWidget *w = QWidgetFactory::create( &f, connector, parent, name ); + if ( !qwf_forms ) + qwf_forms = new QMap<QWidget*, QString>; + qwf_forms->insert( w, uiFile ); + return w; +} + +#undef slots + +/*! \overload + Loads the user interface description from device \a dev. + */ + +QWidget *QWidgetFactory::create( QIODevice *dev, QObject *connector, QWidget *parent, const char *name ) +{ + setupPluginDir(); + QWidget *w = 0; + QDomDocument doc; + QString errMsg; + int errLine; + + QWidgetFactory *widgetFactory = new QWidgetFactory; + widgetFactory->toplevel = 0; + + // If we have no GUI, we only want to load the code + if ( qApp->type() != QApplication::Tty ) { + QIODevice::Offset start = dev->at(); + Q_UINT32 magic; + QDataStream in( dev ); + in >> magic; + if ( magic == UibMagic ) { + w = widgetFactory->createFromUibFile( in, connector, parent, name ); + } else { + in.unsetDevice(); + dev->at( start ); + if ( doc.setContent( dev, &errMsg, &errLine ) ) { + w = widgetFactory->createFromUiFile( doc, connector, parent, name ); + } else { + // qDebug( QString("Parse error: ") + errMsg + QString(" in line %d"), errLine ); + } + } + if ( !w ) { + delete widgetFactory; + return 0; + } + } + + if ( !languageInterfaceManager ) + languageInterfaceManager = + new QPluginManager<LanguageInterface>( IID_Language, QApplication::libraryPaths(), *qwf_plugin_dir ); + widgetFactory->loadExtraSource(); + + if ( widgetFactory->toplevel ) { +#ifndef QT_NO_SQL + QMap<QWidget*, SqlWidgetConnection>::Iterator cit = widgetFactory->sqlWidgetConnections.begin(); + for( ; cit != widgetFactory->sqlWidgetConnections.end(); ++cit ) { + if ( widgetFactory->noDatabaseWidgets.find( cit.key()->name() ) != + widgetFactory->noDatabaseWidgets.end() ) + continue; + if ( cit.key()->inherits( "QDesignerDataBrowser2" ) ) + ( (QDesignerDataBrowser2*)cit.key() )->initPreview( (*cit).conn, (*cit).table, + cit.key(), *(*cit).dbControls ); + else if ( cit.key()->inherits( "QDesignerDataView2" ) ) + ( (QDesignerDataView2*)cit.key() )->initPreview( (*cit).conn, (*cit).table, + cit.key(), *(*cit).dbControls ); + } + + for ( QMap<QString, QStringList>::Iterator it = widgetFactory->dbTables.begin(); + it != widgetFactory->dbTables.end(); ++it ) { + QDataTable *table = (QDataTable*)widgetFactory->toplevel->child( it.key(), "QDataTable" ); + if ( !table ) + continue; + if ( widgetFactory->noDatabaseWidgets.find( table->name() ) != + widgetFactory->noDatabaseWidgets.end() ) + continue; + QValueList<Field> fieldMap = *widgetFactory->fieldMaps.find( table ); + QString conn = (*it)[ 0 ]; + QSqlCursor* c = 0; + QSqlDatabase *db = 0; + if ( conn.isEmpty() || conn == "(default)" ) { + db = QSqlDatabase::database(); + c = new QSqlCursor( (*it)[ 1 ] ); + } else { + db = QSqlDatabase::database( conn ); + c = new QSqlCursor( (*it)[ 1 ], TRUE, db ); + } + if ( db ) { + table->setSqlCursor( c, fieldMap.isEmpty(), TRUE ); + table->refresh( QDataTable::RefreshAll ); + } + } +#endif + } + + for ( QMap<QString, QString>::Iterator it = widgetFactory->buddies.begin(); + it != widgetFactory->buddies.end(); ++it ) { + QLabel *label = (QLabel*)widgetFactory->toplevel->child( it.key(), "QLabel" ); + QWidget *buddy = (QWidget*)widgetFactory->toplevel->child( *it, "QWidget" ); + if ( label && buddy ) + label->setBuddy( buddy ); + } + + delete widgetFactory; + + QApplication::sendPostedEvents(); + + return w; +} + +QWidget *QWidgetFactory::createFromUiFile( QDomDocument doc, QObject *connector, + QWidget *parent, const char *name ) +{ + DomTool::fixDocument( doc ); + + uiFileVersion = doc.firstChild().toElement().attribute("version"); + QDomElement e = doc.firstChild().toElement().firstChild().toElement(); + + QDomElement variables = e; + while ( variables.tagName() != "variables" && !variables.isNull() ) + variables = variables.nextSibling().toElement(); + + QDomElement slots = e; + while ( slots.tagName() != "slots" && !slots.isNull() ) + slots = slots.nextSibling().toElement(); + + QDomElement connections = e; + while ( connections.tagName() != "connections" && !connections.isNull() ) + connections = connections.nextSibling().toElement(); + + QDomElement imageCollection = e; + while ( imageCollection.tagName() != "images" && !imageCollection.isNull() ) + imageCollection = imageCollection.nextSibling().toElement(); + + QDomElement tabOrder = e; + while ( tabOrder.tagName() != "tabstops" && !tabOrder.isNull() ) + tabOrder = tabOrder.nextSibling().toElement(); + + QDomElement actions = e; + while ( actions.tagName() != "actions" && !actions.isNull() ) + actions = actions.nextSibling().toElement(); + + QDomElement toolbars = e; + while ( toolbars.tagName() != "toolbars" && !toolbars.isNull() ) + toolbars = toolbars.nextSibling().toElement(); + + QDomElement menubar = e; + while ( menubar.tagName() != "menubar" && !menubar.isNull() ) + menubar = menubar.nextSibling().toElement(); + + QDomElement functions = e; + while ( functions.tagName() != "functions" && !functions.isNull() ) + functions = functions.nextSibling().toElement(); + + QDomElement widget; + while ( !e.isNull() ) { + if ( e.tagName() == "class" ) { + d->translationContext = e.firstChild().toText().data(); + } else if ( e.tagName() == "widget" ) { + widget = e; + } else if ( e.tagName() == "pixmapinproject" ) { + usePixmapCollection = TRUE; + } else if ( e.tagName() == "layoutdefaults" ) { + defSpacing = e.attribute( "spacing", QString::number( defSpacing ) ).toInt(); + defMargin = e.attribute( "margin", QString::number( defMargin ) ).toInt(); + } + e = e.nextSibling().toElement(); + } + + if ( !imageCollection.isNull() ) + loadImageCollection( imageCollection ); + + createWidgetInternal( widget, parent, 0, widget.attribute("class", "QWidget") ); + QWidget *w = toplevel; + if ( !w ) + return 0; + + if ( !actions.isNull() ) + loadActions( actions ); + if ( !toolbars.isNull() ) + loadToolBars( toolbars ); + if ( !menubar.isNull() ) + loadMenuBar( menubar ); + + if ( !connections.isNull() ) + loadConnections( connections, connector ); + if ( w && name && qstrlen( name ) > 0 ) + w->setName( name ); + + if ( !tabOrder.isNull() ) + loadTabOrder( tabOrder ); + +#if 0 + if ( !functions.isNull() ) // compatibiliy with early 3.0 betas + loadFunctions( functions ); +#endif + + return w; +} + +void QWidgetFactory::unpackUInt16( QDataStream& in, Q_UINT16& n ) +{ + Q_UINT8 half; + in >> half; + if ( half == 255 ) { + in >> n; + } else { + n = half; + } +} + +void QWidgetFactory::unpackUInt32( QDataStream& in, Q_UINT32& n ) +{ + Q_UINT16 half; + in >> half; + if ( half == 65535 ) { + in >> n; + } else { + n = half; + } +} + +void QWidgetFactory::unpackByteArray( QDataStream& in, QByteArray& array ) +{ + Q_UINT32 size; + unpackUInt32( in, size ); + array.resize( size ); + in.readRawBytes( array.data(), size ); +} + +void QWidgetFactory::unpackCString( const UibStrTable& strings, QDataStream& in, + QCString& cstr ) +{ + Q_UINT32 n; + unpackUInt32( in, n ); + cstr = strings.asCString( n ); +} + +void QWidgetFactory::unpackString( const UibStrTable& strings, QDataStream& in, + QString& str ) +{ + Q_UINT32 n; + unpackUInt32( in, n ); + str = strings.asString( n ); +} + +void QWidgetFactory::unpackStringSplit( const UibStrTable& strings, + QDataStream& in, QString& str ) +{ + QString remainder; + unpackString( strings, in, str ); + unpackString( strings, in, remainder ); + str += remainder; +} + +void QWidgetFactory::unpackVariant( const UibStrTable& strings, QDataStream& in, + QVariant& value ) +{ + QString imageName; + Q_UINT32 number; + Q_UINT16 count; + Q_UINT16 x; + Q_UINT16 y; + Q_UINT16 width; + Q_UINT16 height; + Q_UINT8 bit; + Q_UINT8 type; + + in >> type; + + switch ( type ) { + case QVariant::String: + unpackString( strings, in, value.asString() ); + break; + case QVariant::Pixmap: + unpackString( strings, in, imageName ); + if ( imageName.isEmpty() ) { + value.asPixmap() = QPixmap(); + } else { + value.asPixmap() = loadPixmap( imageName ); + } + break; + case QVariant::Image: + unpackString( strings, in, imageName ); + if ( imageName.isEmpty() ) { + value.asImage() = QImage(); + } else { + value.asImage() = loadFromCollection( imageName ); + } + break; + case QVariant::IconSet: + unpackString( strings, in, imageName ); + if ( imageName.isEmpty() ) { + value.asIconSet() = QIconSet(); + } else { + value.asIconSet() = QIconSet( loadPixmap(imageName) ); + } + break; + case QVariant::StringList: + unpackUInt16( in, count ); + while ( count-- ) { + QString str; + unpackString( strings, in, str ); + value.asStringList().append( str ); + } + break; + case QVariant::Rect: + unpackUInt16( in, x ); + unpackUInt16( in, y ); + unpackUInt16( in, width ); + unpackUInt16( in, height ); + value = QRect( x, y, width, height ); + break; + case QVariant::Size: + unpackUInt16( in, width ); + unpackUInt16( in, height ); + value = QSize( width, height ); + break; + case QVariant::Color: + in >> value.asColor(); + break; + case QVariant::Point: + unpackUInt16( in, x ); + unpackUInt16( in, y ); + value = QPoint( x, y ); + break; + case QVariant::Int: + unpackUInt32( in, number ); + value = (int) number; + break; + case QVariant::Bool: + in >> bit; + value = QVariant( bit != 0, 0 ); + break; + case QVariant::Double: + in >> value.asDouble(); + break; + case QVariant::CString: + unpackCString( strings, in, value.asCString() ); + break; + case QVariant::Cursor: + in >> value.asCursor(); + break; + case QVariant::Date: + in >> value.asDate(); + break; + case QVariant::Time: + in >> value.asTime(); + break; + case QVariant::DateTime: + in >> value.asDateTime(); + break; + default: + in >> value; + } +} + +void QWidgetFactory::inputSpacer( const UibStrTable& strings, QDataStream& in, + QLayout *parent ) +{ + QCString name; + QVariant value; + QCString comment; + QSizePolicy::SizeType sizeType = QSizePolicy::Preferred; + bool vertical = FALSE; + int w = 0; + int h = 0; + Q_UINT16 column = 0; + Q_UINT16 row = 0; + Q_UINT16 colspan = 1; + Q_UINT16 rowspan = 1; + Q_UINT8 objectTag; + + in >> objectTag; + while ( !in.atEnd() && objectTag != Object_End ) { + switch ( objectTag ) { + case Object_GridCell: + unpackUInt16( in, column ); + unpackUInt16( in, row ); + unpackUInt16( in, colspan ); + unpackUInt16( in, rowspan ); + break; + case Object_VariantProperty: + unpackCString( strings, in, name ); + unpackVariant( strings, in, value ); + + if ( name == "orientation" ) { + vertical = ( value == "Vertical" ); + } else if ( name == "sizeHint" ) { + w = value.toSize().width(); + h = value.toSize().height(); + } else if ( name == "sizeType" ) { + sizeType = stringToSizeType( value.toString() ); + } + break; + default: + qFatal( "Corrupt" ); + } + in >> objectTag; + } + + if ( parent != 0 ) { + QSpacerItem *spacer; + if ( vertical ) { + spacer = new QSpacerItem( w, h, QSizePolicy::Minimum, sizeType ); + } else { + spacer = new QSpacerItem( w, h, sizeType, QSizePolicy::Minimum ); + } + + if ( parent->inherits("QGridLayout") ) { + ((QGridLayout *) parent)->addMultiCell( spacer, row, + row + rowspan - 1, column, column + colspan - 1, + vertical ? Qt::AlignHCenter : Qt::AlignVCenter ); + } else { + parent->addItem( spacer ); + } + } +} + +void QWidgetFactory::inputColumnOrRow( const UibStrTable& strings, + QDataStream& in, QObject *parent, + bool isRow ) +{ + QString text; + QPixmap pixmap; + QString field; + bool clickable = TRUE; + bool resizable = TRUE; + + QCString name; + QVariant value; + QCString comment; + QString str; + Q_UINT8 objectTag; + + in >> objectTag; + while ( !in.atEnd() && objectTag != Object_End ) { + switch ( objectTag ) { + case Object_TextProperty: + unpackCString( strings, in, name ); + unpackCString( strings, in, value.asCString() ); + unpackCString( strings, in, comment ); + str = translate( value.asCString().data(), comment.data() ); + + if ( name == "field" ) { + field = str; + } else if ( name == "text" ) { + text = str; + } + break; + case Object_VariantProperty: + unpackCString( strings, in, name ); + unpackVariant( strings, in, value ); + + if ( name == "clickable" ) { + clickable = value.toBool(); + } else if ( name == "pixmap" ) { + pixmap = value.asPixmap(); + } else if ( name == "resizable" ) { + resizable = value.toBool(); + } + break; + default: + qFatal( "Corrupt" ); + } + in >> objectTag; + } + + if ( parent != 0 ) { + if ( parent->inherits("QListView") ) { + createListViewColumn( (QListView *) parent, text, pixmap, clickable, + resizable ); +#ifndef QT_NO_TABLE + } else if ( parent->inherits("QTable") ) { + createTableColumnOrRow( (QTable *) parent, text, pixmap, field, + isRow ); +#endif + } + } +} + +void QWidgetFactory::inputItem( const UibStrTable& strings, QDataStream& in, + QObject *parent, QListViewItem *parentItem ) +{ + QStringList texts; + QValueList<QPixmap> pixmaps; + QCString name; + QVariant value; + QCString comment; + Q_UINT8 objectTag; + + QListView *listView = 0; + if ( parent != 0 && parent->inherits("QListView") ) + parent = (QListView *) parent; + QListViewItem *item = 0; + if ( listView != 0 ) { + if ( parentItem == 0 ) { + item = new QListViewItem( listView, d->lastItem ); + } else { + item = new QListViewItem( parentItem, d->lastItem ); + } + d->lastItem = item; + } + + in >> objectTag; + while ( !in.atEnd() && objectTag != Object_End ) { + switch ( objectTag ) { + case Object_Item: + if ( listView != 0 ) + d->lastItem->setOpen( TRUE ); + inputItem( strings, in, parent, item ); + break; + case Object_TextProperty: + unpackCString( strings, in, name ); + unpackCString( strings, in, value.asCString() ); + unpackCString( strings, in, comment ); + + if ( name == "text" ) + texts << translate( value.asCString().data(), comment.data() ); + break; + case Object_VariantProperty: + unpackCString( strings, in, name ); + unpackVariant( strings, in, value ); + + if ( name == "pixmap" ) + pixmaps << value.asPixmap(); + break; + default: + qFatal( "Corrupt" ); + } + in >> objectTag; + } + + if ( listView != 0 ) { + int i = 0; + QStringList::ConstIterator t = texts.begin(); + while ( t != texts.end() ) { + item->setText( i, *t ); + ++i; + ++t; + } + + int j = 0; + QValueList<QPixmap>::ConstIterator p = pixmaps.begin(); + while ( p != pixmaps.end() ) { + item->setPixmap( j, *p ); + ++j; + ++p; + } + } else { + QString text = texts.last(); + QPixmap pixmap = pixmaps.last(); + + if ( parent != 0 ) { + if ( parent->inherits("QComboBox") || + parent->inherits("QListBox") ) { + QListBox *listBox = (QListBox *) parent->qt_cast( "QListBox" ); + if ( listBox == 0 ) + listBox = ((QComboBox *) parent)->listBox(); + + if ( pixmap.isNull() ) { + (void) new QListBoxText( listBox, text ); + } else { + (void) new QListBoxPixmap( listBox, pixmap, text ); + } + #ifndef QT_NO_ICONVIEW + } else if ( parent->inherits("QIconView") ) { + (void) new QIconViewItem( (QIconView *) parent, text, pixmap ); + #endif + } + } + } +} + +void QWidgetFactory::inputMenuItem( QObject **objects, + const UibStrTable& strings, QDataStream& in, + QMenuBar *menuBar ) +{ + QCString name; + QCString text; + Q_UINT16 actionNo; + Q_UINT8 objectTag; + + unpackCString( strings, in, name ); + unpackCString( strings, in, text ); + + QPopupMenu *popupMenu = new QPopupMenu( menuBar->parentWidget(), name ); + + in >> objectTag; + while ( !in.atEnd() && objectTag != Object_End ) { + switch ( objectTag ) { + case Object_ActionRef: + unpackUInt16( in, actionNo ); + ((QAction *) objects[actionNo])->addTo( popupMenu ); + break; + case Object_Separator: + popupMenu->insertSeparator(); + break; + default: + qFatal( "Corrupt" ); + } + in >> objectTag; + } + menuBar->insertItem( translate(text.data()), popupMenu ); +} + +QObject *QWidgetFactory::inputObject( QObject **objects, int& numObjects, + const UibStrTable& strings, + QDataStream& in, QWidget *ancestorWidget, + QObject *parent, QCString className ) +{ + QObject *obj = 0; + QWidget *widget = 0; + QLayout *layout = 0; + QWidget *parentWidget = 0; + QLayout *parentLayout = 0; + + bool isQObject = !className.isEmpty(); + if ( isQObject ) { + if ( parent != 0 ) { + if ( parent->isWidgetType() ) { + if ( parent->inherits("QMainWindow") ) { + parentWidget = ((QMainWindow *) parent)->centralWidget(); + } else { + parentWidget = (QWidget *) parent; + } + } else if ( parent->inherits("QLayout") ) { + parentLayout = (QLayout *) parent; + parentWidget = ancestorWidget; + } + } + + if ( className == "QAction" ) { + unpackCString( strings, in, className ); + if ( className == "QActionGroup" ) { + obj = new QActionGroup( parent ); + } else { + obj = new QAction( parent ); + } + } else if ( className == "QLayout" ) { + unpackCString( strings, in, className ); + LayoutType type = Grid; + if ( className == "QHBoxLayout" ) { + type = HBox; + } else if ( className == "QVBoxLayout" ) { + type = VBox; + } + if ( parentLayout != 0 && parentLayout->inherits("QGridLayout") ) { + layout = createLayout( 0, 0, type ); + } else { + layout = createLayout( parentWidget, parentLayout, type ); + } + obj = layout; + } else if ( className == "QMenuBar" ) { + unpackCString( strings, in, className ); + widget = ((QMainWindow *) parent)->menuBar(); + obj = widget; + } else if ( className == "QToolBar" ) { + Q_UINT8 dock; + in >> dock; + unpackCString( strings, in, className ); + widget = new QToolBar( QString::null, (QMainWindow *) parent, + (Qt::Dock) dock ); + obj = widget; + } else if ( className == "QWidget" ) { + unpackCString( strings, in, className ); + widget = createWidget( className, parentWidget, 0 ); + obj = widget; + } + + if ( widget != 0 ) + ancestorWidget = widget; + d->lastItem = 0; + objects[numObjects++] = obj; + } + + QCString name; + QVariant value; + QCString comment; + QString str; + Q_UINT16 actionNo; + int metAttribute = 0; + Q_UINT16 column = 0; + Q_UINT16 row = 0; + Q_UINT16 colspan = 1; + Q_UINT16 rowspan = 1; + Q_UINT8 paletteTag; + Q_UINT8 objectTag; + + in >> objectTag; + while ( !in.atEnd() && objectTag != Object_End ) { + switch ( objectTag ) { + case Object_ActionRef: + unpackUInt16( in, actionNo ); + ((QAction *) objects[actionNo])->addTo( (QToolBar *) widget ); + break; + case Object_Attribute: + metAttribute = 2; + break; + case Object_Column: + inputColumnOrRow( strings, in, obj, FALSE ); + break; + case Object_Event: + unpackCString( strings, in, name ); + unpackVariant( strings, in, value ); + // ### do something with value.asStringList() + break; + case Object_FontProperty: + { + QFont font; + QString family; + Q_UINT16 pointSize; + Q_UINT8 fontFlags; + + unpackCString( strings, in, name ); + in >> fontFlags; + + if ( fontFlags & Font_Family ) { + unpackString( strings, in, family ); + font.setFamily( family ); + } + if ( fontFlags & Font_PointSize ) { + unpackUInt16( in, pointSize ); + font.setPointSize( pointSize ); + } + if ( fontFlags & Font_Bold ) + font.setBold( TRUE ); + if ( fontFlags & Font_Italic ) + font.setItalic( TRUE ); + if ( fontFlags & Font_Underline ) + font.setUnderline( TRUE ); + if ( fontFlags & Font_StrikeOut ) + font.setStrikeOut( TRUE ); + + if ( obj != 0 ) + setProperty( obj, name, font ); + } + break; + case Object_GridCell: + unpackUInt16( in, column ); + unpackUInt16( in, row ); + unpackUInt16( in, colspan ); + unpackUInt16( in, rowspan ); + break; + case Object_Item: + inputItem( strings, in, obj ); + break; + case Object_MenuItem: + inputMenuItem( objects, strings, in, (QMenuBar *) widget ); + break; + case Object_PaletteProperty: + { + QPalette palette; + QColorGroup colorGroup; + QColor color; + int role = -1; + + unpackCString( strings, in, name ); + + in >> paletteTag; + while ( !in.atEnd() && paletteTag != Palette_End ) { + switch ( paletteTag ) { + case Palette_Active: + palette.setActive( colorGroup ); + role = -1; + break; + case Palette_Inactive: + palette.setInactive( colorGroup ); + role = -1; + break; + case Palette_Disabled: + palette.setDisabled( colorGroup ); + role = -1; + break; + case Palette_Color: + role++; + in >> color; + colorGroup.setColor( (QColorGroup::ColorRole) role, + color ); + break; + case Palette_Pixmap: + unpackVariant( strings, in, value ); + colorGroup.setBrush( (QColorGroup::ColorRole) role, + QBrush(color, value.asPixmap()) ); + break; + default: + qFatal( "Corrupt" ); + } + in >> paletteTag; + } + if ( obj != 0 ) + setProperty( obj, name, palette ); + } + break; + case Object_Row: + inputColumnOrRow( strings, in, obj, TRUE ); + break; + case Object_Spacer: + inputSpacer( strings, in, layout ); + break; + case Object_Separator: + ((QToolBar *) widget)->addSeparator(); + break; + case Object_SubAction: + inputObject( objects, numObjects, strings, in, parentWidget, + obj != 0 ? obj : parent, "QAction" ); + break; + case Object_SubLayout: + inputObject( objects, numObjects, strings, in, parentWidget, obj, + "QLayout" ); + break; + case Object_SubWidget: + inputObject( objects, numObjects, strings, in, parentWidget, obj, + "QWidget" ); + break; + case Object_TextProperty: + unpackCString( strings, in, name ); + unpackCString( strings, in, value.asCString() ); + unpackCString( strings, in, comment ); + str = translate( value.asCString().data(), comment.data() ); + + if ( metAttribute > 0 ) { + if ( name == "title" ) { + if ( parent != 0 ) { + if ( parent->inherits("QTabWidget") ) { + ((QTabWidget *) parent)->insertTab( widget, str ); + } else if ( parent->inherits("QWizard") ) { + ((QWizard *) parent)->addPage( widget, str ); + } + } + } + } else { + if ( obj != 0 ) + setProperty( obj, name, str ); + } + break; + case Object_VariantProperty: + unpackCString( strings, in, name ); + unpackVariant( strings, in, value ); + + if ( metAttribute > 0 ) { + if ( name == "id" ) { + if ( parent != 0 && parent->inherits("QWidgetStack") ) + ((QWidgetStack *) parent)->addWidget( widget, value.toInt() ); + } + } else { + if ( obj != 0 ) + setProperty( obj, name, value ); + } + break; + default: + qFatal( "Corrupt" ); + } + in >> objectTag; + metAttribute--; + } + + if ( parentLayout != 0 ) { + if ( widget != 0 ) { + if ( parentLayout->inherits("QGridLayout") ) { + ((QGridLayout *) parentLayout)->addMultiCellWidget( + widget, row, row + rowspan - 1, column, + column + colspan - 1 ); + } else { + ((QBoxLayout *) parentLayout)->addWidget( widget ); + } + } else if ( layout != 0 ) { + if ( parentLayout->inherits("QGridLayout") ) { + ((QGridLayout *) parentLayout)->addMultiCellLayout( + layout, row, row + rowspan - 1, column, + column + colspan - 1 ); + } + } + } + return obj; +} + +QWidget *QWidgetFactory::createFromUibFile( QDataStream& in, + QObject * /* connector */ , QWidget *parent, const char *name ) +{ +#define END_OF_BLOCK() \ + ( in.atEnd() || in.device()->at() >= nextBlock ) + + Q_UINT8 lf; + Q_UINT8 cr; + in >> lf; + in >> cr; + if ( lf != '\n' || cr != '\r' ) { + qWarning( "File corrupted" ); + return 0; + } + + Q_UINT8 qdatastreamVersion; + in >> qdatastreamVersion; + if ( (int) qdatastreamVersion > in.version() ) { + qWarning( "Incompatible version of Qt" ); + return 0; + } + in.setVersion( qdatastreamVersion ); + + UibStrTable strings; + QObject **objects = 0; + int numObjects = 0; + + Q_UINT8 blockType; + Q_UINT32 blockSize; + + in >> blockType; + while ( !in.atEnd() && blockType != Block_End ) { + unpackUInt32( in, blockSize ); + QIODevice::Offset nextBlock = in.device()->at() + blockSize; + + switch ( blockType ) { + case Block_Actions: + inputObject( objects, numObjects, strings, in, toplevel, toplevel ); + break; + case Block_Buddies: + { + Q_UINT16 labelNo; + Q_UINT16 buddyNo; + + do { + unpackUInt16( in, labelNo ); + unpackUInt16( in, buddyNo ); + QLabel *label = + (QLabel *) objects[labelNo]->qt_cast( "QLabel" ); + if ( label != 0 ) + label->setBuddy( (QWidget *) objects[buddyNo] ); + } while ( !END_OF_BLOCK() ); + } + break; + case Block_Connections: + { + QString language = "C++"; + Q_UINT16 senderNo = 0; + QString signal = "clicked()"; + Q_UINT16 receiverNo = 0; + QString slot = "accept()"; + Q_UINT8 connectionFlags; + + do { + in >> connectionFlags; + if ( connectionFlags & Connection_Language ) + unpackString( strings, in, language ); + if ( connectionFlags & Connection_Sender ) + unpackUInt16( in, senderNo ); + if ( connectionFlags & Connection_Signal ) + unpackStringSplit( strings, in, signal ); + if ( connectionFlags & Connection_Receiver ) + unpackUInt16( in, receiverNo ); + if ( connectionFlags & Connection_Slot ) + unpackStringSplit( strings, in, slot ); + // ### +#if 0 + qWarning( "connect( %p, %s, %p, %s )", objects[senderNo], + signal.latin1(), objects[receiverNo], + slot.latin1() ); +#endif + } while ( !END_OF_BLOCK() ); + } + break; + case Block_Functions: + // ### + qWarning( "Block_Functions not supported" ); + in.device()->at( nextBlock ); + break; + case Block_Images: + { + QString format; + Q_UINT32 length; + QByteArray data; + Image image; + + do { + unpackString( strings, in, image.name ); + unpackString( strings, in, format ); + unpackUInt32( in, length ); + unpackByteArray( in, data ); + image.img = loadImageData( format, length, data ); + images += image; + } while ( !END_OF_BLOCK() ); + } + break; + case Block_Intro: + { + Q_INT16 defaultMargin; + Q_INT16 defaultSpacing; + Q_UINT16 maxObjects; + Q_UINT8 introFlags; + + in >> introFlags; + in >> defaultMargin; + in >> defaultSpacing; + unpackUInt16( in, maxObjects ); + unpackCString( strings, in, d->translationContext ); + + if ( introFlags & Intro_Pixmapinproject ) + usePixmapCollection = TRUE; + if ( defaultMargin != -32768 ) + defMargin = defaultMargin; + if ( defaultSpacing != -32768 ) + defSpacing = defaultSpacing; + objects = new QObject *[maxObjects]; + } + break; + case Block_Menubar: + inputObject( objects, numObjects, strings, in, toplevel, toplevel, + "QMenuBar" ); + break; + case Block_Slots: + { + QString language; + QString slot; + + do { + unpackString( strings, in, language ); + unpackStringSplit( strings, in, slot ); + } while ( !END_OF_BLOCK() ); + } + break; + case Block_Strings: + strings.readBlock( in, blockSize ); + break; + case Block_Tabstops: + { + Q_UINT16 beforeNo; + Q_UINT16 afterNo; + + unpackUInt16( in, beforeNo ); + while ( !END_OF_BLOCK() ) { + unpackUInt16( in, afterNo ); + toplevel->setTabOrder( (QWidget *) objects[beforeNo], + (QWidget *) objects[afterNo] ); + beforeNo = afterNo; + } + } + break; + case Block_Toolbars: + do { + inputObject( objects, numObjects, strings, in, toplevel, + toplevel, "QToolBar" ); + } while ( !END_OF_BLOCK() ); + break; + case Block_Variables: + // ### + qWarning( "Block_Variables not supported" ); + in.device()->at( nextBlock ); + break; + case Block_Widget: + toplevel = (QWidget *) + inputObject( objects, numObjects, strings, in, toplevel, parent, + "QWidget" ); + if ( toplevel != 0 ) + toplevel->setName( name ); + break; + default: + qWarning( "Version error" ); + return 0; + } + in >> blockType; + } + delete[] objects; + return toplevel; +} + +/*! Installs a widget factory \a factory, which normally contains + additional widgets that can then be created using a QWidgetFactory. + See createWidget() for further details. +*/ + +void QWidgetFactory::addWidgetFactory( QWidgetFactory *factory ) +{ + widgetFactories.append( factory ); +} + +/*! + Creates a widget of the type \a className passing \a parent and \a + name to its constructor. + + If \a className is a widget in the Qt library, it is directly + created by this function. If the widget isn't in the Qt library, + each of the installed widget plugins is asked, in turn, to create + the widget. As soon as a plugin says it can create the widget it + is asked to do so. It may occur that none of the plugins can + create the widget, in which case each installed widget factory is + asked to create the widget (see addWidgetFactory()). If the widget + cannot be created by any of these means, 0 is returned. + + If you have a custom widget, and want it to be created using the + widget factory, there are two approaches you can use: + + \list 1 + + \i Write a widget plugin. This allows you to use the widget in + \e{Qt Designer} and in this QWidgetFactory. See the widget plugin + documentation for further details. (See the "Creating Custom + Widgets with Plugins" section of the \link designer-manual.book Qt + Designer manual\endlink for an example. + + \i Subclass QWidgetFactory. Then reimplement this function to + create and return an instance of your custom widget if \a + className equals the name of your widget, otherwise return 0. Then + at the beginning of your program where you want to use the widget + factory to create widgets do a: + \code + QWidgetFactory::addWidgetFactory( new MyWidgetFactory ); + \endcode + where MyWidgetFactory is your QWidgetFactory subclass. + + \endlist +*/ + +QWidget *QWidgetFactory::createWidget( const QString &className, QWidget *parent, + const char *name ) const +{ + // create widgets we know + if ( className == "QPushButton" ) { + return new QPushButton( parent, name ); + } else if ( className == "QToolButton" ) { + return new QToolButton( parent, name ); + } else if ( className == "QCheckBox" ) { + return new QCheckBox( parent, name ); + } else if ( className == "QRadioButton" ) { + return new QRadioButton( parent, name ); + } else if ( className == "QGroupBox" ) { + return new QGroupBox( parent, name ); + } else if ( className == "QButtonGroup" ) { + return new QButtonGroup( parent, name ); + } else if ( className == "QIconView" ) { +#if !defined(QT_NO_ICONVIEW) + return new QIconView( parent, name ); +#endif + } else if ( className == "QTable" ) { +#if !defined(QT_NO_TABLE) + return new QTable( parent, name ); +#endif + } else if ( className == "QListBox" ) { + return new QListBox( parent, name ); + } else if ( className == "QListView" ) { + return new QListView( parent, name ); + } else if ( className == "QLineEdit" ) { + return new QLineEdit( parent, name ); + } else if ( className == "QSpinBox" ) { + return new QSpinBox( parent, name ); + } else if ( className == "QMultiLineEdit" ) { + return new QMultiLineEdit( parent, name ); + } else if ( className == "QLabel" || className == "TextLabel" || className == "PixmapLabel" ) { + return new QLabel( parent, name ); + } else if ( className == "QLayoutWidget" ) { + return new QWidget( parent, name ); + } else if ( className == "QTabWidget" ) { + return new QTabWidget( parent, name ); + } else if ( className == "QComboBox" ) { + return new QComboBox( FALSE, parent, name ); + } else if ( className == "QWidget" ) { + if ( !qwf_stays_on_top ) + return new QWidget( parent, name ); + return new QWidget( parent, name, Qt::WStyle_StaysOnTop ); + } else if ( className == "QDialog" ) { + if ( !qwf_stays_on_top ) + return new QDialog( parent, name ); + return new QDialog( parent, name, FALSE, Qt::WStyle_StaysOnTop ); + } else if ( className == "QWizard" ) { + return new QWizard( parent, name ); + } else if ( className == "QLCDNumber" ) { + return new QLCDNumber( parent, name ); + } else if ( className == "QProgressBar" ) { + return new QProgressBar( parent, name ); + } else if ( className == "QTextView" ) { + return new QTextView( parent, name ); + } else if ( className == "QTextBrowser" ) { + return new QTextBrowser( parent, name ); + } else if ( className == "QDial" ) { + return new QDial( parent, name ); + } else if ( className == "QSlider" ) { + return new QSlider( parent, name ); + } else if ( className == "QFrame" ) { + return new QFrame( parent, name ); + } else if ( className == "QSplitter" ) { + return new QSplitter( parent, name ); + } else if ( className == "Line" ) { + QFrame *f = new QFrame( parent, name ); + f->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + return f; + } else if ( className == "QTextEdit" ) { + return new QTextEdit( parent, name ); + } else if ( className == "QDateEdit" ) { + return new QDateEdit( parent, name ); + } else if ( className == "QTimeEdit" ) { + return new QTimeEdit( parent, name ); + } else if ( className == "QDateTimeEdit" ) { + return new QDateTimeEdit( parent, name ); + } else if ( className == "QScrollBar" ) { + return new QScrollBar( parent, name ); + } else if ( className == "QPopupMenu" ) { + return new QPopupMenu( parent, name ); + } else if ( className == "QWidgetStack" ) { + return new QWidgetStack( parent, name ); + } else if ( className == "QToolBox" ) { + return new QToolBox( parent, name ); + } else if ( className == "QVBox" ) { + return new QVBox( parent, name ); + } else if ( className == "QHBox" ) { + return new QHBox( parent, name ); + } else if ( className == "QGrid" ) { + return new QGrid( 4, parent, name ); + } else if ( className == "QMainWindow" ) { + QMainWindow *mw = 0; + if ( !qwf_stays_on_top ) + mw = new QMainWindow( parent, name ); + else + mw = new QMainWindow( parent, name, Qt::WType_TopLevel | Qt::WStyle_StaysOnTop ); + mw->setCentralWidget( new QWidget( mw, "qt_central_widget" ) ); + mw->centralWidget()->show(); + (void)mw->statusBar(); + return mw; + + } +#if !defined(QT_NO_SQL) + else if ( className == "QDataTable" ) { + return new QDataTable( parent, name ); + } else if ( className == "QDataBrowser" ) { + return new QDesignerDataBrowser2( parent, name ); + } else if ( className == "QDataView" ) { + return new QDesignerDataView2( parent, name ); + } +#endif + + setupPluginDir(); + // try to create it using the loaded widget plugins + if ( !widgetInterfaceManager ) + widgetInterfaceManager = + new QPluginManager<WidgetInterface>( IID_Widget, QApplication::libraryPaths(), + *qwf_plugin_dir ); + + QInterfacePtr<WidgetInterface> iface = 0; + widgetInterfaceManager->queryInterface( className, &iface ); + if ( iface ) { + QWidget *w = iface->create( className, parent, name ); + if ( w ) { + d->customWidgets.replace( className.latin1(), new bool(TRUE) ); + return w; + } + } + + // hope we have a factory which can do it + for ( QWidgetFactory* f = widgetFactories.first(); f; f = widgetFactories.next() ) { + QWidget *w = f->createWidget( className, parent, name ); + if ( w ) + return w; + } + + // no success + return 0; +} + +/*! Returns the names of the widgets this factory can create. */ + +QStringList QWidgetFactory::widgets() +{ + setupWidgetListAndMap(); + return *availableWidgetList; +} + +/*! Returns TRUE if the widget factory can create the specified \a widget; +otherwise returns FALSE. */ + +bool QWidgetFactory::supportsWidget( const QString &widget ) +{ + setupWidgetListAndMap(); + return ( availableWidgetMap->find( widget ) != availableWidgetMap->end() ); +} + +QWidget *QWidgetFactory::createWidgetInternal( const QDomElement &e, QWidget *parent, + QLayout* layout, const QString &classNameArg ) +{ + d->lastItem = 0; + QDomElement n = e.firstChild().toElement(); + QWidget *w = 0; // the widget that got created + QObject *obj = 0; // gets the properties + + QString className = classNameArg; + + int row = e.attribute( "row" ).toInt(); + int col = e.attribute( "column" ).toInt(); + int rowspan = e.attribute( "rowspan" ).toInt(); + int colspan = e.attribute( "colspan" ).toInt(); + if ( rowspan < 1 ) + rowspan = 1; + if ( colspan < 1 ) + colspan = 1; + + bool isQLayoutWidget = FALSE; + + if ( !className.isEmpty() ) { + if ( !layout && className == "QLayoutWidget" ) { + className = "QWidget"; + isQLayoutWidget = TRUE; + } + if ( layout && className == "QLayoutWidget" ) { + // hide layout widgets + w = parent; + } else { + obj = QWidgetFactory::createWidget( className, parent, 0 ); + if ( !obj ) + return 0; + w = (QWidget*)obj; + if ( !toplevel ) + toplevel = w; + if ( w->inherits( "QMainWindow" ) ) + w = ( (QMainWindow*)w )->centralWidget(); + if ( layout ) { + switch( layoutType( layout ) ) { + case HBox: + ( (QHBoxLayout*)layout )->addWidget( w ); + break; + case VBox: + ( (QVBoxLayout*)layout )->addWidget( w ); + break; + case Grid: + ( (QGridLayout*)layout )->addMultiCellWidget( w, row, row + rowspan - 1, + col, col + colspan - 1 ); + break; + default: + break; + } + } + + layout = 0; + } + } +#ifdef QT_CONTAINER_CUSTOM_WIDGETS + QString parentClassName = parent ? parent->className() : 0; + bool isPlugin = parent ? !!d->customWidgets.find( parent->className() ) : FALSE; + if ( isPlugin ) + qWarning( "####### loading custom container widgets without page support not implemented!" ); + // ### TODO loading for custom container widgets without pages +#endif + + int idx = 0; + while ( !n.isNull() ) { + if ( n.tagName() == "spacer" ) { + createSpacer( n, layout ); + } else if ( n.tagName() == "widget" ) { + QMap< QString, QString> *oldDbControls = dbControls; + createWidgetInternal( n, w, layout, n.attribute( "class", "QWidget" ) ); + dbControls = oldDbControls; + } else if ( n.tagName() == "hbox" ) { + QLayout *parentLayout = layout; + if ( layout && layout->inherits( "QGridLayout" ) ) + layout = createLayout( 0, 0, QWidgetFactory::HBox, isQLayoutWidget ); + else + layout = createLayout( w, layout, QWidgetFactory::HBox, isQLayoutWidget ); + obj = layout; + n = n.firstChild().toElement(); + if ( parentLayout && parentLayout->inherits( "QGridLayout" ) ) + ( (QGridLayout*)parentLayout )->addMultiCellLayout( layout, row, + row + rowspan - 1, col, col + colspan - 1 ); + continue; + } else if ( n.tagName() == "grid" ) { + QLayout *parentLayout = layout; + if ( layout && layout->inherits( "QGridLayout" ) ) + layout = createLayout( 0, 0, QWidgetFactory::Grid, isQLayoutWidget ); + else + layout = createLayout( w, layout, QWidgetFactory::Grid, isQLayoutWidget ); + obj = layout; + n = n.firstChild().toElement(); + if ( parentLayout && parentLayout->inherits( "QGridLayout" ) ) + ( (QGridLayout*)parentLayout )->addMultiCellLayout( layout, row, + row + rowspan - 1, col, col + colspan - 1 ); + continue; + } else if ( n.tagName() == "vbox" ) { + QLayout *parentLayout = layout; + if ( layout && layout->inherits( "QGridLayout" ) ) + layout = createLayout( 0, 0, QWidgetFactory::VBox, isQLayoutWidget ); + else + layout = createLayout( w, layout, QWidgetFactory::VBox, isQLayoutWidget ); + obj = layout; + n = n.firstChild().toElement(); + if ( parentLayout && parentLayout->inherits( "QGridLayout" ) ) + ( (QGridLayout*)parentLayout )->addMultiCellLayout( layout, row, + row + rowspan - 1, col, col + colspan - 1 ); + continue; + } else if ( n.tagName() == "property" && obj ) { + setProperty( obj, n.attribute( "name" ), n.firstChild().toElement() ); + } else if ( n.tagName() == "attribute" && w ) { + QString attrib = n.attribute( "name" ); + QVariant v = DomTool::elementToVariant( n.firstChild().toElement(), QVariant() ); + if ( parent ) { + if ( parent->inherits( "QTabWidget" ) ) { + if ( attrib == "title" ) + ( (QTabWidget*)parent )->insertTab( w, translate( v.toString() ) ); + } else if ( parent->inherits( "QWidgetStack" ) ) { + if ( attrib == "id" ) + ( (QWidgetStack*)parent )->addWidget( w, v.toInt() ); + } else if ( parent->inherits( "QToolBox" ) ) { + if ( attrib == "label" ) + ( (QToolBox*)parent )->addItem( w, v.toString() ); + } else if ( parent->inherits( "QWizard" ) ) { + if ( attrib == "title" ) + ( (QWizard*)parent )->addPage( w, translate( v.toString() ) ); +#ifdef QT_CONTAINER_CUSTOM_WIDGETS + } else if ( isPlugin ) { + if ( attrib == "label" ) { + WidgetInterface *iface = 0; + widgetInterfaceManager->queryInterface( parentClassName, &iface ); + if ( iface ) { + QWidgetContainerInterfacePrivate *iface2 = 0; + iface->queryInterface( IID_QWidgetContainer, + (QUnknownInterface**)&iface2 ); + if ( iface2 ) { + iface2->insertPage( parentClassName, + (QWidget*)parent, translate( v.toString() ), -1, w ); + iface2->release(); + } + iface->release(); + } + } +#endif + } + } + } else if ( n.tagName() == "item" ) { + createItem( n, w ); + } else if ( n.tagName() == "column" || n.tagName() == "row" ) { + createColumn( n, w ); + } + + n = n.nextSibling().toElement(); + idx++; + } + + return w; +} + +QLayout *QWidgetFactory::createLayout( QWidget *widget, QLayout* layout, + LayoutType type, bool isQLayoutWidget ) +{ + int spacing = defSpacing; + int margin = defMargin; + + if ( layout || !widget || isQLayoutWidget ) + margin = 0; + + if ( !layout && widget && widget->inherits( "QTabWidget" ) ) + widget = ((QTabWidget*)widget)->currentPage(); + + if ( !layout && widget && widget->inherits( "QWizard" ) ) + widget = ((QWizard*)widget)->currentPage(); + + if ( !layout && widget && widget->inherits( "QWidgetStack" ) ) + widget = ((QWidgetStack*)widget)->visibleWidget(); + + if ( !layout && widget && widget->inherits( "QToolBox" ) ) + widget = ((QToolBox*)widget)->currentItem(); + + QLayout *l = 0; + int align = 0; + if ( !layout && widget && widget->inherits( "QGroupBox" ) ) { + QGroupBox *gb = (QGroupBox*)widget; + gb->setColumnLayout( 0, Qt::Vertical ); + layout = gb->layout(); + layout->setMargin( 0 ); + layout->setSpacing( 0 ); + align = Qt::AlignTop; + } + if ( layout ) { + switch ( type ) { + case HBox: + l = new QHBoxLayout( layout ); + break; + case VBox: + l = new QVBoxLayout( layout ); + break; + case Grid: + l = new QGridLayout( layout ); + break; + default: + return 0; + } + } else { + switch ( type ) { + case HBox: + l = new QHBoxLayout( widget ); + break; + case VBox: + l = new QVBoxLayout( widget ); + break; + case Grid: + l = new QGridLayout( widget ); + break; + default: + return 0; + } + } + l->setAlignment( align ); + l->setMargin( margin ); + l->setSpacing( spacing ); + return l; +} + +QWidgetFactory::LayoutType QWidgetFactory::layoutType( QLayout *layout ) const +{ + if ( layout->inherits( "QHBoxLayout" ) ) + return HBox; + else if ( layout->inherits( "QVBoxLayout" ) ) + return VBox; + else if ( layout->inherits( "QGridLayout" ) ) + return Grid; + return NoLayout; +} + +void QWidgetFactory::setProperty( QObject* obj, const QString &prop, + QVariant value ) +{ + int offset = obj->metaObject()->findProperty( prop, TRUE ); + + if ( offset != -1 ) { + if ( prop == "geometry" && obj == toplevel ) { + toplevel->resize( value.toRect().size() ); + } else if ( prop == "accel" ) { + obj->setProperty( prop, value.toKeySequence() ); + } else { + if ( value.type() == QVariant::String || + value.type() == QVariant::CString ) { + const QMetaProperty *metaProp = + obj->metaObject()->property( offset, TRUE ); + if ( metaProp != 0 && metaProp->isEnumType() ) { + if ( metaProp->isSetType() ) { + QStrList flagsCStr; + QStringList flagsStr = + QStringList::split( '|', value.asString() ); + QStringList::ConstIterator f = flagsStr.begin(); + while ( f != flagsStr.end() ) { + flagsCStr.append( *f ); + ++f; + } + value = QVariant( metaProp->keysToValue(flagsCStr) ); + } else { + QCString key = value.toCString(); + value = QVariant( metaProp->keyToValue(key) ); + } + } + } + obj->setProperty( prop, value ); + } + } else { + if ( obj->isWidgetType() ) { + if ( prop == "toolTip" ) { + if ( !value.toString().isEmpty() ) + QToolTip::add( (QWidget*)obj, translate( value.toString() ) ); + } else if ( prop == "whatsThis" ) { + if ( !value.toString().isEmpty() ) + QWhatsThis::add( (QWidget*)obj, translate( value.toString() ) ); + } else if ( prop == "buddy" ) { + buddies.insert( obj->name(), value.toCString() ); + } else if ( prop == "buttonGroupId" ) { + if ( obj->inherits( "QButton" ) && obj->parent()->inherits( "QButtonGroup" ) ) + ( (QButtonGroup*)obj->parent() )->insert( (QButton*)obj, value.toInt() ); +#ifndef QT_NO_SQL + } else if ( prop == "database" && !obj->inherits( "QDataView" ) + && !obj->inherits( "QDataBrowser" ) ) { + const QStringList& lst = value.asStringList(); + if ( lst.count() > 2 ) { + if ( dbControls ) + dbControls->insert( obj->name(), lst[ 2 ] ); + } else if ( lst.count() == 2 ) { + dbTables.insert( obj->name(), lst ); + } + } else if ( prop == "database" ) { + const QStringList& lst = value.asStringList(); + if ( lst.count() == 2 && obj->inherits( "QWidget" ) ) { + SqlWidgetConnection conn( lst[ 0 ], lst[ 1 ] ); + sqlWidgetConnections.insert( (QWidget*)obj, conn ); + dbControls = conn.dbControls; + } +#endif + } else if ( prop == "frameworkCode" ) { + if ( value.isValid() && !value.toBool() ) + noDatabaseWidgets << obj->name(); + } + } + } +} + +void QWidgetFactory::setProperty( QObject* widget, const QString &prop, const QDomElement &e ) +{ + QString comment; + QVariant value( DomTool::elementToVariant( e, QVariant(), comment ) ); + + if ( e.tagName() == "string" ) { + value = translate( value.asString(), comment ); + } else if ( e.tagName() == "pixmap" ) { + QPixmap pix = loadPixmap( value.toString() ); + if ( !pix.isNull() ) + value = pix; + } else if ( e.tagName() == "iconset" ) { + QPixmap pix = loadPixmap( value.toString() ); + if ( !pix.isNull() ) + value = QIconSet( pix ); + } else if ( e.tagName() == "image" ) { + value = loadFromCollection( value.toString() ); + } else if ( e.tagName() == "palette" ) { + QDomElement n = e.firstChild().toElement(); + QPalette p; + while ( !n.isNull() ) { + QColorGroup cg; + if ( n.tagName() == "active" ) { + cg = loadColorGroup( n ); + p.setActive( cg ); + } else if ( n.tagName() == "inactive" ) { + cg = loadColorGroup( n ); + p.setInactive( cg ); + } else if ( n.tagName() == "disabled" ) { + cg = loadColorGroup( n ); + p.setDisabled( cg ); + } + n = n.nextSibling().toElement(); + } + value = p; + } + setProperty( widget, prop, value ); +} + +void QWidgetFactory::createSpacer( const QDomElement &e, QLayout *layout ) +{ + QDomElement n = e.firstChild().toElement(); + int row = e.attribute( "row" ).toInt(); + int col = e.attribute( "column" ).toInt(); + int rowspan = e.attribute( "rowspan" ).toInt(); + int colspan = e.attribute( "colspan" ).toInt(); + + Qt::Orientation orient = Qt::Horizontal; + int w = 0, h = 0; + QSizePolicy::SizeType sizeType = QSizePolicy::Preferred; + while ( !n.isNull() ) { + if ( n.tagName() == "property" ) { + QString prop = n.attribute( "name" ); + if ( prop == "orientation" ) { + if ( n.firstChild().firstChild().toText().data() == "Horizontal" ) + orient = Qt::Horizontal; + else + orient = Qt::Vertical; + } else if ( prop == "sizeType" ) { + sizeType = stringToSizeType( n.firstChild().firstChild().toText().data() ); + } else if ( prop == "sizeHint" ) { + w = n.firstChild().firstChild().firstChild().toText().data().toInt(); + h = n.firstChild().firstChild().nextSibling().firstChild().toText().data().toInt(); + } + } + n = n.nextSibling().toElement(); + } + + if ( rowspan < 1 ) + rowspan = 1; + if ( colspan < 1 ) + colspan = 1; + QSpacerItem *item = new QSpacerItem( w, h, orient == Qt::Horizontal ? sizeType : QSizePolicy::Minimum, + orient == Qt::Vertical ? sizeType : QSizePolicy::Minimum ); + if ( layout ) { + if ( layout->inherits( "QBoxLayout" ) ) + ( (QBoxLayout*)layout )->addItem( item ); + else + ( (QGridLayout*)layout )->addMultiCell( item, row, row + rowspan - 1, col, col + colspan - 1, + orient == Qt::Horizontal ? Qt::AlignVCenter : Qt::AlignHCenter ); + } +} + +static QImage loadImageData( QDomElement &n2 ) +{ + QString format = n2.attribute( "format", "PNG" ); + QString hex = n2.firstChild().toText().data(); + int n = hex.length() / 2; + QByteArray data( n ); + for ( int i = 0; i < n; i++ ) + data[i] = (char) hex.mid( 2 * i, 2 ).toUInt( 0, 16 ); + return loadImageData( format, n2.attribute("length").toULong(), data ); +} + +void QWidgetFactory::loadImageCollection( const QDomElement &e ) +{ + QDomElement n = e.firstChild().toElement(); + while ( !n.isNull() ) { + if ( n.tagName() == "image" ) { + Image img; + img.name = n.attribute( "name" ); + QDomElement n2 = n.firstChild().toElement(); + while ( !n2.isNull() ) { + if ( n2.tagName() == "data" ) + img.img = loadImageData( n2 ); + n2 = n2.nextSibling().toElement(); + } + images.append( img ); + n = n.nextSibling().toElement(); + } + } +} + +QImage QWidgetFactory::loadFromCollection( const QString &name ) +{ + QValueList<Image>::Iterator it = images.begin(); + for ( ; it != images.end(); ++it ) { + if ( ( *it ).name == name ) + return ( *it ).img; + } + return QImage(); +} + +QPixmap QWidgetFactory::loadPixmap( const QString& name ) +{ + QPixmap pix; + if ( usePixmapCollection ) { + const QMimeSource *m = QMimeSourceFactory::defaultFactory()->data( name ); + if ( m ) + QImageDrag::decode( m, pix ); + } else { + pix.convertFromImage( loadFromCollection(name) ); + } + return pix; +} + +QPixmap QWidgetFactory::loadPixmap( const QDomElement &e ) +{ + return loadPixmap( e.firstChild().toText().data() ); +} + +QColorGroup QWidgetFactory::loadColorGroup( const QDomElement &e ) +{ + QColorGroup cg; + int r = -1; + QDomElement n = e.firstChild().toElement(); + QColor col; + while ( !n.isNull() ) { + if ( n.tagName() == "color" ) { + r++; + cg.setColor( (QColorGroup::ColorRole)r, (col = DomTool::readColor( n ) ) ); + } else if ( n.tagName() == "pixmap" ) { + QPixmap pix = loadPixmap( n ); + cg.setBrush( (QColorGroup::ColorRole)r, QBrush( col, pix ) ); + } + n = n.nextSibling().toElement(); + } + return cg; +} + +struct Connection +{ + QObject *sender, *receiver; + QCString signal, slot; + bool operator==( const Connection &c ) const { + return sender == c.sender && receiver == c.receiver && + signal == c.signal && slot == c.slot ; + } + + Connection() : sender( 0 ), receiver( 0 ) { } +}; + +class NormalizeObject : public QObject +{ +public: + NormalizeObject() : QObject() {} + static QCString normalizeSignalSlot( const char *signalSlot ) { return QObject::normalizeSignalSlot( signalSlot ); } +}; + +void QWidgetFactory::loadConnections( const QDomElement &e, QObject *connector ) +{ + QDomElement n = e.firstChild().toElement(); + while ( !n.isNull() ) { + if ( n.tagName() == "connection" ) { + QString lang = n.attribute( "language", "C++" ); + QDomElement n2 = n.firstChild().toElement(); + Connection conn; + while ( !n2.isNull() ) { + if ( n2.tagName() == "sender" ) { + QString name = n2.firstChild().toText().data(); + if ( name == "this" || qstrcmp( toplevel->name(), name ) == 0 ) { + conn.sender = toplevel; + } else { + if ( name == "this" ) + name = toplevel->name(); + QObjectList *l = toplevel->queryList( 0, name, FALSE ); + if ( l ) { + if ( l->first() ) + conn.sender = l->first(); + delete l; + } + } + if ( !conn.sender ) + conn.sender = findAction( name ); + } else if ( n2.tagName() == "signal" ) { + conn.signal = n2.firstChild().toText().data(); + } else if ( n2.tagName() == "receiver" ) { + QString name = n2.firstChild().toText().data(); + if ( name == "this" || qstrcmp( toplevel->name(), name ) == 0 ) { + conn.receiver = toplevel; + } else { + QObjectList *l = toplevel->queryList( 0, name, FALSE ); + if ( l ) { + if ( l->first() ) + conn.receiver = l->first(); + delete l; + } + } + } else if ( n2.tagName() == "slot" ) { + conn.slot = n2.firstChild().toText().data(); + } + n2 = n2.nextSibling().toElement(); + } + + conn.signal = NormalizeObject::normalizeSignalSlot( conn.signal ); + conn.slot = NormalizeObject::normalizeSignalSlot( conn.slot ); + + if ( !conn.sender || !conn.receiver ) { + n = n.nextSibling().toElement(); + continue; + } + + QObject *sender = 0, *receiver = 0; + QObjectList *l = toplevel->queryList( 0, conn.sender->name(), FALSE ); + if ( qstrcmp( conn.sender->name(), toplevel->name() ) == 0 ) { + sender = toplevel; + } else { + if ( !l || !l->first() ) { + delete l; + n = n.nextSibling().toElement(); + continue; + } + sender = l->first(); + delete l; + } + if ( !sender ) + sender = findAction( conn.sender->name() ); + + if ( qstrcmp( conn.receiver->name(), toplevel->name() ) == 0 ) { + receiver = toplevel; + } else { + l = toplevel->queryList( 0, conn.receiver->name(), FALSE ); + if ( !l || !l->first() ) { + delete l; + n = n.nextSibling().toElement(); + continue; + } + receiver = l->first(); + delete l; + } + + QString s = "2""%1"; + s = s.arg( conn.signal ); + QString s2 = "1""%1"; + s2 = s2.arg( conn.slot ); + + QStrList signalList = sender->metaObject()->signalNames( TRUE ); + QStrList slotList = receiver->metaObject()->slotNames( TRUE ); + + // if this is a connection to a custom slot and we have a connector, try this as receiver + if ( slotList.find( conn.slot ) == -1 && receiver == toplevel && connector ) { + slotList = connector->metaObject()->slotNames( TRUE ); + receiver = connector; + } + + // avoid warnings + if ( signalList.find( conn.signal ) == -1 || + slotList.find( conn.slot ) == -1 ) { + n = n.nextSibling().toElement(); + continue; + } + QObject::connect( sender, s, receiver, s2 ); + } + n = n.nextSibling().toElement(); + } +} + +void QWidgetFactory::loadTabOrder( const QDomElement &e ) +{ + QWidget *last = 0; + QDomElement n = e.firstChild().toElement(); + while ( !n.isNull() ) { + if ( n.tagName() == "tabstop" ) { + QString name = n.firstChild().toText().data(); + QObjectList *l = toplevel->queryList( 0, name, FALSE ); + if ( l ) { + if ( l->first() ) { + QWidget *w = (QWidget*)l->first(); + if ( last ) + toplevel->setTabOrder( last, w ); + last = w; + } + delete l; + } + } + n = n.nextSibling().toElement(); + } +} + +void QWidgetFactory::createListViewColumn( QListView *lv, const QString& txt, + const QPixmap& pix, bool clickable, + bool resizable ) +{ + if ( pix.isNull() ) { + lv->addColumn( txt ); + } else { + lv->addColumn( pix, txt ); + } + + int i = lv->header()->count() - 1; + if ( !pix.isNull() ) + lv->header()->setLabel( i, pix, txt ); + if ( !clickable ) + lv->header()->setClickEnabled( clickable, i ); + if ( !resizable ) + lv->header()->setResizeEnabled( resizable, i ); +} + +#ifndef QT_NO_TABLE +void QWidgetFactory::createTableColumnOrRow( QTable *table, const QString& txt, + const QPixmap& pix, + const QString& field, bool isRow ) +{ +#ifndef QT_NO_SQL + bool isSql = table->inherits( "QDataTable" ); +#endif + if ( isRow ) + table->setNumRows( table->numRows() + 1 ); + else { +#ifndef QT_NO_SQL + if ( !isSql ) +#endif + table->setNumCols( table->numCols() + 1 ); + } + + QValueList<Field> fieldMap; + if ( fieldMaps.find( table ) != fieldMaps.end() ) { + fieldMap = *fieldMaps.find( table ); + fieldMaps.remove( table ); + } + + int i = isRow ? table->numRows() - 1 : table->numCols() - 1; + QHeader *h = !isRow ? table->horizontalHeader() : table->verticalHeader(); + if ( !pix.isNull() ) { +#ifndef QT_NO_SQL + if ( isSql ) + ((QDataTable*)table)->addColumn( field, txt, -1, pix ); + else +#endif + h->setLabel( i, pix, txt ); + } else { +#ifndef QT_NO_SQL + if ( isSql ) + ((QDataTable*)table)->addColumn( field, txt ); + else +#endif + h->setLabel( i, txt ); + } + if ( !isRow && !field.isEmpty() ) { + fieldMap.append( Field( txt, pix, field ) ); + fieldMaps.insert( table, fieldMap ); + } + +} +#endif + +void QWidgetFactory::createColumn( const QDomElement &e, QWidget *widget ) +{ + if ( widget->inherits( "QListView" ) && e.tagName() == "column" ) { + QListView *lv = (QListView*)widget; + QDomElement n = e.firstChild().toElement(); + QPixmap pix; + QString txt; + bool clickable = TRUE, resizable = TRUE; + while ( !n.isNull() ) { + if ( n.tagName() == "property" ) { + QString attrib = n.attribute( "name" ); + QVariant v = DomTool::elementToVariant( n.firstChild().toElement(), QVariant() ); + if ( attrib == "text" ) + txt = translate( v.toString() ); + else if ( attrib == "pixmap" ) + pix = loadPixmap( n.firstChild().toElement().toElement() ); + else if ( attrib == "clickable" ) + clickable = v.toBool(); + else if ( attrib == "resizable" || attrib == "resizeable" ) + resizable = v.toBool(); + } + n = n.nextSibling().toElement(); + } + createListViewColumn( lv, txt, pix, clickable, resizable ); + } +#ifndef QT_NO_TABLE + else if ( widget->inherits( "QTable" ) ) { + QTable *table = (QTable*)widget; + + QDomElement n = e.firstChild().toElement(); + QPixmap pix; + QString txt; + QString field; + + while ( !n.isNull() ) { + if ( n.tagName() == "property" ) { + QString attrib = n.attribute( "name" ); + QVariant v = DomTool::elementToVariant( n.firstChild().toElement(), QVariant() ); + if ( attrib == "text" ) + txt = translate( v.toString() ); + else if ( attrib == "pixmap" ) { + if ( !n.firstChild().firstChild().toText().data().isEmpty() ) + pix = loadPixmap( n.firstChild().toElement().toElement() ); + } else if ( attrib == "field" ) + field = translate( v.toString() ); + } + n = n.nextSibling().toElement(); + } + createTableColumnOrRow( table, txt, pix, field, e.tagName() == "row" ); + } +#endif +} + +void QWidgetFactory::loadItem( const QDomElement &e, QPixmap &pix, QString &txt, bool &hasPixmap ) +{ + QDomElement n = e; + hasPixmap = FALSE; + while ( !n.isNull() ) { + if ( n.tagName() == "property" ) { + QString attrib = n.attribute( "name" ); + QVariant v = DomTool::elementToVariant( n.firstChild().toElement(), QVariant() ); + if ( attrib == "text" ) + txt = translate( v.toString() ); + else if ( attrib == "pixmap" ) { + pix = loadPixmap( n.firstChild().toElement() ); + hasPixmap = !pix.isNull(); + } + } + n = n.nextSibling().toElement(); + } +} + +void QWidgetFactory::createItem( const QDomElement &e, QWidget *widget, QListViewItem *i ) +{ + if ( widget->inherits( "QListBox" ) || widget->inherits( "QComboBox" ) ) { + QDomElement n = e.firstChild().toElement(); + QPixmap pix; + bool hasPixmap = FALSE; + QString txt; + loadItem( n, pix, txt, hasPixmap ); + QListBox *lb = 0; + if ( widget->inherits( "QListBox" ) ) { + lb = (QListBox*)widget; + } else { + QComboBox *cb = (QComboBox*)widget; + lb = cb->listBox(); + if (!lb) { + lb = new QListBox(cb); + cb->setListBox(lb); + } + } + if ( hasPixmap ) { + new QListBoxPixmap( lb, pix, txt ); + } else { + new QListBoxText( lb, txt ); + } +#ifndef QT_NO_ICONVIEW + } else if ( widget->inherits( "QIconView" ) ) { + QDomElement n = e.firstChild().toElement(); + QPixmap pix; + bool hasPixmap = FALSE; + QString txt; + loadItem( n, pix, txt, hasPixmap ); + + QIconView *iv = (QIconView*)widget; + new QIconViewItem( iv, txt, pix ); +#endif + } else if ( widget->inherits( "QListView" ) ) { + QDomElement n = e.firstChild().toElement(); + QPixmap pix; + QValueList<QPixmap> pixmaps; + QStringList textes; + QListViewItem *item = 0; + QListView *lv = (QListView*)widget; + if ( i ) + item = new QListViewItem( i, d->lastItem ); + else + item = new QListViewItem( lv, d->lastItem ); + while ( !n.isNull() ) { + if ( n.tagName() == "property" ) { + QString attrib = n.attribute( "name" ); + QVariant v = DomTool::elementToVariant( n.firstChild().toElement(), QVariant() ); + if ( attrib == "text" ) + textes << translate( v.toString() ); + else if ( attrib == "pixmap" ) { + QString s = v.toString(); + if ( s.isEmpty() ) { + pixmaps << QPixmap(); + } else { + pix = loadPixmap( n.firstChild().toElement() ); + pixmaps << pix; + } + } + } else if ( n.tagName() == "item" ) { + item->setOpen( TRUE ); + createItem( n, widget, item ); + } + + n = n.nextSibling().toElement(); + } + + for ( int i = 0; i < lv->columns(); ++i ) { + item->setText( i, textes[ i ] ); + item->setPixmap( i, pixmaps[ i ] ); + } + d->lastItem = item; + } +} + + + +void QWidgetFactory::loadChildAction( QObject *parent, const QDomElement &e ) +{ + QDomElement n = e; + QAction *a = 0; + bool hasMenuText = FALSE; + if ( n.tagName() == "action" ) { + a = new QAction( parent ); + QDomElement n2 = n.firstChild().toElement(); + + while ( !n2.isNull() ) { + if ( n2.tagName() == "property" ) { + QString prop(n2.attribute("name")); + if (prop == "menuText") + hasMenuText = TRUE; + setProperty( a, prop, n2.firstChild().toElement() ); + } + n2 = n2.nextSibling().toElement(); + } + if ( !parent->inherits( "QAction" ) ) + actionList.append( a ); + } else if ( n.tagName() == "actiongroup" ) { + a = new QActionGroup( parent ); + QDomElement n2 = n.firstChild().toElement(); + while ( !n2.isNull() ) { + if ( n2.tagName() == "property" ) { + QString prop(n2.attribute("name")); + if (prop == "menuText") + hasMenuText = TRUE; + setProperty( a, prop, n2.firstChild().toElement() ); + } else if ( n2.tagName() == "action" || + n2.tagName() == "actiongroup" ) { + loadChildAction( a, n2 ); + + } + n2 = n2.nextSibling().toElement(); + } + if ( !parent->inherits( "QAction" ) ) + actionList.append( a ); + } + + if (a && !hasMenuText && !a->text().isEmpty() && uiFileVersion < "3.3") + a->setMenuText(a->text()); +} + +void QWidgetFactory::loadActions( const QDomElement &e ) +{ + QDomElement n = e.firstChild().toElement(); + while ( !n.isNull() ) { + if ( n.tagName() == "action" ) { + loadChildAction( toplevel, n ); + } else if ( n.tagName() == "actiongroup" ) { + loadChildAction( toplevel, n ); + } + n = n.nextSibling().toElement(); + } +} + +void QWidgetFactory::loadToolBars( const QDomElement &e ) +{ + QDomElement n = e.firstChild().toElement(); + QMainWindow *mw = ( (QMainWindow*)toplevel ); + QToolBar *tb = 0; + while ( !n.isNull() ) { + if ( n.tagName() == "toolbar" ) { + Qt::Dock dock = (Qt::Dock)n.attribute( "dock" ).toInt(); + tb = new QToolBar( QString::null, mw, dock ); + tb->setLabel( n.attribute( "label" ) ); + tb->setName( n.attribute( "name" ) ); + QDomElement n2 = n.firstChild().toElement(); + while ( !n2.isNull() ) { + if ( n2.tagName() == "action" ) { + QAction *a = findAction( n2.attribute( "name" ) ); + if ( a ) + a->addTo( tb ); + } else if ( n2.tagName() == "separator" ) { + tb->addSeparator(); + } else if ( n2.tagName() == "widget" ) { + (void)createWidgetInternal( n2, tb, 0, n2.attribute( "class", "QWidget" ) ); + } else if ( n2.tagName() == "property" ) { + setProperty( tb, n2.attribute( "name" ), n2.firstChild().toElement() ); + } + n2 = n2.nextSibling().toElement(); + } + } + n = n.nextSibling().toElement(); + } +} + +void QWidgetFactory::loadMenuBar( const QDomElement &e ) +{ + QDomElement n = e.firstChild().toElement(); + QMainWindow *mw = ( (QMainWindow*)toplevel ); + QMenuBar *mb = mw->menuBar(); + while ( !n.isNull() ) { + if ( n.tagName() == "item" ) { + QPopupMenu *popup = new QPopupMenu( mw ); + loadPopupMenu( popup, n ); + popup->setName( n.attribute( "name" ) ); + mb->insertItem( translate( n.attribute( "text" ) ), popup ); + } else if ( n.tagName() == "property" ) { + setProperty( mb, n.attribute( "name" ), n.firstChild().toElement() ); + } else if ( n.tagName() == "separator" ) { + mb->insertSeparator(); + } + n = n.nextSibling().toElement(); + } +} + +void QWidgetFactory::loadPopupMenu( QPopupMenu *p, const QDomElement &e ) +{ + QMainWindow *mw = ( (QMainWindow*)toplevel ); + QDomElement n = e.firstChild().toElement(); + while ( !n.isNull() ) { + if ( n.tagName() == "action" || n.tagName() == "actiongroup" ) { + QAction *a = findAction( n.attribute( "name" ) ); + QDomElement n2 = n.nextSibling().toElement(); + if ( n2.tagName() == "item") { // load submenu + QPopupMenu *popup = new QPopupMenu( mw ); + popup->setName( n2.attribute( "name" ) ); + if ( a ) { + p->setAccel( a->accel(), p->insertItem( a->iconSet(), + translate( n2.attribute( "text" ).utf8().data() ), + popup ) ); + } else { + p->insertItem( translate( n2.attribute( "text" ).utf8().data() ), popup ); + } + loadPopupMenu( popup, n2 ); + n = n2; + } else { + if ( a ) { + a->addTo( p ); + } + } + a = 0; + } else if ( n.tagName() == "separator" ) { + p->insertSeparator(); + } + n = n.nextSibling().toElement(); + } +} + +// compatibility with early 3.0 betas +// ### remove for 4.0 +void QWidgetFactory::loadFunctions( const QDomElement & ) +{ +} + +QAction *QWidgetFactory::findAction( const QString &name ) +{ + for ( QAction *a = actionList.first(); a; a = actionList.next() ) { + if ( QString( a->name() ) == name ) + return a; + QAction *ac = (QAction*)a->child( name.latin1(), "QAction" ); + if ( ac ) + return ac; + } + return 0; +} + +/*! + If you use a pixmap collection (which is the default for new + projects) rather than saving the pixmaps within the .ui XML file, + you must load the pixmap collection. QWidgetFactory looks in the + default QMimeSourceFactory for the pixmaps. Either add it there + manually, or call this function and specify the directory where + the images can be found, as \a dir. This is normally the + directory called \c images in the project's directory. +*/ + +void QWidgetFactory::loadImages( const QString &dir ) +{ + QDir d( dir ); + QStringList l = d.entryList( QDir::Files ); + for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) + QMimeSourceFactory::defaultFactory()->setPixmap( *it, QPixmap( d.path() + "/" + *it, "PNG" ) ); + +} + +void QWidgetFactory::loadExtraSource() +{ + if ( !qwf_language || !languageInterfaceManager ) + return; + QString lang = *qwf_language; + LanguageInterface *iface = 0; + languageInterfaceManager->queryInterface( lang, &iface ); + if ( !iface ) + return; + QFile f( qwf_currFileName + iface->formCodeExtension() ); + if ( f.open( IO_ReadOnly ) ) { + QTextStream ts( &f ); + code = ts.read(); + } +} + +QString QWidgetFactory::translate( const QString& sourceText, const QString& comment ) +{ + return qApp->translate( d->translationContext, sourceText.utf8(), comment.utf8(), + QApplication::UnicodeUTF8 ); +} + +QString QWidgetFactory::translate( const char *sourceText, const char *comment ) +{ + return qApp->translate( d->translationContext, sourceText, comment, + QApplication::UnicodeUTF8 ); +} diff --git a/tools/designer/uilib/qwidgetfactory.h b/tools/designer/uilib/qwidgetfactory.h new file mode 100644 index 0000000..daf5db6 --- /dev/null +++ b/tools/designer/uilib/qwidgetfactory.h @@ -0,0 +1,187 @@ +/********************************************************************** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt Designer. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with +** the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef QWIDGETFACTORY_H +#define QWIDGETFACTORY_H + +#ifndef QT_H +#include <qstring.h> +#include <qptrlist.h> +#include <qimage.h> +#include <qpixmap.h> +#include <qvaluelist.h> +#include <qmap.h> +#include <qaction.h> +#endif // QT_H + +class QDomDocument; +class QDomElement; +class QLayout; +class QListView; +class QListViewItem; +class QMenuBar; +class QTable; +class QWidget; +class QWidgetFactoryPrivate; +class UibStrTable; + +class QWidgetFactory +{ +public: + QWidgetFactory(); + virtual ~QWidgetFactory(); + + static QWidget *create( const QString &uiFile, QObject *connector = 0, QWidget *parent = 0, const char *name = 0 ); + static QWidget *create( QIODevice *dev, QObject *connector = 0, QWidget *parent = 0, const char *name = 0 ); + static void addWidgetFactory( QWidgetFactory *factory ); + static void loadImages( const QString &dir ); + + virtual QWidget *createWidget( const QString &className, QWidget *parent, const char *name ) const; + static QStringList widgets(); + static bool supportsWidget( const QString &widget ); + +private: + enum LayoutType { HBox, VBox, Grid, NoLayout }; + void loadImageCollection( const QDomElement &e ); + void loadConnections( const QDomElement &e, QObject *connector ); + void loadTabOrder( const QDomElement &e ); + QWidget *createWidgetInternal( const QDomElement &e, QWidget *parent, QLayout* layout, const QString &classNameArg ); + QLayout *createLayout( QWidget *widget, QLayout* layout, LayoutType type, bool isQLayoutWidget = FALSE ); + LayoutType layoutType( QLayout *l ) const; + void setProperty( QObject* widget, const QString &prop, QVariant value ); + void setProperty( QObject* widget, const QString &prop, const QDomElement &e ); + void createSpacer( const QDomElement &e, QLayout *layout ); + QImage loadFromCollection( const QString &name ); + QPixmap loadPixmap( const QString &name ); + QPixmap loadPixmap( const QDomElement &e ); + QColorGroup loadColorGroup( const QDomElement &e ); + void createListViewColumn( QListView *lv, const QString& txt, + const QPixmap& pix, bool clickable, + bool resizable ); +#ifndef QT_NO_TABLE + void createTableColumnOrRow( QTable *table, const QString& txt, + const QPixmap& pix, const QString& field, + bool isRow ); +#endif + void createColumn( const QDomElement &e, QWidget *widget ); + void loadItem( const QDomElement &e, QPixmap &pix, QString &txt, bool &hasPixmap ); + void createItem( const QDomElement &e, QWidget *widget, QListViewItem *i = 0 ); + void loadChildAction( QObject *parent, const QDomElement &e ); + void loadActions( const QDomElement &e ); + void loadToolBars( const QDomElement &e ); + void loadMenuBar( const QDomElement &e ); + void loadPopupMenu( QPopupMenu *p, const QDomElement &e ); + void loadFunctions( const QDomElement &e ); + QAction *findAction( const QString &name ); + void loadExtraSource(); + QString translate( const char *sourceText, const char *comment = "" ); + QString translate( const QString& sourceText, const QString& comment = QString::null ); + + void unpackUInt16( QDataStream& in, Q_UINT16& n ); + void unpackUInt32( QDataStream& in, Q_UINT32& n ); + void unpackByteArray( QDataStream& in, QByteArray& array ); + void unpackCString( const UibStrTable& strings, QDataStream& in, + QCString& cstr ); + void unpackString( const UibStrTable& strings, QDataStream& in, + QString& str ); + void unpackStringSplit( const UibStrTable& strings, QDataStream& in, + QString& str ); + void unpackVariant( const UibStrTable& strings, QDataStream& in, + QVariant& value ); + void inputSpacer( const UibStrTable& strings, QDataStream& in, + QLayout *parent ); + void inputColumnOrRow( const UibStrTable& strings, QDataStream& in, + QObject *parent, bool isRow ); + void inputItem( const UibStrTable& strings, QDataStream& in, + QObject *parent, QListViewItem *parentItem = 0 ); + void inputMenuItem( QObject **objects, const UibStrTable& strings, + QDataStream& in, QMenuBar *menuBar ); + QObject *inputObject( QObject **objects, int& numObjects, + const UibStrTable& strings, QDataStream& in, + QWidget *ancestorWidget, QObject *parent, + QCString className = "" ); + QWidget *createFromUiFile( QDomDocument doc, QObject *connector, + QWidget *parent, const char *name ); + QWidget *createFromUibFile( QDataStream& in, QObject *connector, + QWidget *parent, const char *name ); + +private: + struct Image { + QImage img; + QString name; + bool operator==( const Image &i ) const { + return ( i.name == name && + i.img == img ); + } + }; + + struct Field + { + Field() {} + Field( const QString &s1, const QPixmap &p, const QString &s2 ) : name( s1 ), pix( p ), field( s2 ) {} + QString name; + QPixmap pix; + QString field; + Q_DUMMY_COMPARISON_OPERATOR( Field ) + }; + + struct SqlWidgetConnection + { + SqlWidgetConnection() {} + SqlWidgetConnection( const QString &c, const QString &t ) + : conn( c ), table( t ), dbControls( new QMap<QString, QString>() ) {} + QString conn; + QString table; + QMap<QString, QString> *dbControls; + Q_DUMMY_COMPARISON_OPERATOR( SqlWidgetConnection ) + }; + + QValueList<Image> images; + QWidget *toplevel; + QWidgetFactoryPrivate *d; + QMap<QString, QString> *dbControls; + QMap<QString, QStringList> dbTables; + QMap<QWidget*, SqlWidgetConnection> sqlWidgetConnections; + QMap<QString, QString> buddies; + QMap<QTable*, QValueList<Field> > fieldMaps; + QPtrList<QAction> actionList; + QMap<QString, QString> languageSlots; + QStringList noDatabaseWidgets; + bool usePixmapCollection; + int defMargin; + int defSpacing; + QString code; + QString uiFileVersion; +}; + +#endif diff --git a/tools/designer/uilib/test/main.cpp b/tools/designer/uilib/test/main.cpp new file mode 100644 index 0000000..f5f0559 --- /dev/null +++ b/tools/designer/uilib/test/main.cpp @@ -0,0 +1,50 @@ +/********************************************************************** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt GUI Designer. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with +** the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include <qapplication.h> +#include "../qwidgetfactory.h" + +int main( int argc, char ** argv ) +{ + QApplication a( argc, argv ); + if ( argc == 1 ) + return 0; + if ( argc == 3 ) + QWidgetFactory::loadImages( argv[ 2 ] ); + QWidget *w = QWidgetFactory::create( argv[ 1 ] ); + if ( !w ) + return 0; + w->show(); + a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) ); + return a.exec(); +} diff --git a/tools/designer/uilib/test/test.pro b/tools/designer/uilib/test/test.pro new file mode 100644 index 0000000..b2459c0 --- /dev/null +++ b/tools/designer/uilib/test/test.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += qt warn_on release +HEADERS = +SOURCES = main.cpp +TARGET = test +LIBS += -L$$QT_BUILD_TREE/lib -lqui + diff --git a/tools/designer/uilib/uilib.pro b/tools/designer/uilib/uilib.pro new file mode 100644 index 0000000..bf98d7b --- /dev/null +++ b/tools/designer/uilib/uilib.pro @@ -0,0 +1,30 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +win32:CONFIG += static +win32:CONFIG -= dll +SOURCES = qwidgetfactory.cpp \ + ../shared/domtool.cpp \ + ../shared/uib.cpp + +HEADERS = ../shared/domtool.h \ + ../shared/uib.h + +sql:SOURCES += ../designer/database.cpp +sql:HEADERS += ../designer/database2.h + +DEFINES += QT_INTERNAL_XML +!win32-borland:DEFINES += Q_TEMPLATE_EXTERN=extern +include( ../../../src/qt_professional.pri ) +TARGET = qui +INCLUDEPATH += ../shared +DESTDIR = ../../../lib +VERSION = 1.0.0 +DEFINES += RESOURCE + +unix { + target.path=$$libs.path + + INSTALLS += target +} + +mac:QMAKE_LFLAGS_PREBIND = -prebind -seg1addr 0xB9000000 |