Exemple #1
0
void Uic::registerLayouts( const QDomElement &e ) {
  if ( layouts.contains( e.tagName() ) ) {
    createObjectDecl( e );
    QString t = e.tagName();
    if ( t == "vbox" || t == "hbox" || t == "grid" )
      createSpacerDecl( e );
  }

  QDomNodeList nl = e.childNodes();
  for ( int i = 0; i < ( int ) nl.length(); ++i )
    registerLayouts( nl.item( i ).toElement() );
}
/*!
  Creates a declaration (header file) for the form given in \a e

  \sa createFormImpl(), createObjectDecl()
*/
void Uic::createFormDecl( const QDomElement &e )
{
    QDomElement n;
    QDomNodeList nl;
    int i;
    QString objClass = getClassName( e );
    if ( objClass.isEmpty() )
	return;
    QString objName = getObjectName( e );

    QStringList typeDefs;

    QMap<QString, CustomInclude> customWidgetIncludes;

    QString imageMembers;

    /*
      We are generating a few QImage members that are not strictly
      necessary in some cases. Ideally, we would use requiredImage,
      which is computed elsewhere, to keep the generated .h and .cpp
      files synchronized.
    */

    // at first the images
    QMap<QString, int> customWidgets;
    QStringList forwardDecl;
    QStringList forwardDecl2;
    QString exportMacro;
    for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
	if ( n.tagName() == "images" ) {
	    nl = n.elementsByTagName( "image" );
	    for ( i = 0; i < (int) nl.length(); i++ ) {
		QString img = registerObject( nl.item(i).toElement().attribute("name") );
		registerObject( img );
		imageMembers += QString( "    QPixmap %1;\n" ).arg( img );
	    }
	} else if ( n.tagName() == "customwidgets" ) {
	    QDomElement n2 = n.firstChild().toElement();
	    while ( !n2.isNull() ) {
		if ( n2.tagName() == "customwidget" ) {
		    QDomElement n3 = n2.firstChild().toElement();
		    QString cl;
		    WidgetDatabaseRecord *r = new WidgetDatabaseRecord;
		    while ( !n3.isNull() ) {
			if ( n3.tagName() == "class" ) {
			    cl = n3.firstChild().toText().data();
			    if ( !nofwd )
				forwardDecl << cl;
			    customWidgets.insert( cl, 0 );
			    r->name = cl;
			} else if ( n3.tagName() == "header" ) {
			    CustomInclude ci;
			    ci.header = n3.firstChild().toText().data();
			    ci.location = n3.attribute( "location", "global" );
			    r->includeFile = ci.header;
			    customWidgetIncludes.insert( cl, ci );
			}
			WidgetDatabase::append( r );
			n3 = n3.nextSibling().toElement();
		    }
		}
		n2 = n2.nextSibling().toElement();
	    }
	}
    }

    // register the object and unify its name
    objName = registerObject( objName );
    QString protector = objName.upper() + "_H";
    protector.replace( "::", "_" );
    out << "#ifndef " << protector << endl;
    out << "#define " << protector << endl;
    out << endl;
    out << "#include <qvariant.h>" << endl; // for broken HP-UX compilers

    if ( !imageMembers.isEmpty() )
	out << "#include <qpixmap.h>" << endl;

    QStringList globalIncludes, localIncludes;
    int wid = WidgetDatabase::idFromClassName( objClass );
    {
	QMap<QString, CustomInclude>::Iterator it = customWidgetIncludes.find( objClass );
	if ( it != customWidgetIncludes.end() ) {
	    if ( ( *it ).location == "global" )
		globalIncludes += (*it).header;
	    else
		localIncludes += (*it).header;
	} else {
	    globalIncludes += WidgetDatabase::includeFile( wid );
	}
    }

    nl = e.parentNode().toElement().elementsByTagName( "include" );
    for ( i = 0; i < (int) nl.length(); i++ ) {
	QDomElement n2 = nl.item(i).toElement();
	QString s = n2.firstChild().toText().data();
	if ( n2.attribute( "impldecl", "in implementation" ) == "in declaration" &&
	     n2.attribute( "location" ) != "local" ) {
	    if ( s.right( 5 ) == ".ui.h" )
		continue;
	    globalIncludes += s;
	}
    }
    for ( i = 0; i < (int) nl.length(); i++ ) {
	QDomElement n2 = nl.item(i).toElement();
	QString s = n2.firstChild().toText().data();
	if ( n2.attribute( "impldecl", "in implementation" ) == "in declaration" &&
	     n2.attribute( "location" ) == "local" &&!globalIncludes.contains( s ) ) {
	    if ( s.right( 5 ) == ".ui.h" )
		continue;
	    localIncludes += s;
	}
    }

    QStringList::Iterator it;

    globalIncludes = unique( globalIncludes );
    for ( it = globalIncludes.begin(); it != globalIncludes.end(); ++it ) {
	if ( !(*it).isEmpty() )
	    out << "#include <" << *it << ">" << endl;
    }
    localIncludes = unique( localIncludes );
    for ( it = localIncludes.begin(); it != localIncludes.end(); ++it ) {
	if ( !(*it).isEmpty() )
	    out << "#include \"" << *it << "\"" << endl;
    }
    out << endl;

    // forward declarations for child widgets and layouts
    out << "class QVBoxLayout;" << endl;
    out << "class QHBoxLayout;" << endl;
    out << "class QGridLayout;" << endl;
    out << "class QSpacerItem;" << endl;
    if ( objClass == "QMainWindow" ) {
	out << "class QAction;" << endl;
	out << "class QActionGroup;" << endl;
	out << "class QToolBar;" << endl;
	out << "class QPopupMenu;" << endl;
    }

    bool dbForm = FALSE;
    registerDatabases( e );
    dbConnections = unique( dbConnections );
    if ( dbConnections.count() )
	forwardDecl += "QSqlDatabase";
    if ( dbCursors.count() )
	forwardDecl += "QSqlCursor";
    if ( dbForms[ "(default)" ].count() )
	dbForm = TRUE;
    bool subDbForms = FALSE;
    for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
	if ( !(*it).isEmpty() && (*it) != "(default)" ) {
	    if ( dbForms[ (*it) ].count() ) {
		subDbForms = TRUE;
		break;
	    }
	}
    }
    if ( dbForm || subDbForms )
	forwardDecl += "QSqlForm";

    for ( it = tags.begin(); it != tags.end(); ++it ) {
	nl = e.parentNode().toElement().elementsByTagName( *it );
	for ( i = 1; i < (int) nl.length(); i++ ) { // begin at 1, 0 is the toplevel widget
	    QString s = getClassName( nl.item(i).toElement() );
	    if ( s == "QLayoutWidget" )
		continue; // hide qlayoutwidgets
	    if ( s == "Line" )
		s = "QFrame";
	    if ( !(nofwd && customWidgets.contains(s)) )
		forwardDecl += s;
	    if ( s.mid( 1 ) == "ListBox" || s.mid( 1 ) == "ListView" || s.mid( 1 ) == "IconView" )
		forwardDecl += "Q" + s.mid( 1 ) + "Item";
	    if ( s == "QDataTable" ) { // other convenience classes which are used in QDataTable signals, and thus should be forward-declared by uic for us
		forwardDecl += "QSqlRecord";
	    }
	}
    }

    // some typedefs, maybe
    typeDefs = unique( typeDefs );
    for ( it = typeDefs.begin(); it != typeDefs.end(); ++it ) {
	if ( !(*it).isEmpty() )
	    out << "typedef " << *it << ";" << endl;
    }

    nl = e.parentNode().toElement().elementsByTagName( "forward" );
    for ( i = 0; i < (int) nl.length(); i++ )
	forwardDecl2 << nl.item(i).toElement().firstChild().toText().data();

    nl = e.parentNode().toElement().elementsByTagName( "include" );
    for ( i = 0; i < (int) nl.length(); i++ ) {
	QDomElement n2 = nl.item(i).toElement();
	QString s = n2.firstChild().toText().data();
	if ( n2.attribute( "impldecl", "in implementation" ) == "in declaration" &&
	     n2.attribute( "location" ) != "local" )
	    globalIncludes += s;
    }
    for ( i = 0; i < (int) nl.length(); i++ ) {
	QDomElement n2 = nl.item(i).toElement();
	QString s = n2.firstChild().toText().data();
	if ( n2.attribute( "impldecl", "in implementation" ) == "in declaration" &&
	     n2.attribute( "location" ) == "local" &&!globalIncludes.contains( s ) )
	    localIncludes += s;
    }
    nl = e.parentNode().toElement().elementsByTagName( "exportmacro" );
    if ( nl.length() == 1 )
	exportMacro = nl.item( 0 ).firstChild().toText().data();

    forwardDecl = unique( forwardDecl );
    for ( it = forwardDecl.begin(); it != forwardDecl.end(); ++it ) {
	if ( !(*it).isEmpty() && (*it) != objClass ) {
	    QString forwardName = *it;
	    QStringList forwardNamespaces = QStringList::split( "::",
								forwardName );
	    forwardName = forwardNamespaces.last();
	    forwardNamespaces.remove( forwardNamespaces.fromLast() );

	    QStringList::ConstIterator ns = forwardNamespaces.begin();
	    while ( ns != forwardNamespaces.end() ) {
		out << "namespace " << *ns << " {" << endl;
		++ns;
	    }
	    out << "class " << forwardName << ";" << endl;
	    for ( int i = 0; i < (int) forwardNamespaces.count(); i++ )
		out << "}" << endl;
	}
    }

    for ( it = forwardDecl2.begin(); it != forwardDecl2.end(); ++it ) {
	QString fd = *it;
	fd = fd.stripWhiteSpace();
	if ( !fd.endsWith( ";" ) )
	    fd += ";";
	out << fd << endl;
    }

    out << endl;

    QStringList::ConstIterator ns = namespaces.begin();
    while ( ns != namespaces.end() ) {
	out << "namespace " << *ns << " {" << endl;
	++ns;
    }

    out << "class ";
    if ( !exportMacro.isEmpty() )
	out << exportMacro << " ";
    out << bareNameOfClass << " : public " << objClass << endl << "{" << endl;

    /* qmake ignore Q_OBJECT */
    out << "    Q_OBJECT" << endl;
    out << endl;
    out << "public:" << endl;

    // constructor
    if ( objClass == "QDialog" || objClass == "QWizard" ) {
	out << "    " << bareNameOfClass << "( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );" << endl;
    } else if ( objClass == "QWidget" ) {
	out << "    " << bareNameOfClass << "( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );" << endl;
    } else if ( objClass == "QMainWindow" ) {
	out << "    " << bareNameOfClass << "( QWidget* parent = 0, const char* name = 0, WFlags fl = WType_TopLevel );" << endl;
	isMainWindow = TRUE;
    } else {
	out << "    " << bareNameOfClass << "( QWidget* parent = 0, const char* name = 0 );" << endl;
    }

    // destructor
    out << "    ~" << bareNameOfClass << "();" << endl;
    out << endl;

    // children
    bool needPolish = FALSE;
    nl = e.parentNode().toElement().elementsByTagName( "widget" );
    for ( i = 1; i < (int) nl.length(); i++ ) { // start at 1, 0 is the toplevel widget
	n = nl.item(i).toElement();
	createObjectDecl( n );
	QString t = n.tagName();
 	if ( t == "vbox" || t == "hbox" || t == "grid" )
 	    createSpacerDecl( n );
	QString s = getClassName( n );
	if ( s == "QDataTable" || s == "QDataBrowser" ) {
	    if ( isFrameworkCodeGenerated( n ) )
		 needPolish = TRUE;
	}
    }

    // actions, toolbars, menus
    for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
	if ( n.tagName()  == "actions" ) {
	    for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
		createActionDecl( a );
	} else if ( n.tagName() == "toolbars" ) {
	    for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
		createToolbarDecl( a );
	} else if ( n.tagName() == "menubar" ) {
	    out << "    " << "QMenuBar *" << getObjectName( n ) << ";" << endl;
	    for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
		createMenuBarDecl( a );
	}
    }
    out << endl;

    // database connections
    dbConnections = unique( dbConnections );
    bool hadOutput = FALSE;
    for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
	if ( !(*it).isEmpty() ) {
	    // only need pointers to non-default connections
	    if ( (*it) != "(default)" && !(*it).isEmpty() ) {
		out << indent << "QSqlDatabase* " << *it << "Connection;" << endl;
		hadOutput = TRUE;
	    }
	}
    }
    if ( hadOutput )
	out << endl;

    QStringList publicSlots, protectedSlots, privateSlots;
    QStringList publicSlotTypes, protectedSlotTypes, privateSlotTypes;
    QStringList publicSlotSpecifier, protectedSlotSpecifier, privateSlotSpecifier;

    nl = e.parentNode().toElement().elementsByTagName( "slot" );
    for ( i = 0; i < (int) nl.length(); i++ ) {
	n = nl.item(i).toElement();
	if ( n.parentNode().toElement().tagName() != "slots"
	     && n.parentNode().toElement().tagName() != "connections" )
	    continue;
	if ( n.attribute( "language", "C++" ) != "C++" )
	    continue;
	QString returnType = n.attribute( "returnType", "void" );
	QString functionName = n.firstChild().toText().data().stripWhiteSpace();
	if ( functionName.endsWith( ";" ) )
	    functionName = functionName.left( functionName.length() - 1 );
	QString specifier = n.attribute( "specifier" );
	QString access = n.attribute( "access" );
	if ( access == "protected" ) {
	    protectedSlots += functionName;
	    protectedSlotTypes += returnType;
	    protectedSlotSpecifier += specifier;
	} else if ( access == "private" ) {
	    privateSlots += functionName;
	    privateSlotTypes += returnType;
	    privateSlotSpecifier += specifier;
	} else {
	    publicSlots += functionName;
	    publicSlotTypes += returnType;
	    publicSlotSpecifier += specifier;
	}
    }

    QStringList publicFuncts, protectedFuncts, privateFuncts;
    QStringList publicFunctRetTyp, protectedFunctRetTyp, privateFunctRetTyp;
    QStringList publicFunctSpec, protectedFunctSpec, privateFunctSpec;

    nl = e.parentNode().toElement().elementsByTagName( "function" );
    for ( i = 0; i < (int) nl.length(); i++ ) {
	n = nl.item( i ).toElement();
	if ( n.parentNode().toElement().tagName() != "functions" )
	    continue;
	if ( n.attribute( "language", "C++" ) != "C++" )
	    continue;
	QString returnType = n.attribute( "returnType", "void" );
	QString functionName = n.firstChild().toText().data().stripWhiteSpace();
	if ( functionName.endsWith( ";" ) )
	    functionName = functionName.left( functionName.length() - 1 );
	QString specifier = n.attribute( "specifier" );
	QString access = n.attribute( "access" );
	if ( access == "protected" ) {
	    protectedFuncts += functionName;
	    protectedFunctRetTyp += returnType;
	    protectedFunctSpec += specifier;
	} else if ( access == "private" ) {
	    privateFuncts += functionName;
	    privateFunctRetTyp += returnType;
	    privateFunctSpec += specifier;
	} else {
	    publicFuncts += functionName;
	    publicFunctRetTyp += returnType;
	    publicFunctSpec += specifier;
	}
    }

    QStringList publicVars, protectedVars, privateVars;
    nl = e.parentNode().toElement().elementsByTagName( "variable" );
    for ( i = 0; i < (int)nl.length(); i++ ) {
	n = nl.item( i ).toElement();
	// Because of compatibility the next lines have to be commented out.
	// Someday it should be uncommented.
	//if ( n.parentNode().toElement().tagName() != "variables" )
	//    continue;
	QString access = n.attribute( "access", "protected" );
	QString var = n.firstChild().toText().data().stripWhiteSpace();
	if ( !var.endsWith( ";" ) )
	    var += ";";
	if ( access == "public" )
	    publicVars += var;
	else if ( access == "private" )
	    privateVars += var;
	else
	    protectedVars += var;
    }

    if ( !publicVars.isEmpty() ) {
	for ( it = publicVars.begin(); it != publicVars.end(); ++it )
	    out << indent << *it << endl;
	out << endl;
    }
    if ( !publicFuncts.isEmpty() )
	writeFunctionsDecl( publicFuncts, publicFunctRetTyp, publicFunctSpec );

    if ( needPolish || !publicSlots.isEmpty() ) {
	out << "public slots:" << endl;
	if ( needPolish ) {
	    out << indent << "virtual void polish();" << endl;
	    out << endl;
	}
	if ( !publicSlots.isEmpty() )
	    writeFunctionsDecl( publicSlots, publicSlotTypes, publicSlotSpecifier );
    }

    // find signals
    QStringList extraSignals;
    nl = e.parentNode().toElement().elementsByTagName( "signal" );
    for ( i = 0; i < (int) nl.length(); i++ ) {
	n = nl.item( i ).toElement();
	if ( n.parentNode().toElement().tagName() != "signals"
	     && n.parentNode().toElement().tagName() != "connections" )
	    continue;
	if ( n.attribute( "language", "C++" ) != "C++" )
	    continue;
	QString sigName = n.firstChild().toText().data().stripWhiteSpace();
	if ( sigName.endsWith( ";" ) )
	    sigName = sigName.left( sigName.length() - 1 );
	extraSignals += sigName;
    }

    // create signals
    if ( !extraSignals.isEmpty() ) {
	out << "signals:" << endl;
	for ( it = extraSignals.begin(); it != extraSignals.end(); ++it )
	    out << "    void " << (*it) << ";" << endl;
	out << endl;
    }

    out << "protected:" << endl;
    if ( !protectedVars.isEmpty() ) {
	for ( it = protectedVars.begin(); it != protectedVars.end(); ++it )
	    out << indent << *it << endl;
	out << endl;
    }
    if ( !protectedFuncts.isEmpty() )
	writeFunctionsDecl( protectedFuncts, protectedFunctRetTyp, protectedFunctSpec );

    // child layouts
    registerLayouts( e );
    out << endl;

#if QT_VERSION >= 0x030900
#error Make languageChange() a virtual protected non-slot member of QWidget
#endif

    out << "protected slots:" << endl;
    out << "    virtual void languageChange();" << endl;
    if ( !protectedSlots.isEmpty() ) {
	out << endl;
	writeFunctionsDecl( protectedSlots, protectedSlotTypes, protectedSlotSpecifier );
    }
    out << endl;

    // create all private stuff
    if ( !privateFuncts.isEmpty() || !privateVars.isEmpty() || !imageMembers.isEmpty() ) {
	out << "private:" << endl;
	if ( !privateVars.isEmpty() ) {
	    for ( it = privateVars.begin(); it != privateVars.end(); ++it )
		out << indent << *it << endl;
	    out << endl;
	}
	if ( !imageMembers.isEmpty() ) {
	    out << imageMembers;
	    out << endl;
	}
	if ( !privateFuncts.isEmpty() )
	    writeFunctionsDecl( privateFuncts, privateFunctRetTyp, privateFunctSpec );
    }

    if ( !privateSlots.isEmpty() ) {
	out << "private slots:" << endl;
	writeFunctionsDecl( privateSlots, privateSlotTypes, privateSlotSpecifier );
    }

    out << "};" << endl;
    for ( i = 0; i < (int) namespaces.count(); i++ )
	out << "}" << endl;

    out << endl;
    out << "#endif // " << protector << endl;
}