SIP4 python bindings for TQt
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

form.cpp 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. /**********************************************************************
  2. ** Copyright (C) 2000 Trolltech AS. All rights reserved.
  3. **
  4. ** This file is part of TQt Designer.
  5. **
  6. ** This file may be distributed and/or modified under the terms of the
  7. ** GNU General Public License version 2 as published by the Free Software
  8. ** Foundation and appearing in the file LICENSE.GPL included in the
  9. ** packaging of this file.
  10. **
  11. ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  12. ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  13. **
  14. ** See http://www.trolltech.com/gpl/ for GPL licensing information.
  15. **
  16. ** Contact info@trolltech.com if any conditions of this licensing are
  17. ** not clear to you.
  18. **
  19. **********************************************************************/
  20. #include <stdio.h>
  21. #include "uic.h"
  22. #include "parser.h"
  23. #include "widgetdatabase.h"
  24. #include "domtool.h"
  25. #include <qstringlist.h>
  26. #include <qfile.h>
  27. #include <qfileinfo.h>
  28. #include <qregexp.h>
  29. #define NO_STATIC_COLORS
  30. #include <globaldefs.h>
  31. #if QT_VERSION < 0x030100
  32. #include <zlib.h>
  33. #endif
  34. static TQByteArray unzipXPM( TQString data, ulong& length )
  35. {
  36. #if QT_VERSION >= 0x030100
  37. const int lengthOffset = 4;
  38. int baSize = data.length() / 2 + lengthOffset;
  39. uchar *ba = new uchar[ baSize ];
  40. for ( int i = lengthOffset; i < baSize; ++i ) {
  41. char h = data[ 2 * (i-lengthOffset) ].latin1();
  42. char l = data[ 2 * (i-lengthOffset) + 1 ].latin1();
  43. uchar r = 0;
  44. if ( h <= '9' )
  45. r += h - '0';
  46. else
  47. r += h - 'a' + 10;
  48. r = r << 4;
  49. if ( l <= '9' )
  50. r += l - '0';
  51. else
  52. r += l - 'a' + 10;
  53. ba[ i ] = r;
  54. }
  55. // qUncompress() expects the first 4 bytes to be the expected length of the
  56. // uncompressed data
  57. ba[0] = ( length & 0xff000000 ) >> 24;
  58. ba[1] = ( length & 0x00ff0000 ) >> 16;
  59. ba[2] = ( length & 0x0000ff00 ) >> 8;
  60. ba[3] = ( length & 0x000000ff );
  61. TQByteArray baunzip = qUncompress( ba, baSize );
  62. delete[] ba;
  63. return baunzip;
  64. #else
  65. uchar *ba = new uchar[ data.length() / 2 ];
  66. for ( int i = 0; i < (int)data.length() / 2; ++i ) {
  67. char h = data[ 2 * i ].latin1();
  68. char l = data[ 2 * i + 1 ].latin1();
  69. uchar r = 0;
  70. if ( h <= '9' )
  71. r += h - '0';
  72. else
  73. r += h - 'a' + 10;
  74. r = r << 4;
  75. if ( l <= '9' )
  76. r += l - '0';
  77. else
  78. r += l - 'a' + 10;
  79. ba[ i ] = r;
  80. }
  81. // I'm not sure this makes sense. Why couldn't the compressed data be
  82. // less than 20% of the original data? Maybe it's enough to trust the
  83. // `length' passed as an argument. Quoting the zlib header:
  84. // Upon entry, destLen is the total size of the destination
  85. // buffer, which must be large enough to hold the entire
  86. // uncompressed data. (The size of the uncompressed data must
  87. // have been saved previously by the compressor and transmitted
  88. // to the decompressor by some mechanism outside the scope of
  89. // this compression library.)
  90. // Which is the role of `length'. On the other hand this could prevent
  91. // crashes in some cases of slightly corrupt UIC files.
  92. if ( length < data.length() * 5 )
  93. length = data.length() * 5;
  94. TQByteArray baunzip( length );
  95. ::uncompress( (uchar*) baunzip.data(), &length, ba, data.length()/2 );
  96. delete[] ba;
  97. return baunzip;
  98. #endif
  99. }
  100. /*!
  101. Creates an implementation ( cpp-file ) for the form given in \a e
  102. \sa createFormDecl(), createObjectImpl()
  103. */
  104. void Uic::createFormImpl( const TQDomElement &e )
  105. {
  106. TQDomElement n;
  107. TQDomNodeList nl;
  108. int i;
  109. TQString objClass = getClassName( e );
  110. if ( objClass.isEmpty() )
  111. return;
  112. TQString objName = getObjectName( e );
  113. // generate local and local includes required
  114. TQStringList globalIncludes;
  115. TQStringList::Iterator it;
  116. TQStringList sqlClasses;
  117. TQStringList axwidgets, databrowsers;
  118. TQMap<TQString, CustomInclude> customWidgetIncludes;
  119. TQMap<TQString, TQString> functionImpls;
  120. // find additional slots and functions
  121. TQStringList extraSlots;
  122. TQStringList extraSlotTypes;
  123. nl = e.parentNode().toElement().elementsByTagName( "slot" );
  124. for ( i = 0; i < (int) nl.length(); i++ ) {
  125. n = nl.item(i).toElement();
  126. if ( n.parentNode().toElement().tagName() != "slots"
  127. && n.parentNode().toElement().tagName() != "connections" )
  128. continue;
  129. if ( n.attribute( "language", "C++" ) != "C++" )
  130. continue;
  131. TQString slotName = n.firstChild().toText().data().stripWhiteSpace();
  132. if ( slotName.endsWith( ";" ) )
  133. slotName = slotName.left( slotName.length() - 1 );
  134. extraSlots += Parser::cleanArgs(slotName);
  135. extraSlotTypes += n.attribute( "returnType", "void" );
  136. }
  137. for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
  138. if ( n.tagName() == "functions" ) { // compatibility
  139. for ( TQDomElement n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() ) {
  140. if ( n2.tagName() == "function" ) {
  141. TQString fname = n2.attribute( "name" );
  142. fname = Parser::cleanArgs( fname );
  143. functionImpls.insert( fname, n2.firstChild().toText().data() );
  144. }
  145. }
  146. }
  147. }
  148. // additional includes (local or global ) and forward declaractions
  149. nl = e.parentNode().toElement().elementsByTagName( "include" );
  150. for ( i = 0; i < (int) nl.length(); i++ ) {
  151. TQDomElement n2 = nl.item(i).toElement();
  152. TQString s = n2.firstChild().toText().data();
  153. if ( n2.attribute( "location" ) != "local" ) {
  154. if ( s.right( 5 ) == ".ui.h" && !TQFile::exists( s ) )
  155. continue;
  156. if ( n2.attribute( "impldecl", "in implementation" ) != "in implementation" )
  157. continue;
  158. globalIncludes += s;
  159. }
  160. }
  161. // do the local includes afterwards, since global includes have priority on clashes
  162. TQFileInfo fi(fileName);
  163. for ( i = 0; i < (int) nl.length(); i++ ) {
  164. TQDomElement n2 = nl.item(i).toElement();
  165. TQString s = n2.firstChild().toText().data();
  166. if ( n2.attribute( "location" ) == "local" &&!globalIncludes.contains( s ) ) {
  167. if ( s.right( 5 ) != ".ui.h" )
  168. continue;
  169. if ( !TQFile::exists( s ) )
  170. {
  171. s = fi.dirPath() + "/" + s;
  172. if ( !TQFile::exists( s ) )
  173. continue;
  174. }
  175. if ( TQFile::exists( s ) )
  176. {
  177. TQFile f(s);
  178. f.open(IO_ReadOnly);
  179. TQTextStream headerStream(&f);
  180. TQString line;
  181. TQString functionText;
  182. TQString functionName;
  183. TQRegExp rx("void .*::(.*\\(.*\\))");
  184. int pos, inFunction = 0;
  185. while (line = headerStream.readLine())
  186. {
  187. pos = rx.search(line);
  188. if (pos > -1)
  189. {
  190. if (inFunction)
  191. functionImpls.insert(Parser::cleanArgs(functionName),functionText);
  192. functionName = rx.cap(1);
  193. functionText = "";
  194. inFunction = 1;
  195. }
  196. functionText += line + "\n";
  197. }
  198. if (inFunction)
  199. functionImpls.insert(Parser::cleanArgs(functionName),functionText);
  200. }
  201. }
  202. }
  203. // additional custom widget headers
  204. nl = e.parentNode().toElement().elementsByTagName( "header" );
  205. for ( i = 0; i < (int) nl.length(); i++ ) {
  206. TQDomElement n2 = nl.item(i).toElement();
  207. TQString s = n2.firstChild().toText().data();
  208. if ( n2.attribute( "location" ) != "local" )
  209. globalIncludes += s;
  210. }
  211. // includes for child widgets
  212. for ( it = tags.begin(); it != tags.end(); ++it ) {
  213. nl = e.parentNode().toElement().elementsByTagName( *it );
  214. for ( i = 1; i < (int) nl.length(); i++ ) { // start at 1, 0 is the toplevel widget
  215. TQString name = getClassName( nl.item(i).toElement() );
  216. if ( name == "Spacer" ) {
  217. globalIncludes += "qlayout.h";
  218. globalIncludes += "qapplication.h";
  219. continue;
  220. }
  221. if ( name.mid( 1 ) == "ListView" )
  222. globalIncludes += "qheader.h";
  223. else if ( name == "TQAxWidget" )
  224. axwidgets += getObjectName(nl.item(i).toElement());
  225. else if ( name == "TQDataBrowser" )
  226. databrowsers += getObjectName(nl.item(i).toElement());
  227. if ( name != objClass ) {
  228. int wid = WidgetDatabase::idFromClassName( name );
  229. TQMap<TQString, CustomInclude>::Iterator it = customWidgetIncludes.find( name );
  230. if ( it == customWidgetIncludes.end() )
  231. globalIncludes += WidgetDatabase::includeFile( wid );
  232. }
  233. }
  234. }
  235. if (globalIncludes.findIndex("qtable.h") >= 0)
  236. out << indent << "from qttable import TQTable" << endl;
  237. if (!axwidgets.empty())
  238. out << indent << "from qtaxcontainer import TQAxWidget" << endl;
  239. if (globalIncludes.findIndex("qextscintilla.h") >= 0)
  240. out << indent << "from qtext import QextScintilla" << endl;
  241. registerDatabases( e );
  242. dbConnections = unique( dbConnections );
  243. if ( dbConnections.count() )
  244. sqlClasses += "TQSqlDatabase";
  245. if ( dbCursors.count() )
  246. sqlClasses += "TQSqlCursor";
  247. bool dbForm = FALSE;
  248. if ( dbForms[ "(default)" ].count() )
  249. dbForm = TRUE;
  250. bool subDbForms = FALSE;
  251. for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
  252. if ( !(*it).isEmpty() && (*it) != "(default)" ) {
  253. if ( dbForms[ (*it) ].count() ) {
  254. subDbForms = TRUE;
  255. break;
  256. }
  257. }
  258. }
  259. if ( dbForm || subDbForms ) {
  260. sqlClasses += "TQSqlForm";
  261. sqlClasses += "TQSqlRecord";
  262. }
  263. if (globalIncludes.findIndex("qdatatable.h") >= 0)
  264. sqlClasses += "TQDataTable";
  265. if (globalIncludes.findIndex("qtableview.h") >= 0)
  266. sqlClasses += "TQTableView";
  267. if (globalIncludes.findIndex("qdatabrowser.h") >= 0)
  268. sqlClasses += "TQDataBrowser";
  269. if (globalIncludes.findIndex("qdataview.h") >= 0)
  270. sqlClasses += "TQDataView";
  271. if ( !sqlClasses.empty() ) {
  272. out << indent << "from qtsql import";
  273. const char *sep = " ";
  274. for ( it = sqlClasses.begin(); it != sqlClasses.end(); ++it ) {
  275. out << sep << (*it);
  276. sep = ", ";
  277. }
  278. out << endl;
  279. }
  280. // Add any code from the comments.
  281. if (!pyCode.isEmpty())
  282. out << pyCode;
  283. out << endl;
  284. // find out what images are required
  285. TQStringList requiredImages;
  286. static const char *imgTags[] = { "pixmap", "iconset", 0 };
  287. for ( i = 0; imgTags[i] != 0; i++ ) {
  288. nl = e.parentNode().toElement().elementsByTagName( imgTags[i] );
  289. for ( int j = 0; j < (int) nl.length(); j++ ) {
  290. TQDomNode nn = nl.item(j);
  291. while ( nn.parentNode() != e.parentNode() )
  292. nn = nn.parentNode();
  293. if ( nn.nodeName() != "customwidgets" )
  294. requiredImages += nl.item(j).firstChild().toText().data();
  295. }
  296. }
  297. // register the object and unify its name
  298. objName = registerObject( objName );
  299. TQStringList images;
  300. TQStringList xpmImages;
  301. if ( pixmapLoaderFunction.isEmpty() && !externPixmaps ) {
  302. // create images
  303. for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
  304. if ( n.tagName() == "images" ) {
  305. nl = n.elementsByTagName( "image" );
  306. for ( i = 0; i < (int) nl.length(); i++ ) {
  307. TQString img = registerObject( nl.item(i).toElement().attribute( "name" ) );
  308. if ( !requiredImages.contains( img ) )
  309. continue;
  310. TQDomElement tmp = nl.item(i).firstChild().toElement();
  311. if ( tmp.tagName() != "data" )
  312. continue;
  313. TQString format = tmp.attribute("format", "PNG" );
  314. TQString data = tmp.firstChild().toText().data();
  315. if ( format == "XPM.GZ" ) {
  316. xpmImages += img;
  317. ulong length = tmp.attribute("length").toULong();
  318. TQByteArray baunzip = unzipXPM( data, length );
  319. length = baunzip.size();
  320. // shouldn't we test the initial `length' against the
  321. // resulting `length' to catch corrupt UIC files?
  322. int a = 0;
  323. out << indent << img << "_data = [" << endl;
  324. while ( baunzip[a] != '\"' )
  325. a++;
  326. for ( ; a < (int) length; a++ )
  327. {
  328. char ch;
  329. if ((ch = baunzip[a]) == '}')
  330. {
  331. out << endl << "]";
  332. break;
  333. }
  334. out << ch;
  335. }
  336. out << endl;
  337. } else {
  338. images += img;
  339. out << indent << img << "_data = \\" << endl;
  340. ++indent;
  341. out << indent << "\"";
  342. int a ;
  343. for ( a = 0; a < (int) (data.length()/2)-1; a++ ) {
  344. out << "\\x" << TQString(data[2*a]) << TQString(data[2*a+1]);
  345. if ( a % 12 == 11 )
  346. out << "\" \\" << endl << indent << "\"";
  347. }
  348. out << "\\x" << TQString(data[2*a]) << TQString(data[2*a+1]) << "\"" << endl;
  349. --indent;
  350. }
  351. }
  352. }
  353. }
  354. out << endl;
  355. } else if ( externPixmaps ) {
  356. #if QT_VERSION >= 0x030100
  357. pixmapLoaderFunction = "TQPixmap.fromMimeSource";
  358. #else
  359. out << indent << "def uic_load_pixmap_" << objName << "(name):" << endl;
  360. ++indent;
  361. out << indent << "pix = TQPixmap()" << endl;
  362. out << indent << "m = TQMimeSourceFactory.defaultFactory().data(name)" << endl;
  363. out << endl;
  364. out << indent << "if m:" << endl;
  365. ++indent;
  366. out << indent << "TQImageDrag.decode(m,pix)" << endl;
  367. --indent;
  368. out << endl;
  369. out << indent << "return pix" << endl;
  370. --indent;
  371. out << endl;
  372. out << endl;
  373. pixmapLoaderFunction = "uic_load_pixmap_" + objName;
  374. #endif
  375. }
  376. // constructor(s)
  377. out << indent << "class " << nameOfClass << "(" << objClass << "):" << endl;
  378. ++indent;
  379. if ( objClass == "TQDialog" || objClass == "TQWizard" ) {
  380. out << indent << "def __init__(self,parent = None,name = None,modal = 0,fl = 0):" << endl;
  381. ++indent;
  382. out << indent << objClass << ".__init__(self,parent,name,modal,fl)" << endl;
  383. } else if ( objClass == "TQWidget" ) {
  384. out << indent << "def __init__(self,parent = None,name = None,fl = 0):" << endl;
  385. ++indent;
  386. out << indent << objClass << ".__init__(self,parent,name,fl)" << endl;
  387. } else if ( objClass == "TQMainWindow" ) {
  388. out << indent << "def __init__(self,parent = None,name = None,fl = 0):" << endl;
  389. ++indent;
  390. out << indent << objClass << ".__init__(self,parent,name,fl)" << endl;
  391. out << indent << "self.statusBar()" << endl;
  392. isMainWindow = TRUE;
  393. } else {
  394. out << indent << "def __init__(self,parent = None,name = None):" << endl;
  395. ++indent;
  396. out << indent << objClass << ".__init__(self,parent,name)" << endl;
  397. }
  398. out << endl;
  399. // create pixmaps for all images
  400. if ( !images.isEmpty() ) {
  401. TQStringList::Iterator it;
  402. for ( it = images.begin(); it != images.end(); ++it ) {
  403. out << indent << "self." << (*it) << " = TQPixmap()" << endl;
  404. out << indent << "self." << (*it) << ".loadFromData(" << (*it) << "_data,\"PNG\")" << endl;
  405. }
  406. }
  407. // create pixmaps for all images
  408. if ( !xpmImages.isEmpty() ) {
  409. for ( it = xpmImages.begin(); it != xpmImages.end(); ++it ) {
  410. out << indent << "self." << (*it) << " = TQPixmap(" << (*it) << "_data)" << endl;
  411. }
  412. out << endl;
  413. }
  414. // set the properties
  415. TQSize geometry( 0, 0 );
  416. for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
  417. if ( n.tagName() == "property" ) {
  418. bool stdset = stdsetdef;
  419. if ( n.hasAttribute( "stdset" ) )
  420. stdset = toBool( n.attribute( "stdset" ) );
  421. TQString prop = n.attribute("name");
  422. TQDomElement n2 = n.firstChild().toElement();
  423. TQString value = setObjectProperty( objClass, TQString::null, prop, n2, stdset );
  424. if ( value.isEmpty() )
  425. continue;
  426. if ( prop == "geometry" && n2.tagName() == "rect") {
  427. TQDomElement n3 = n2.firstChild().toElement();
  428. while ( !n3.isNull() ) {
  429. if ( n3.tagName() == "width" )
  430. geometry.setWidth( n3.firstChild().toText().data().toInt() );
  431. else if ( n3.tagName() == "height" )
  432. geometry.setHeight( n3.firstChild().toText().data().toInt() );
  433. n3 = n3.nextSibling().toElement();
  434. }
  435. } else {
  436. TQString call;
  437. if ( stdset )
  438. call = "self." + mkStdSet( prop ) + "(" + value + ")";
  439. else
  440. call = "self.setProperty(\"" + prop + "\",TQVariant(" + value + "))";
  441. if ( n2.tagName() == "string" ) {
  442. trout << trindent << call << endl;
  443. } else if ( prop == "name" ) {
  444. out << indent << "if not name:" << endl;
  445. ++indent;
  446. out << indent << call << endl;
  447. --indent;
  448. out << endl;
  449. } else {
  450. out << indent << call << endl;
  451. }
  452. }
  453. }
  454. }
  455. out << endl;
  456. // create all children, some forms have special requirements
  457. if ( objClass == "TQWizard" ) {
  458. for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
  459. if ( tags.contains( n.tagName() ) ) {
  460. TQString page = createObjectImpl( n, objClass, "self" );
  461. TQString comment;
  462. TQString label = DomTool::readAttribute( n, "title", "", comment ).toString();
  463. out << indent << "self.addPage(" << page << ",TQString(\"\"))" << endl;
  464. trout << trindent << "self.setTitle(" << page << ","<< trcall( label, comment ) << ")" << endl;
  465. TQVariant def( FALSE, 0 );
  466. if ( DomTool::hasAttribute( n, "backEnabled" ) )
  467. out << indent << "self.setBackEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "backEnabled", def).toBool() ) << ")" << endl;
  468. if ( DomTool::hasAttribute( n, "nextEnabled" ) )
  469. out << indent << "self.setNextEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "nextEnabled", def).toBool() ) << ")" << endl;
  470. if ( DomTool::hasAttribute( n, "finishEnabled" ) )
  471. out << indent << "self.setFinishEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "finishEnabled", def).toBool() ) << ")" << endl;
  472. if ( DomTool::hasAttribute( n, "helpEnabled" ) )
  473. out << indent << "self.setHelpEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "helpEnabled", def).toBool() ) << ")" << endl;
  474. if ( DomTool::hasAttribute( n, "finish" ) )
  475. out << indent << "self.setFinish( " << page << "," << mkBool( DomTool::readAttribute( n, "finish", def).toBool() ) << ")" << endl;
  476. }
  477. }
  478. } else { // standard widgets
  479. for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
  480. if ( tags.contains( n.tagName() ) )
  481. createObjectImpl( n, objName, "self" );
  482. }
  483. }
  484. // database support
  485. dbConnections = unique( dbConnections );
  486. if ( dbConnections.count() )
  487. out << endl;
  488. for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
  489. if ( !(*it).isEmpty() && (*it) != "(default)") {
  490. out << indent << "self." << (*it) << "Connection = TQSqlDatabase.database(\"" <<(*it) << "\")" << endl;
  491. }
  492. }
  493. nl = e.parentNode().toElement().elementsByTagName( "widget" );
  494. for ( i = 1; i < (int) nl.length(); i++ ) { // start at 1, 0 is the toplevel widget
  495. n = nl.item(i).toElement();
  496. TQString s = getClassName( n );
  497. if ( (dbForm || subDbForms) && (s == "TQDataBrowser" || s == "TQDataView") ) {
  498. TQString objName = getObjectName( n );
  499. TQString tab = getDatabaseInfo( n, "table" );
  500. TQString con = getDatabaseInfo( n, "connection" );
  501. out << indent << objName << "Form = TQSqlForm(self,\"" << objName << "Form\")" << endl;
  502. TQDomElement n2;
  503. for ( n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() )
  504. createFormImpl( n2, objName, con, tab );
  505. out << indent << "self." << objName << ".setForm(" << objName << "Form)" << endl;
  506. }
  507. }
  508. // actions, toolbars, menubar
  509. bool needEndl = FALSE;
  510. for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
  511. if ( n.tagName() == "actions" ) {
  512. if ( !needEndl )
  513. out << endl;
  514. createActionImpl( n.firstChild().toElement(), "self" );
  515. needEndl = TRUE;
  516. }
  517. }
  518. if ( needEndl )
  519. out << endl;
  520. needEndl = FALSE;
  521. for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
  522. if ( n.tagName() == "toolbars" ) {
  523. if ( !needEndl )
  524. out << endl;
  525. createToolbarImpl( n, objClass, objName );
  526. needEndl = TRUE;
  527. }
  528. }
  529. if ( needEndl )
  530. out << endl;
  531. needEndl = FALSE;
  532. for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
  533. if ( n.tagName() == "menubar" ) {
  534. if ( !needEndl )
  535. out << endl;
  536. createMenuBarImpl( n, objClass, objName );
  537. needEndl = TRUE;
  538. }
  539. }
  540. if ( needEndl )
  541. out << endl;
  542. out << endl;
  543. out << indent << "self.languageChange()" << endl;
  544. out << endl;
  545. // take minimumSizeHint() into account, for height-for-width widgets
  546. if ( !geometry.isNull() ) {
  547. out << indent << "self.resize(TQSize(" << geometry.width() << ","
  548. << geometry.height() <<").expandedTo(self.minimumSizeHint()))" << endl;
  549. out << indent << "self.clearWState(TQt.WState_Polished)" << endl;
  550. }
  551. for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
  552. if ( n.tagName() == "connections" ) {
  553. // setup signals and slots connections
  554. out << endl;
  555. nl = n.elementsByTagName( "connection" );
  556. for ( i = 0; i < (int) nl.length(); i++ ) {
  557. TQString sender, receiver, signal, slot;
  558. for ( TQDomElement n2 = nl.item(i).firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() ) {
  559. if ( n2.tagName() == "sender" )
  560. sender = n2.firstChild().toText().data();
  561. else if ( n2.tagName() == "receiver" )
  562. receiver = n2.firstChild().toText().data();
  563. else if ( n2.tagName() == "signal" )
  564. signal = n2.firstChild().toText().data();
  565. else if ( n2.tagName() == "slot" )
  566. slot = n2.firstChild().toText().data();
  567. }
  568. if ( sender.isEmpty() ||
  569. receiver.isEmpty() ||
  570. signal.isEmpty() ||
  571. slot.isEmpty() )
  572. continue;
  573. if ( sender[0] == '<' ||
  574. receiver[0] == '<' ||
  575. signal[0] == '<' ||
  576. slot[0] == '<' )
  577. continue;
  578. sender = registeredName( sender );
  579. receiver = registeredName( receiver );
  580. // translate formwindow name to "self"
  581. if ( sender == objName )
  582. sender = "self";
  583. else
  584. sender = "self." + sender;
  585. bool isaxwidget = (axwidgets.findIndex(receiver) >= 0);
  586. bool isdatabrowser = (databrowsers.findIndex(receiver) >= 0);
  587. if ( receiver == objName )
  588. receiver = "self";
  589. else
  590. receiver = "self." + receiver;
  591. out << indent << "self.connect(" << sender
  592. << ",SIGNAL(\"" << signal << "\")," << receiver;
  593. // Normally we never use the SLOT() macro in case the
  594. // connection is to a method of a Python custom widget. The
  595. // exception is if the receiver is a TQAxWidget where it must be
  596. // used because the slots are dynamic.
  597. if (isaxwidget)
  598. out << ",SLOT(\"" << slot << "\")";
  599. else
  600. {
  601. TQString mname = slot.left(slot.find('('));
  602. // Rename slots that have different names in PyTQt.
  603. if (isdatabrowser && mname == "del")
  604. mname = "delOnCursor";
  605. out << "." << mname;
  606. }
  607. out << ")" << endl;
  608. }
  609. } else if ( n.tagName() == "tabstops" ) {
  610. // setup tab order
  611. out << endl;
  612. TQString lastName;
  613. TQDomElement n2 = n.firstChild().toElement();
  614. while ( !n2.isNull() ) {
  615. if ( n2.tagName() == "tabstop" ) {
  616. TQString name = n2.firstChild().toText().data();
  617. name = registeredName( name );
  618. if ( !lastName.isEmpty() )
  619. out << indent << "self.setTabOrder(self." << lastName << ",self." << name << ")" << endl;
  620. lastName = name;
  621. }
  622. n2 = n2.nextSibling().toElement();
  623. }
  624. }
  625. }
  626. // buddies
  627. bool firstBuddy = TRUE;
  628. for ( TQValueList<Buddy>::Iterator buddy = buddies.begin(); buddy != buddies.end(); ++buddy ) {
  629. if ( isObjectRegistered( (*buddy).buddy ) ) {
  630. if ( firstBuddy ) {
  631. out << endl;
  632. }
  633. out << indent << "self." << (*buddy).key << ".setBuddy(self." << registeredName( (*buddy).buddy ) << ")" << endl;
  634. firstBuddy = FALSE;
  635. }
  636. }
  637. if ( extraSlots.find( "init()" ) != extraSlots.end() )
  638. out << endl << indent << "self.init()" << endl;
  639. // end of constructor
  640. --indent;
  641. // destructor
  642. if ( extraSlots.find( "destroy()" ) != extraSlots.end() ) {
  643. out << endl;
  644. out << indent << "def __del__(self):" << endl;
  645. ++indent;
  646. out << indent << "self.destroy()" << endl;
  647. --indent;
  648. }
  649. // handle application events if required
  650. bool needFontEventHandler = FALSE;
  651. bool needSqlTableEventHandler = FALSE;
  652. bool needSqlDataBrowserEventHandler = FALSE;
  653. nl = e.elementsByTagName( "widget" );
  654. for ( i = 0; i < (int) nl.length(); i++ ) {
  655. if ( !DomTool::propertiesOfType( nl.item(i).toElement() , "font" ).isEmpty() )
  656. needFontEventHandler = TRUE;
  657. TQString s = getClassName( nl.item(i).toElement() );
  658. if ( s == "TQDataTable" || s == "TQDataBrowser" ) {
  659. if ( !isFrameworkCodeGenerated( nl.item(i).toElement() ) )
  660. continue;
  661. if ( s == "TQDataTable" )
  662. needSqlTableEventHandler = TRUE;
  663. if ( s == "TQDataBrowser" )
  664. needSqlDataBrowserEventHandler = TRUE;
  665. }
  666. if ( needFontEventHandler && needSqlTableEventHandler && needSqlDataBrowserEventHandler )
  667. break;
  668. }
  669. if ( needFontEventHandler && FALSE ) {
  670. // indent = "\t"; // increase indentation for if-clause below
  671. out << "/* " << endl;
  672. out << " * Main event handler. Reimplemented to handle" << endl;
  673. out << " * application font changes";
  674. out << " */" << endl;
  675. out << "bool " << nameOfClass << "::event( TQEvent* ev )" << endl;
  676. out << "{" << endl;
  677. out << " bool ret = " << objClass << "::event( ev ); " << endl;
  678. if ( needFontEventHandler ) {
  679. ++indent;
  680. out << " if ( ev->type() == TQEvent::ApplicationFontChange ) {" << endl;
  681. for ( i = 0; i < (int) nl.length(); i++ ) {
  682. n = nl.item(i).toElement();
  683. TQStringList list = DomTool::propertiesOfType( n, "font" );
  684. for ( it = list.begin(); it != list.end(); ++it )
  685. createExclusiveProperty( n, *it );
  686. }
  687. out << " }" << endl;
  688. --indent;
  689. }
  690. out << "}" << endl;
  691. out << endl;
  692. }
  693. if ( needSqlTableEventHandler || needSqlDataBrowserEventHandler ) {
  694. out << endl;
  695. out << indent << "# Widget polish. Reimplemented to handle default data" << endl;
  696. if ( needSqlTableEventHandler )
  697. out << indent << "# table initialization." << endl;
  698. if ( needSqlDataBrowserEventHandler )
  699. out << indent << "# browser initialization." << endl;
  700. out << indent << "def polish(self):" << endl;
  701. ++indent;
  702. if ( needSqlTableEventHandler ) {
  703. for ( i = 0; i < (int) nl.length(); i++ ) {
  704. TQString s = getClassName( nl.item(i).toElement() );
  705. if ( s == "TQDataTable" ) {
  706. n = nl.item(i).toElement();
  707. TQString c = getObjectName( n );
  708. TQString conn = getDatabaseInfo( n, "connection" );
  709. TQString tab = getDatabaseInfo( n, "table" );
  710. if ( !( conn.isEmpty() || tab.isEmpty() || !isFrameworkCodeGenerated( nl.item(i).toElement() ) ) ) {
  711. out << indent << "if self." << c << ":" << endl;
  712. ++indent;
  713. out << indent << "cursor = self." << c << ".sqlCursor()" << endl;
  714. out << endl;
  715. out << indent << "if not cursor:" << endl;
  716. ++indent;
  717. if ( conn == "(default)" )
  718. out << indent << "cursor = TQSqlCursor(\"" << tab << "\")" << endl;
  719. else
  720. out << indent << "cursor = TQSqlCursor(\"" << tab << "\",1,self." << conn << "Connection)" << endl;
  721. out << indent << "if self." << c << ".isReadOnly():" << endl;
  722. ++indent;
  723. out << indent << "cursor.setMode(TQSqlCursor.ReadOnly)" << endl;
  724. --indent;
  725. out << indent << "self." << c << ".setSqlCursor(cursor,0,1)" << endl;
  726. --indent;
  727. out << endl;
  728. out << indent << "if not cursor.isActive():" << endl;
  729. ++indent;
  730. out << indent << "self." << c << ".refresh(TQDataTable.RefreshAll)" << endl;
  731. --indent;
  732. --indent;
  733. }
  734. }
  735. }
  736. }
  737. if ( needSqlDataBrowserEventHandler ) {
  738. nl = e.elementsByTagName( "widget" );
  739. for ( i = 0; i < (int) nl.length(); i++ ) {
  740. TQString s = getClassName( nl.item(i).toElement() );
  741. if ( s == "TQDataBrowser" ) {
  742. TQString obj = getObjectName( nl.item(i).toElement() );
  743. TQString tab = getDatabaseInfo( nl.item(i).toElement(),
  744. "table" );
  745. TQString conn = getDatabaseInfo( nl.item(i).toElement(),
  746. "connection" );
  747. if ( !(tab.isEmpty() || !isFrameworkCodeGenerated( nl.item(i).toElement() ) ) ) {
  748. out << indent << "if self." << obj << ":" << endl;
  749. ++indent;
  750. out << indent << "if not self." << obj << ".sqlCursor():" << endl;
  751. ++indent;
  752. if ( conn == "(default)" )
  753. out << indent << "cursor = TQSqlCursor(\"" << tab << "\")" << endl;
  754. else
  755. out << indent << "cursor = TQSqlCursor(\"" << tab << "\",1,self." << conn << "Connection)" << endl;
  756. out << indent << "self." << obj << ".setSqlCursor(cursor,1)" << endl;
  757. out << indent << "self." << obj << ".refresh()" << endl;
  758. out << indent << "self." << obj << ".first()" << endl;
  759. --indent;
  760. --indent;
  761. }
  762. }
  763. }
  764. }
  765. out << indent << objClass << ".polish(self)" << endl;
  766. --indent;
  767. }
  768. out << endl;
  769. out << endl;
  770. out << indent << "def languageChange(self):" << endl;
  771. uint old = indent.setIndent(0);
  772. out << languageChangeBody << endl;
  773. indent.setIndent(old);
  774. // create stubs for additional slots if necessary
  775. if ( !extraSlots.isEmpty() && writeFunctImpl ) {
  776. TQStringList::ConstIterator cit;
  777. for ( cit = extraSlots.begin(); cit != extraSlots.end(); ++cit ) {
  778. pySlot(cit);
  779. bool createWarning = TRUE;
  780. TQString fname = Parser::cleanArgs( *cit );
  781. TQMap<TQString, TQString>::Iterator fit = functionImpls.find( fname );
  782. if ( fit != functionImpls.end() ) {
  783. int begin = (*fit).find( "{" );
  784. TQString body = (*fit).mid( begin + 1, (*fit).findRev( "}" ) - begin - 1 );
  785. createWarning = body.simplifyWhiteSpace().isEmpty();
  786. if ( !createWarning )
  787. {
  788. ++indent;
  789. TQString formatted_body = body.replace(TQRegExp("\n"), TQString("\n") + TQString(indent));
  790. out << formatted_body << endl;
  791. --indent;
  792. }
  793. }
  794. if ( createWarning ) {
  795. out << endl;
  796. ++indent;
  797. if ( *cit != "init()" && *cit != "destroy()" )
  798. out << indent << "print \"" << nameOfClass << "." << (*cit) << ": Not implemented yet\"" << endl;
  799. else
  800. out << indent << "pass" << endl;
  801. --indent;
  802. }
  803. }
  804. }
  805. --indent;
  806. }
  807. /*! Creates form support implementation code for the widgets given
  808. in \a e.
  809. Traverses recursively over all children.
  810. */
  811. void Uic::createFormImpl( const TQDomElement& e, const TQString& form, const TQString& connection, const TQString& table )
  812. {
  813. if ( e.tagName() == "widget" &&
  814. e.attribute( "class" ) != "TQDataTable" ) {
  815. TQString field = getDatabaseInfo( e, "field" );
  816. if ( !field.isEmpty() ) {
  817. if ( isWidgetInTable( e, connection, table ) )
  818. out << indent << form << "Form.insert(self." << getObjectName( e ) << "," << fixString( field ) << ")" << endl;
  819. }
  820. }
  821. TQDomElement n;
  822. for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
  823. createFormImpl( n, form, connection, table );
  824. }
  825. }
  826. // Generate a Python slot definition.
  827. void Uic::pySlot(TQStringList::ConstIterator &it)
  828. {
  829. out << endl;
  830. int astart = (*it).find('(');
  831. out << indent << "def " << (*it).left(astart) << "(self";
  832. // We don't reproduce the argument names (if any) because we would have to
  833. // remove the types - too complicated for the moment, so we just count them
  834. // and give them names based on their position.
  835. TQString args = (*it).mid(astart + 1,(*it).find(')') - astart - 1).stripWhiteSpace();
  836. if (!args.isEmpty()) {
  837. int nrargs = args.contains(',') + 1;
  838. for (int i = 0; i < nrargs; ++i)
  839. out << ",a" << i;
  840. }
  841. out << "):";
  842. }