src/tools/uic3/form.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the tools applications of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "ui3reader.h"
       
    43 #include "parser.h"
       
    44 #include "domtool.h"
       
    45 #include "globaldefs.h"
       
    46 
       
    47 // uic4
       
    48 #include "uic.h"
       
    49 #include "ui4.h"
       
    50 #include "driver.h"
       
    51 #include "option.h"
       
    52 
       
    53 #include <QStringList>
       
    54 #include <QFile>
       
    55 #include <QFileInfo>
       
    56 #include <QDir>
       
    57 #include <QRegExp>
       
    58 #include <QtDebug>
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 QByteArray combinePath(const char *infile, const char *outfile)
       
    63 {
       
    64     QFileInfo inFileInfo(QDir::current(), QFile::decodeName(infile));
       
    65     QFileInfo outFileInfo(QDir::current(), QFile::decodeName(outfile));
       
    66     int numCommonComponents = 0;
       
    67 
       
    68     QStringList inSplitted = inFileInfo.dir().canonicalPath().split(QLatin1Char('/'));
       
    69     QStringList outSplitted = outFileInfo.dir().canonicalPath().split(QLatin1Char('/'));
       
    70 
       
    71     while (!inSplitted.isEmpty() && !outSplitted.isEmpty() &&
       
    72             inSplitted.first() == outSplitted.first()) {
       
    73         inSplitted.erase(inSplitted.begin());
       
    74         outSplitted.erase(outSplitted.begin());
       
    75         numCommonComponents++;
       
    76     }
       
    77 
       
    78     if (numCommonComponents < 2) {
       
    79         /*
       
    80           The paths don't have the same drive, or they don't have the
       
    81           same root directory. Use an absolute path.
       
    82         */
       
    83         return QFile::encodeName(inFileInfo.absoluteFilePath());
       
    84     } else {
       
    85         /*
       
    86           The paths have something in common. Use a path relative to
       
    87           the output file.
       
    88         */
       
    89         while (!outSplitted.isEmpty()) {
       
    90             outSplitted.erase(outSplitted.begin());
       
    91             inSplitted.prepend(QLatin1String(".."));
       
    92         }
       
    93         inSplitted.append(inFileInfo.fileName());
       
    94         return QFile::encodeName(inSplitted.join(QLatin1String("/")));
       
    95     }
       
    96 }
       
    97 
       
    98 /*!
       
    99   Creates a declaration (header file) for the form given in \a e
       
   100 
       
   101   \sa createFormImpl()
       
   102 */
       
   103 void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes)
       
   104 {
       
   105     QDomElement body = e;
       
   106 
       
   107     QDomElement n;
       
   108     QDomNodeList nl;
       
   109     int i;
       
   110     QString objClass = getClassName(e);
       
   111     if (objClass.isEmpty())
       
   112         return;
       
   113     QString objName = getObjectName(e);
       
   114 
       
   115     QStringList typeDefs;
       
   116 
       
   117     QMap<QString, CustomInclude> customWidgetIncludes;
       
   118 
       
   119     /*
       
   120       We are generating a few QImage members that are not strictly
       
   121       necessary in some cases. Ideally, we would use requiredImage,
       
   122       which is computed elsewhere, to keep the generated .h and .cpp
       
   123       files synchronized.
       
   124     */
       
   125 
       
   126     // at first the images
       
   127     QMap<QString, int> customWidgets;
       
   128     QStringList forwardDecl;
       
   129     QStringList forwardDecl2;
       
   130     for (n = e; !n.isNull(); n = n.nextSibling().toElement()) {
       
   131         if (n.tagName().toLower() == QLatin1String("customwidgets")) {
       
   132             QDomElement n2 = n.firstChild().toElement();
       
   133             while (!n2.isNull()) {
       
   134                 if (n2.tagName().toLower() == QLatin1String("customwidget")) {
       
   135                     QDomElement n3 = n2.firstChild().toElement();
       
   136                     QString cl;
       
   137                     while (!n3.isNull()) {
       
   138                         QString tagName = n3.tagName().toLower();
       
   139                         if (tagName == QLatin1String("class")) {
       
   140                             cl = n3.firstChild().toText().data();
       
   141                             if (!nofwd)
       
   142                                 forwardDecl << cl;
       
   143                             customWidgets.insert(cl, 0);
       
   144                         } else if (tagName == QLatin1String("header")) {
       
   145                             CustomInclude ci;
       
   146                             ci.header = n3.firstChild().toText().data();
       
   147                             ci.location = n3.attribute(QLatin1String("location"), QLatin1String("global"));
       
   148                             if (!ci.header.isEmpty())
       
   149                                 forwardDecl.removeAll(cl);
       
   150                             customWidgetIncludes.insert(cl, ci);
       
   151                         }
       
   152                         n3 = n3.nextSibling().toElement();
       
   153                     }
       
   154                 }
       
   155                 n2 = n2.nextSibling().toElement();
       
   156             }
       
   157         }
       
   158     }
       
   159 
       
   160     // register the object and unify its name
       
   161     objName = registerObject(objName);
       
   162     QString protector = objName.toUpper() + QLatin1String("_H");
       
   163     protector.replace(QLatin1String("::"), QLatin1String("_"));
       
   164     out << "#ifndef " << protector << endl;
       
   165     out << "#define " << protector << endl;
       
   166     out << endl;
       
   167 
       
   168     out << "#include <qvariant.h>" << endl; // for broken HP-UX compilers
       
   169 
       
   170     QStringList globalIncludes, localIncludes;
       
   171 
       
   172     {
       
   173         QMap<QString, CustomInclude>::Iterator it = customWidgetIncludes.find(objClass);
       
   174         if (it != customWidgetIncludes.end()) {
       
   175             if ((*it).location == QLatin1String("global"))
       
   176                 globalIncludes += (*it).header;
       
   177             else
       
   178                 localIncludes += (*it).header;
       
   179         }
       
   180     }
       
   181 
       
   182     QStringList::ConstIterator it;
       
   183 
       
   184     globalIncludes = unique(globalIncludes);
       
   185     for (it = globalIncludes.constBegin(); it != globalIncludes.constEnd(); ++it) {
       
   186         if (!(*it).isEmpty()) {
       
   187             QString header = fixHeaderName(*it);
       
   188             out << "#include <" << header << '>' << endl;
       
   189         }
       
   190     }
       
   191     localIncludes = unique(localIncludes);
       
   192     for (it = localIncludes.constBegin(); it != localIncludes.constEnd(); ++it) {
       
   193         if (!(*it).isEmpty()) {
       
   194             QString header = fixHeaderName(*it);
       
   195             out << "#include \"" << header << '\"' << endl;
       
   196         }
       
   197     }
       
   198     out << endl;
       
   199 
       
   200     bool dbForm = false;
       
   201     registerDatabases(e);
       
   202     dbConnections = unique(dbConnections);
       
   203     if (dbForms[QLatin1String("(default)")].count())
       
   204         dbForm = true;
       
   205     bool subDbForms = false;
       
   206     for (it = dbConnections.constBegin(); it != dbConnections.constEnd(); ++it) {
       
   207         if (!(*it).isEmpty() && (*it) != QLatin1String("(default)")) {
       
   208             if (dbForms[(*it)].count()) {
       
   209                 subDbForms = true;
       
   210                 break;
       
   211             }
       
   212         }
       
   213     }
       
   214 
       
   215     // some typedefs, maybe
       
   216     typeDefs = unique(typeDefs);
       
   217     for (it = typeDefs.constBegin(); it != typeDefs.constEnd(); ++it) {
       
   218         if (!(*it).isEmpty())
       
   219             out << "typedef " << *it << ';' << endl;
       
   220     }
       
   221 
       
   222     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("forward"));
       
   223     for (i = 0; i < (int) nl.length(); i++)
       
   224         forwardDecl2 << fixDeclaration(nl.item(i).toElement().firstChild().toText().data());
       
   225 
       
   226     forwardDecl = unique(forwardDecl);
       
   227     for (it = forwardDecl.constBegin(); it != forwardDecl.constEnd(); ++it) {
       
   228         if (!(*it).isEmpty() && (*it) != objClass) {
       
   229             QString forwardName = *it;
       
   230             QStringList forwardNamespaces = forwardName.split(QLatin1String("::"));
       
   231             forwardName = forwardNamespaces.last();
       
   232             forwardNamespaces.removeAt(forwardNamespaces.size()-1);
       
   233 
       
   234             QStringList::ConstIterator ns = forwardNamespaces.constBegin();
       
   235             while (ns != forwardNamespaces.constEnd()) {
       
   236                 out << "namespace " << *ns << " {" << endl;
       
   237                 ++ns;
       
   238             }
       
   239             out << "class " << forwardName << ';' << endl;
       
   240             for (int i = 0; i < (int) forwardNamespaces.count(); i++)
       
   241                 out << '}' << endl;
       
   242         }
       
   243     }
       
   244 
       
   245     for (it = forwardDecl2.constBegin(); it != forwardDecl2.constEnd(); ++it) {
       
   246         QString fd = *it;
       
   247         fd = fd.trimmed();
       
   248         if (!fd.endsWith(QLatin1Char(';')))
       
   249             fd += QLatin1Char(';');
       
   250         out << fd << endl;
       
   251     }
       
   252 
       
   253     out << endl;
       
   254 
       
   255     Driver d;
       
   256     d.option().headerProtection = false;
       
   257     d.option().copyrightHeader = false;
       
   258     d.option().extractImages = m_extractImages;
       
   259     d.option().qrcOutputFile = m_qrcOutputFile;
       
   260     d.option().implicitIncludes = implicitIncludes;
       
   261     if (trmacro.size())
       
   262         d.option().translateFunction = trmacro;
       
   263     DomUI *ui = generateUi4(e, implicitIncludes);
       
   264     d.uic(fileName, ui, &out);
       
   265     delete ui;
       
   266 
       
   267     createWrapperDeclContents(e);
       
   268 
       
   269     out << "#endif // " << protector << endl;
       
   270 }
       
   271 
       
   272 void Ui3Reader::createWrapperDecl(const QDomElement &e, const QString &convertedUiFile)
       
   273 {
       
   274     QString objName = getObjectName(e);
       
   275 
       
   276     objName = registerObject(objName);
       
   277     QString protector = objName.toUpper() + QLatin1String("_H");
       
   278     protector.replace(QLatin1String("::"), QLatin1String("_"));
       
   279     out << "#ifndef " << protector << endl;
       
   280     out << "#define " << protector << endl;
       
   281     out << endl;
       
   282     out << "#include \"" << convertedUiFile << '\"' << endl;
       
   283 
       
   284     createWrapperDeclContents(e);
       
   285     out << endl;
       
   286     out << "#endif // " << protector << endl;
       
   287 }
       
   288 
       
   289 void Ui3Reader::createWrapperDeclContents(const QDomElement &e)
       
   290 {
       
   291     QString objClass = getClassName(e);
       
   292     if (objClass.isEmpty())
       
   293         return;
       
   294 
       
   295     QDomNodeList nl;
       
   296     QString exportMacro;
       
   297     int i;
       
   298     QDomElement n;
       
   299     QStringList::ConstIterator it;
       
   300     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("exportmacro"));
       
   301     if (nl.length() == 1)
       
   302         exportMacro = nl.item(0).firstChild().toText().data();
       
   303 
       
   304     QStringList::ConstIterator ns = namespaces.constBegin();
       
   305     while (ns != namespaces.constEnd()) {
       
   306         out << "namespace " << *ns << " {" << endl;
       
   307         ++ns;
       
   308     }
       
   309 
       
   310     out << "class ";
       
   311     if (!exportMacro.isEmpty())
       
   312         out << exportMacro << ' ';
       
   313     out << bareNameOfClass << " : public " << objClass << ", public Ui::" << bareNameOfClass << endl << '{' << endl;
       
   314 
       
   315     /* qmake ignore Q_OBJECT */
       
   316     out << "    Q_OBJECT" << endl;
       
   317     out << endl;
       
   318     out << "public:" << endl;
       
   319 
       
   320     // constructor
       
   321     if (objClass == QLatin1String("QDialog") || objClass == QLatin1String("QWizard")) {
       
   322         out << "    " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WindowFlags fl = 0);" << endl;
       
   323     } else if (objClass == QLatin1String("QWidget")) {
       
   324         out << "    " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = 0);" << endl;
       
   325     } else if (objClass == QLatin1String("QMainWindow") || objClass == QLatin1String("Q3MainWindow")) {
       
   326         out << "    " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = Qt::WType_TopLevel);" << endl;
       
   327         isMainWindow = true;
       
   328     } else {
       
   329         out << "    " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0);" << endl;
       
   330     }
       
   331 
       
   332     // destructor
       
   333     out << "    ~" << bareNameOfClass << "();" << endl;
       
   334     out << endl;
       
   335 
       
   336     // database connections
       
   337     dbConnections = unique(dbConnections);
       
   338     bool hadOutput = false;
       
   339     for (it = dbConnections.constBegin(); it != dbConnections.constEnd(); ++it) {
       
   340         if (!(*it).isEmpty()) {
       
   341             // only need pointers to non-default connections
       
   342             if ((*it) != QLatin1String("(default)") && !(*it).isEmpty()) {
       
   343                 out << indent << "QSqlDatabase* " << *it << "Connection;" << endl;
       
   344                 hadOutput = true;
       
   345             }
       
   346         }
       
   347     }
       
   348     if (hadOutput)
       
   349         out << endl;
       
   350 
       
   351     QStringList publicSlots, protectedSlots, privateSlots;
       
   352     QStringList publicSlotTypes, protectedSlotTypes, privateSlotTypes;
       
   353     QStringList publicSlotSpecifier, protectedSlotSpecifier, privateSlotSpecifier;
       
   354 
       
   355     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("slot"));
       
   356     for (i = 0; i < (int) nl.length(); i++) {
       
   357         n = nl.item(i).toElement();
       
   358         if (n.parentNode().toElement().tagName() != QLatin1String("slots")
       
   359              && n.parentNode().toElement().tagName() != QLatin1String("connections"))
       
   360             continue;
       
   361         if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++"))
       
   362             continue;
       
   363         QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void"));
       
   364         QString functionName = n.firstChild().toText().data().trimmed();
       
   365         if (functionName.endsWith(QLatin1Char(';')))
       
   366             functionName.chop(1);
       
   367         QString specifier = n.attribute(QLatin1String("specifier"));
       
   368         QString access = n.attribute(QLatin1String("access"));
       
   369         if (access == QLatin1String(QLatin1String("protected"))) {
       
   370             protectedSlots += functionName;
       
   371             protectedSlotTypes += returnType;
       
   372             protectedSlotSpecifier += specifier;
       
   373         } else if (access == QLatin1String("private")) {
       
   374             privateSlots += functionName;
       
   375             privateSlotTypes += returnType;
       
   376             privateSlotSpecifier += specifier;
       
   377         } else {
       
   378             publicSlots += functionName;
       
   379             publicSlotTypes += returnType;
       
   380             publicSlotSpecifier += specifier;
       
   381         }
       
   382     }
       
   383 
       
   384     QStringList publicFuncts, protectedFuncts, privateFuncts;
       
   385     QStringList publicFunctRetTyp, protectedFunctRetTyp, privateFunctRetTyp;
       
   386     QStringList publicFunctSpec, protectedFunctSpec, privateFunctSpec;
       
   387 
       
   388     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("function"));
       
   389     for (i = 0; i < (int) nl.length(); i++) {
       
   390         n = nl.item(i).toElement();
       
   391         if (n.parentNode().toElement().tagName() != QLatin1String("functions"))
       
   392             continue;
       
   393         if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++"))
       
   394             continue;
       
   395         QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void"));
       
   396         QString functionName = n.firstChild().toText().data().trimmed();
       
   397         if (functionName.endsWith(QLatin1Char(';')))
       
   398             functionName.chop(1);
       
   399         QString specifier = n.attribute(QLatin1String("specifier"));
       
   400         QString access = n.attribute(QLatin1String("access"));
       
   401         if (access == QLatin1String("protected")) {
       
   402             protectedFuncts += functionName;
       
   403             protectedFunctRetTyp += returnType;
       
   404             protectedFunctSpec += specifier;
       
   405         } else if (access == QLatin1String("private")) {
       
   406             privateFuncts += functionName;
       
   407             privateFunctRetTyp += returnType;
       
   408             privateFunctSpec += specifier;
       
   409         } else {
       
   410             publicFuncts += functionName;
       
   411             publicFunctRetTyp += returnType;
       
   412             publicFunctSpec += specifier;
       
   413         }
       
   414     }
       
   415 
       
   416     QStringList publicVars, protectedVars, privateVars;
       
   417     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("variable"));
       
   418     for (i = 0; i < (int)nl.length(); i++) {
       
   419         n = nl.item(i).toElement();
       
   420         // Because of compatibility the next lines have to be commented out.
       
   421         // Someday it should be uncommented.
       
   422         //if (n.parentNode().toElement().tagName() != QLatin1String("variables"))
       
   423         //    continue;
       
   424         QString access = n.attribute(QLatin1String("access"), QLatin1String("protected"));
       
   425         QString var = fixDeclaration(n.firstChild().toText().data().trimmed());
       
   426         if (!var.endsWith(QLatin1Char(';')))
       
   427             var += QLatin1Char(';');
       
   428         if (access == QLatin1String("public"))
       
   429             publicVars += var;
       
   430         else if (access == QLatin1String("private"))
       
   431             privateVars += var;
       
   432         else
       
   433             protectedVars += var;
       
   434     }
       
   435 
       
   436     if (!publicVars.isEmpty()) {
       
   437         for (it = publicVars.constBegin(); it != publicVars.constEnd(); ++it)
       
   438             out << indent << *it << endl;
       
   439         out << endl;
       
   440     }
       
   441     if (!publicFuncts.isEmpty())
       
   442         writeFunctionsDecl(publicFuncts, publicFunctRetTyp, publicFunctSpec);
       
   443 
       
   444     if (!publicSlots.isEmpty()) {
       
   445         out << "public slots:" << endl;
       
   446         if (!publicSlots.isEmpty())
       
   447             writeFunctionsDecl(publicSlots, publicSlotTypes, publicSlotSpecifier);
       
   448     }
       
   449 
       
   450     // find signals
       
   451     QStringList extraSignals;
       
   452     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("signal"));
       
   453     for (i = 0; i < (int) nl.length(); i++) {
       
   454         n = nl.item(i).toElement();
       
   455         if (n.parentNode().toElement().tagName() != QLatin1String("signals")
       
   456              && n.parentNode().toElement().tagName() != QLatin1String("connections"))
       
   457             continue;
       
   458         if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++"))
       
   459             continue;
       
   460         QString sigName = n.firstChild().toText().data().trimmed();
       
   461         if (sigName.endsWith(QLatin1Char(';')))
       
   462             sigName = sigName.left(sigName.length() - 1);
       
   463         extraSignals += fixDeclaration(sigName);
       
   464     }
       
   465 
       
   466     // create signals
       
   467     if (!extraSignals.isEmpty()) {
       
   468         out << "signals:" << endl;
       
   469         for (it = extraSignals.constBegin(); it != extraSignals.constEnd(); ++it)
       
   470             out << "    void " << (*it) << ';' << endl;
       
   471         out << endl;
       
   472     }
       
   473 
       
   474     if (!protectedVars.isEmpty()) {
       
   475         out << "protected:" << endl;
       
   476         for (it = protectedVars.constBegin(); it != protectedVars.constEnd(); ++it)
       
   477             out << indent << *it << endl;
       
   478         out << endl;
       
   479     }
       
   480 
       
   481     if (!protectedFuncts.isEmpty()) {
       
   482         if (protectedVars.isEmpty())
       
   483             out << "protected:" << endl;
       
   484 
       
   485         writeFunctionsDecl(protectedFuncts, protectedFunctRetTyp, protectedFunctSpec);
       
   486     }
       
   487 
       
   488     out << "protected slots:" << endl;
       
   489     out << "    virtual void languageChange();" << endl;
       
   490 
       
   491     if (!protectedSlots.isEmpty()) {
       
   492         out << endl;
       
   493         writeFunctionsDecl(protectedSlots, protectedSlotTypes, protectedSlotSpecifier);
       
   494     }
       
   495     out << endl;
       
   496 
       
   497     // create all private stuff
       
   498     if (!privateFuncts.isEmpty() || !privateVars.isEmpty()) {
       
   499         out << "private:" << endl;
       
   500         if (!privateVars.isEmpty()) {
       
   501             for (it = privateVars.constBegin(); it != privateVars.constEnd(); ++it)
       
   502                 out << indent << *it << endl;
       
   503             out << endl;
       
   504         }
       
   505         if (!privateFuncts.isEmpty())
       
   506             writeFunctionsDecl(privateFuncts, privateFunctRetTyp, privateFunctSpec);
       
   507     }
       
   508 
       
   509     if (!privateSlots.isEmpty()) {
       
   510         out << "private slots:" << endl;
       
   511         writeFunctionsDecl(privateSlots, privateSlotTypes, privateSlotSpecifier);
       
   512     }
       
   513 
       
   514     out << "};" << endl;
       
   515     for (i = 0; i < (int) namespaces.count(); i++)
       
   516         out << '}' << endl;
       
   517 
       
   518     out << endl;
       
   519 }
       
   520 
       
   521 void Ui3Reader::writeFunctionsDecl(const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst)
       
   522 {
       
   523     QStringList::ConstIterator it, it2, it3;
       
   524     for (it = fuLst.begin(), it2 = typLst.begin(), it3 = specLst.begin();
       
   525           it != fuLst.end(); ++it, ++it2, ++it3) {
       
   526         QString signature = *it;
       
   527         QString specifier;
       
   528         QString pure;
       
   529         QString type = *it2;
       
   530         if (type.isEmpty())
       
   531             type = QLatin1String("void");
       
   532         if (*it3 == QLatin1String("static")) {
       
   533             specifier = QLatin1String("static ");
       
   534         } else {
       
   535             if (*it3 != QLatin1String("non virtual") && *it3 != QLatin1String("nonVirtual"))
       
   536                 specifier = QLatin1String("virtual ");
       
   537             if (*it3 == QLatin1String("pure virtual") || *it3 == QLatin1String("pureVirtual"))
       
   538                 pure = QLatin1String(" = 0");
       
   539         }
       
   540         type.replace(QLatin1String(">>"), QLatin1String("> >"));
       
   541         if (!signature.contains(QLatin1String("operator")))
       
   542             signature.replace(QLatin1String(">>"), QLatin1String("> >"));
       
   543 
       
   544         signature = fixDeclaration(signature);
       
   545         type = fixType(type);
       
   546         out << "    " << specifier << type << ' ' << signature << pure << ';' << endl;
       
   547     }
       
   548     out << endl;
       
   549 }
       
   550 
       
   551 /*!
       
   552   Creates an implementation (cpp-file) for the form given in \a e.
       
   553 
       
   554   \sa createFormDecl(), createObjectImpl()
       
   555  */
       
   556 void Ui3Reader::createFormImpl(const QDomElement &e)
       
   557 {
       
   558     QDomElement n;
       
   559     QDomNodeList nl;
       
   560     int i;
       
   561     QString objClass = getClassName(e);
       
   562     if (objClass.isEmpty())
       
   563         return;
       
   564     QString objName = getObjectName(e);
       
   565 
       
   566     // generate local and local includes required
       
   567     QStringList globalIncludes, localIncludes;
       
   568     QStringList::Iterator it;
       
   569 
       
   570     QMap<QString, CustomInclude> customWidgetIncludes;
       
   571 
       
   572     // find additional slots and functions
       
   573     QStringList extraFuncts;
       
   574     QStringList extraFunctTyp;
       
   575     QStringList extraFunctSpecifier;
       
   576 
       
   577     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("slot"));
       
   578     for (i = 0; i < (int) nl.length(); i++) {
       
   579         n = nl.item(i).toElement();
       
   580         if (n.parentNode().toElement().tagName() != QLatin1String("slots")
       
   581              && n.parentNode().toElement().tagName() != QLatin1String("connections"))
       
   582             continue;
       
   583         if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++"))
       
   584             continue;
       
   585         QString functionName = n.firstChild().toText().data().trimmed();
       
   586         if (functionName.endsWith(QLatin1Char(';')))
       
   587             functionName.chop(1);
       
   588         extraFuncts += functionName;
       
   589         extraFunctTyp += n.attribute(QLatin1String("returnType"), QLatin1String("void"));
       
   590         extraFunctSpecifier += n.attribute(QLatin1String("specifier"), QLatin1String("virtual"));
       
   591     }
       
   592 
       
   593     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("function"));
       
   594     for (i = 0; i < (int) nl.length(); i++) {
       
   595         n = nl.item(i).toElement();
       
   596         if (n.parentNode().toElement().tagName() != QLatin1String("functions"))
       
   597             continue;
       
   598         if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++"))
       
   599             continue;
       
   600         QString functionName = n.firstChild().toText().data().trimmed();
       
   601         if (functionName.endsWith(QLatin1Char(';')))
       
   602             functionName.chop(1);
       
   603         extraFuncts += functionName;
       
   604         extraFunctTyp += n.attribute(QLatin1String("returnType"), QLatin1String("void"));
       
   605         extraFunctSpecifier += n.attribute(QLatin1String("specifier"), QLatin1String("virtual"));
       
   606     }
       
   607 
       
   608     // additional includes (local or global) and forward declaractions
       
   609     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("include"));
       
   610     for (i = 0; i < (int) nl.length(); i++) {
       
   611         QDomElement n2 = nl.item(i).toElement();
       
   612         QString s = n2.firstChild().toText().data();
       
   613         if (n2.attribute(QLatin1String("location")) != QLatin1String("local")) {
       
   614             if (s.right(5) == QLatin1String(".ui.h") && !QFile::exists(s))
       
   615                 continue;
       
   616             if (n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) != QLatin1String("in implementation"))
       
   617                 continue;
       
   618             globalIncludes += s;
       
   619         }
       
   620     }
       
   621 
       
   622     registerDatabases(e);
       
   623     dbConnections = unique(dbConnections);
       
   624     bool dbForm = false;
       
   625     if (dbForms[QLatin1String("(default)")].count())
       
   626         dbForm = true;
       
   627     bool subDbForms = false;
       
   628     for (it = dbConnections.begin(); it != dbConnections.end(); ++it) {
       
   629         if (!(*it).isEmpty()  && (*it) != QLatin1String("(default)")) {
       
   630             if (dbForms[(*it)].count()) {
       
   631                 subDbForms = true;
       
   632                 break;
       
   633             }
       
   634         }
       
   635     }
       
   636 
       
   637     // do the local includes afterwards, since global includes have priority on clashes
       
   638     for (i = 0; i < (int) nl.length(); i++) {
       
   639         QDomElement n2 = nl.item(i).toElement();
       
   640         QString s = n2.firstChild().toText().data();
       
   641         if (n2.attribute(QLatin1String("location")) == QLatin1String("local") && !globalIncludes.contains(s)) {
       
   642             if (s.right(5) == QLatin1String(".ui.h") && !QFile::exists(s))
       
   643                 continue;
       
   644             if (n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) != QLatin1String("in implementation"))
       
   645                 continue;
       
   646             localIncludes += s;
       
   647         }
       
   648     }
       
   649 
       
   650     // additional custom widget headers
       
   651     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("header"));
       
   652     for (i = 0; i < (int) nl.length(); i++) {
       
   653         QDomElement n2 = nl.item(i).toElement();
       
   654         QString s = n2.firstChild().toText().data();
       
   655         if (n2.attribute(QLatin1String("location")) != QLatin1String("local"))
       
   656             globalIncludes += s;
       
   657         else
       
   658             localIncludes += s;
       
   659     }
       
   660 
       
   661     out << "#include <qvariant.h>" << endl; // first for gcc 2.7.2
       
   662 
       
   663     globalIncludes = unique(globalIncludes);
       
   664     for (it = globalIncludes.begin(); it != globalIncludes.end(); ++it) {
       
   665         if (!(*it).isEmpty())
       
   666             out << "#include <" << fixHeaderName(*it) << '>' << endl;
       
   667     }
       
   668 
       
   669     if (externPixmaps) {
       
   670         out << "#include <qimage.h>" << endl;
       
   671         out << "#include <qpixmap.h>" << endl << endl;
       
   672     }
       
   673 
       
   674     /*
       
   675       Put local includes after all global includes
       
   676     */
       
   677     localIncludes = unique(localIncludes);
       
   678     for (it = localIncludes.begin(); it != localIncludes.end(); ++it) {
       
   679         if (!(*it).isEmpty() && *it != QFileInfo(fileName + QLatin1String(".h")).fileName())
       
   680             out << "#include \"" << fixHeaderName(*it) << '\"' << endl;
       
   681     }
       
   682 
       
   683     QString uiDotH = fileName + QLatin1String(".h");
       
   684     if (QFile::exists(uiDotH)) {
       
   685         if (!outputFileName.isEmpty())
       
   686             uiDotH = QString::fromUtf8(combinePath(uiDotH.ascii(), outputFileName.ascii()));
       
   687         out << "#include \"" << uiDotH << '\"' << endl;
       
   688         writeFunctImpl = false;
       
   689     }
       
   690 
       
   691     // register the object and unify its name
       
   692     objName = registerObject(objName);
       
   693 
       
   694     if (externPixmaps) {
       
   695         pixmapLoaderFunction = QLatin1String("QPixmap::fromMimeSource");
       
   696     }
       
   697 
       
   698     // constructor
       
   699     if (objClass == QLatin1String("QDialog") || objClass == QLatin1String("QWizard")) {
       
   700         out << "/*" << endl;
       
   701         out << " *  Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl;
       
   702         out << " *  name 'name' and widget flags set to 'f'." << endl;
       
   703         out << " *" << endl;
       
   704         out << " *  The " << objClass.mid(1).toLower() << " will by default be modeless, unless you set 'modal' to" << endl;
       
   705         out << " *  true to construct a modal " << objClass.mid(1).toLower() << '.' << endl;
       
   706         out << " */" << endl;
       
   707         out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl)" << endl;
       
   708         out << "    : " << objClass << "(parent, name, modal, fl)";
       
   709     } else if (objClass == QLatin1String("QWidget"))  {
       
   710         out << "/*" << endl;
       
   711         out << " *  Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl;
       
   712         out << " *  name 'name' and widget flags set to 'f'." << endl;
       
   713         out << " */" << endl;
       
   714         out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, Qt::WindowFlags fl)" << endl;
       
   715         out << "    : " << objClass << "(parent, name, fl)";
       
   716     } else if (objClass == QLatin1String("QMainWindow") || objClass == QLatin1String("Q3MainWindow")) {
       
   717         out << "/*" << endl;
       
   718         out << " *  Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl;
       
   719         out << " *  name 'name' and widget flags set to 'f'." << endl;
       
   720         out << " *" << endl;
       
   721         out << " */" << endl;
       
   722         out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, Qt::WindowFlags fl)" << endl;
       
   723         out << "    : " << objClass << "(parent, name, fl)";
       
   724         isMainWindow = true;
       
   725     } else {
       
   726         out << "/*" << endl;
       
   727         out << " *  Constructs a " << nameOfClass << " which is a child of 'parent', with the" << endl;
       
   728         out << " *  name 'name'.' " << endl;
       
   729         out << " */" << endl;
       
   730         out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name)" << endl;
       
   731         out << "    : " << objClass << "(parent, name)";
       
   732     }
       
   733 
       
   734     out << endl;
       
   735 
       
   736     out << '{' << endl;
       
   737 
       
   738 //
       
   739 // setup the gui
       
   740 //
       
   741     out << indent << "setupUi(this);" << endl << endl;
       
   742 
       
   743 
       
   744     if (isMainWindow)
       
   745         out << indent << "(void)statusBar();" << endl;
       
   746 
       
   747     // database support
       
   748     dbConnections = unique(dbConnections);
       
   749     if (dbConnections.count())
       
   750         out << endl;
       
   751     for (it = dbConnections.begin(); it != dbConnections.end(); ++it) {
       
   752         if (!(*it).isEmpty() && (*it) != QLatin1String("(default)")) {
       
   753             out << indent << (*it) << "Connection = QSqlDatabase::database(\"" <<(*it) << "\");" << endl;
       
   754         }
       
   755     }
       
   756 
       
   757     nl = e.parentNode().toElement().elementsByTagName(QLatin1String("widget"));
       
   758     for (i = 1; i < (int) nl.length(); i++) { // start at 1, 0 is the toplevel widget
       
   759         n = nl.item(i).toElement();
       
   760         QString s = getClassName(n);
       
   761         if ((dbForm || subDbForms) && (s == QLatin1String("QDataBrowser") || s == QLatin1String("QDataView"))) {
       
   762             QString objName = getObjectName(n);
       
   763             QString tab = getDatabaseInfo(n, QLatin1String("table"));
       
   764             QString con = getDatabaseInfo(n, QLatin1String("connection"));
       
   765             out << indent << "QSqlForm* " << objName << "Form = new QSqlForm(this);" << endl;
       
   766             out << indent << objName << "Form->setObjectName(\"" << objName << "Form\");" << endl;
       
   767             QDomElement n2;
       
   768             for (n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement())
       
   769                 createFormImpl(n2, objName, con, tab);
       
   770             out << indent << objName << "->setForm(" << objName << "Form);" << endl;
       
   771         }
       
   772     }
       
   773 
       
   774     if (extraFuncts.contains(QLatin1String("init()")))
       
   775         out << indent << "init();" << endl;
       
   776 
       
   777     // end of constructor
       
   778     out << '}' << endl;
       
   779     out << endl;
       
   780 
       
   781     // destructor
       
   782     out << "/*" << endl;
       
   783     out << " *  Destroys the object and frees any allocated resources" << endl;
       
   784     out << " */" << endl;
       
   785     out << nameOfClass << "::~" << bareNameOfClass << "()" << endl;
       
   786     out << '{' << endl;
       
   787     if (extraFuncts.contains(QLatin1String("destroy()")))
       
   788         out << indent << "destroy();" << endl;
       
   789     out << indent << "// no need to delete child widgets, Qt does it all for us" << endl;
       
   790     out << '}' << endl;
       
   791     out << endl;
       
   792 
       
   793     // handle application events if required
       
   794     bool needFontEventHandler = false;
       
   795     bool needSqlTableEventHandler = false;
       
   796     bool needSqlDataBrowserEventHandler = false;
       
   797     nl = e.elementsByTagName(QLatin1String("widget"));
       
   798     for (i = 0; i < (int) nl.length(); i++) {
       
   799         if (!DomTool::propertiesOfType(nl.item(i).toElement() , QLatin1String("font")).isEmpty())
       
   800             needFontEventHandler = true;
       
   801         QString s = getClassName(nl.item(i).toElement());
       
   802         if (s == QLatin1String("QDataTable") || s == QLatin1String("QDataBrowser")) {
       
   803             if (!isFrameworkCodeGenerated(nl.item(i).toElement()))
       
   804                  continue;
       
   805             if (s == QLatin1String("QDataTable"))
       
   806                 needSqlTableEventHandler = true;
       
   807             if (s == QLatin1String("QDataBrowser"))
       
   808                 needSqlDataBrowserEventHandler = true;
       
   809         }
       
   810         if (needFontEventHandler && needSqlTableEventHandler && needSqlDataBrowserEventHandler)
       
   811             break;
       
   812     }
       
   813 
       
   814     out << "/*" << endl;
       
   815     out << " *  Sets the strings of the subwidgets using the current" << endl;
       
   816     out << " *  language." << endl;
       
   817     out << " */" << endl;
       
   818     out << "void " << nameOfClass << "::languageChange()" << endl;
       
   819     out << '{' << endl;
       
   820     out << "    retranslateUi(this);" << endl;
       
   821     out << '}' << endl;
       
   822     out << endl;
       
   823 
       
   824     // create stubs for additional slots if necessary
       
   825     if (!extraFuncts.isEmpty() && writeFunctImpl) {
       
   826         it = extraFuncts.begin();
       
   827         QStringList::Iterator it2 = extraFunctTyp.begin();
       
   828         QStringList::Iterator it3 = extraFunctSpecifier.begin();
       
   829         while (it != extraFuncts.end()) {
       
   830             QString type = fixDeclaration(*it2);
       
   831             if (type.isEmpty())
       
   832                 type = QLatin1String("void");
       
   833             type = type.simplified();
       
   834             QString fname = fixDeclaration(Parser::cleanArgs(*it));
       
   835             if (!(*it3).startsWith(QLatin1String("pure"))) { // "pure virtual" or "pureVirtual"
       
   836                 out << type << ' ' << nameOfClass << "::" << fname << endl;
       
   837                 out << '{' << endl;
       
   838                 if (*it != QLatin1String("init()") && *it != QLatin1String("destroy()")) {
       
   839                     QRegExp numeric(QLatin1String("^(?:signed|unsigned|u?char|u?short|u?int"
       
   840                                      "|u?long|Q_U?INT(?:8|16|32)|Q_U?LONG|float"
       
   841                                      "|double)$"));
       
   842                     QString retVal;
       
   843 
       
   844                     /*
       
   845                       We return some kind of dummy value to shut the
       
   846                       compiler up.
       
   847 
       
   848                       1.  If the type is 'void', we return nothing.
       
   849 
       
   850                       2.  If the type is 'bool', we return 'false'.
       
   851 
       
   852                       3.  If the type is 'unsigned long' or
       
   853                           'quint16' or 'double' or similar, we
       
   854                           return '0'.
       
   855 
       
   856                       4.  If the type is 'Foo *', we return '0'.
       
   857 
       
   858                       5.  If the type is 'Foo &', we create a static
       
   859                           variable of type 'Foo' and return it.
       
   860 
       
   861                       6.  If the type is 'Foo', we assume there's a
       
   862                           default constructor and use it.
       
   863                     */
       
   864                     if (type != QLatin1String("void")) {
       
   865                         QStringList toks = type.split(QLatin1String(" "));
       
   866                         bool isBasicNumericType =
       
   867                                 (toks.filter(numeric).count() == toks.count());
       
   868 
       
   869                         if (type == QLatin1String("bool")) {
       
   870                             retVal = QLatin1String("false");
       
   871                         } else if (isBasicNumericType || type.endsWith(QLatin1Char('*'))) {
       
   872                             retVal = QLatin1String("0");
       
   873                         } else if (type.endsWith(QLatin1Char('&'))) {
       
   874                             do {
       
   875                                 type.chop(1);
       
   876                             } while (type.endsWith(QLatin1Char(' ')));
       
   877                             retVal = QLatin1String("uic_temp_var");
       
   878                             out << indent << "static " << type << ' ' << retVal << ';' << endl;
       
   879                         } else {
       
   880                             retVal = type + QLatin1String("()");
       
   881                         }
       
   882                     }
       
   883 
       
   884                     out << indent << "qWarning(\"" << nameOfClass << "::" << fname << ": Not implemented yet\");" << endl;
       
   885                     if (!retVal.isEmpty())
       
   886                         out << indent << "return " << retVal << ';' << endl;
       
   887                 }
       
   888                 out << '}' << endl;
       
   889                 out << endl;
       
   890             }
       
   891             ++it;
       
   892             ++it2;
       
   893             ++it3;
       
   894         }
       
   895     }
       
   896 }
       
   897 
       
   898 
       
   899 /*! Creates form support implementation code for the widgets given
       
   900   in \a e.
       
   901 
       
   902   Traverses recursively over all children.
       
   903  */
       
   904 
       
   905 void Ui3Reader::createFormImpl(const QDomElement& e, const QString& form, const QString& connection, const QString& table)
       
   906 {
       
   907     if (e.tagName() == QLatin1String("widget")
       
   908             && e.attribute(QLatin1String("class")) != QLatin1String("QDataTable")) {
       
   909         QString field = getDatabaseInfo(e, QLatin1String("field"));
       
   910         if (!field.isEmpty()) {
       
   911             if (isWidgetInTable(e, connection, table))
       
   912                 out << indent << form << "Form->insert(" << getObjectName(e) << ", " << fixString(field) << ");" << endl;
       
   913         }
       
   914     }
       
   915     QDomElement n;
       
   916     for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
       
   917         createFormImpl(n, form, connection, table);
       
   918     }
       
   919 }
       
   920 
       
   921 QT_END_NAMESPACE