📄 qwidgetfactory.cpp
字号:
/************************************************************************ Copyright (C) 2000-2002 Trolltech AS. All rights reserved.**** This file is part of Qt Designer.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qwidgetfactory.h"#include "../interfaces/interpreterinterface.h"#include "../interfaces/languageinterface.h"#include "../interfaces/widgetinterface.h"#include <qfeatures.h>#include "../designer/config.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 <qtextedit.h>#include <qscrollbar.h>#include <qmainwindow.h>#include <qsplitter.h>#include <qaction.h>#include <qpopupmenu.h>#include <qmenubar.h>#include <qpopupmenu.h>#include <qwidgetstack.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<InterpreterInterface> *interpreterInterfaceManager = 0;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"; 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" ) { 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, "XPM" ); } 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\e{Qt Designer} 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 ). 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 ); if ( !interpreterInterfaceManager ) interpreterInterfaceManager = new QPluginManager<InterpreterInterface>( IID_Interpreter, 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 } if ( widgetFactory->toplevel || qwf_form_object ) { if ( qwf_language && interpreterInterfaceManager && qwf_execute_code ) { InterpreterInterface *interpreterInterface = 0; interpreterInterfaceManager->queryInterface( *qwf_language, &interpreterInterface ); if ( interpreterInterface ) { interpreterInterface->init(); interpreterInterface->exec( qwf_form_object ? qwf_form_object : widgetFactory->toplevel, widgetFactory->code ); } } } 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 ); 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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -