source: trunk/tools/designer/designer/project.cpp@ 197

Last change on this file since 197 was 197, checked in by rudi, 14 years ago

Added QtDesigner

File size: 43.1 KB
Line 
1/**********************************************************************
2** Copyright (C) 2005-2007 Trolltech ASA. All rights reserved.
3**
4**1 This file is part of Qt 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** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
12** licenses may use this file in accordance with the Qt Commercial License
13** Agreement provided with the Software.
14**
15** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17**
18** See http://www.trolltech.com/gpl/ for GPL licensing information.
19** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
20** information about Qt Commercial License Agreements.
21**
22** Contact info@trolltech.com if any conditions of this licensing are
23** not clear to you.
24**
25**********************************************************************/
26
27#include "project.h"
28#include "formwindow.h"
29#include "designerappiface.h"
30#include "../interfaces/languageinterface.h"
31#include "pixmapcollection.h"
32#ifndef QT_NO_SQL
33#include "dbconnectionimpl.h"
34#endif
35#include "resource.h"
36#include <qwidgetfactory.h>
37#include "outputwindow.h"
38
39#include <qfile.h>
40#include <qtextstream.h>
41#include <qurl.h>
42#include <qobjectlist.h>
43#include <qfeatures.h>
44#include <qtextcodec.h>
45#include <qdom.h>
46#include <qmessagebox.h>
47#include <qapplication.h>
48#include "mainwindow.h"
49#include <qworkspace.h>
50
51#ifndef QT_NO_SQL
52#include <qsqldatabase.h>
53#include <qsqlrecord.h>
54#include <qdatatable.h>
55#endif
56
57#include <stdlib.h>
58#ifdef Q_OS_UNIX
59# include <unistd.h>
60#endif
61
62#ifndef QT_NO_SQL
63DatabaseConnection::~DatabaseConnection()
64{
65 delete iface;
66}
67
68bool DatabaseConnection::refreshCatalog()
69{
70#ifndef QT_NO_SQL
71 if ( loaded )
72 return TRUE;
73 if ( !open() )
74 return FALSE;
75 tbls = conn->tables( QSql::TableType( QSql::Tables | QSql::Views ) );
76 flds.clear();
77 for ( QStringList::Iterator it = tbls.begin(); it != tbls.end(); ++it ) {
78 QSqlRecord fil = conn->record( *it );
79 QStringList lst;
80 for ( uint j = 0; j < fil.count(); ++j )
81 lst << fil.field( j )->name();
82 flds.insert( *it, lst );
83 }
84 loaded = TRUE;
85 conn->close();
86 return loaded;
87#else
88 return FALSE;
89#endif
90}
91
92#ifndef QT_NO_SQL
93void DatabaseConnection::remove()
94{
95 if ( nm == "(default)" )
96 QSqlDatabase::removeDatabase( QSqlDatabase::defaultConnection );
97 else
98 QSqlDatabase::removeDatabase( nm );
99 // the above will effectively delete the current connection
100 conn = 0;
101}
102#endif
103
104bool DatabaseConnection::open( bool suppressDialog )
105{
106#ifndef QT_NO_SQL
107 // register our name, if nec
108 if ( nm == "(default)" ) {
109 if ( !QSqlDatabase::contains() ) // default doesn't exists?
110 conn = QSqlDatabase::addDatabase( drv );
111 else
112 conn = QSqlDatabase::database();
113 } else {
114 if ( !QSqlDatabase::contains( nm ) )
115 conn = QSqlDatabase::addDatabase( drv, nm );
116 else
117 conn = QSqlDatabase::database( nm );
118 }
119 conn->setDatabaseName( dbName );
120 conn->setUserName( uname );
121 conn->setPassword( pword );
122 conn->setHostName( hname );
123 conn->setPort( prt );
124 bool success = conn->open();
125 for( ; suppressDialog == FALSE ; ) {
126 bool done = FALSE;
127 if ( !success ) {
128 DatabaseConnectionEditor dia( this, 0 , 0 , TRUE );
129 switch( dia.exec() ) {
130 case QDialog::Accepted:
131 done = FALSE;
132 break;
133 case QDialog::Rejected:
134 done = TRUE;
135 break;
136 }
137 }
138 if ( done )
139 break;
140 conn->setUserName( uname );
141 conn->setPassword( pword );
142 conn->setHostName( hname );
143 conn->setPort( prt );
144 success = conn->open();
145 if ( !success ) {
146 switch( QMessageBox::warning( project->messageBoxParent(), QApplication::tr( "Connection" ),
147 QApplication::tr( "Could not connect to the database.\n"
148 "Press 'OK' to continue or 'Cancel' to "
149 "specify different\nconnection information.\n" )
150 + QString( "[" + conn->lastError().driverText() + "\n" +
151 conn->lastError().databaseText() + "]\n" ),
152 QApplication::tr( "&OK" ),
153 QApplication::tr( "&Cancel" ), QString::null, 0, 1 ) ) {
154 case 0: // OK or Enter
155 continue;
156 case 1: // Cancel or Escape
157 done = TRUE;
158 break;
159 }
160 } else
161 break;
162 if ( done )
163 break;
164 }
165 if ( !success ) {
166 dbErr = conn->lastError().driverText() + "\n" + conn->lastError().databaseText();
167 remove();
168 }
169 return success;
170#else
171 return FALSE;
172#endif
173}
174
175void DatabaseConnection::close()
176{
177 if ( !loaded )
178 return;
179#ifndef QT_NO_SQL
180 if ( conn ) {
181 conn->close();
182 }
183#endif
184}
185
186DesignerDatabase *DatabaseConnection::iFace()
187{
188 if ( !iface )
189 iface = new DesignerDatabaseImpl( this );
190 return iface;
191}
192
193#endif
194
195////////
196
197bool Project::isDummy() const
198{
199 return isDummyProject;
200}
201
202Project::Project( const QString &fn, const QString &pName,
203 QPluginManager<ProjectSettingsInterface> *pm, bool isDummy,
204 const QString &l )
205 : proName( pName ), projectSettingsPluginManager( pm ), isDummyProject( isDummy )
206{
207 modified = TRUE;
208 pixCollection = new PixmapCollection( this );
209 iface = 0;
210 lang = l;
211 is_cpp = lang == "C++";
212 cfg.insert( "(all)", "qt warn_on release" );
213 templ = "app";
214 setFileName( fn );
215 if ( !pName.isEmpty() )
216 proName = pName;
217 sourcefiles.setAutoDelete( TRUE );
218 modified = FALSE;
219 objs.setAutoDelete( FALSE );
220 fakeFormFiles.setAutoDelete( FALSE );
221}
222
223Project::~Project()
224{
225 if ( singleProjectMode() )
226 removeTempProject();
227 delete iface;
228 delete pixCollection;
229}
230
231void Project::setModified( bool b )
232{
233 modified = b;
234 emit projectModified();
235}
236
237#ifndef QT_NO_SQL
238DatabaseConnection *Project::databaseConnection( const QString &name )
239{
240 for ( DatabaseConnection *conn = dbConnections.first();
241 conn;
242 conn = dbConnections.next() ) {
243 if ( conn->name() == name )
244 return conn;
245 }
246 return 0;
247}
248#endif
249
250void Project::setFileName( const QString &fn, bool doClear )
251{
252 if ( fn == filename )
253 return;
254
255 if ( singleProjectMode() ) {
256 QString qsa = QString( getenv( "HOME" ) ) + QString( "/.qsa" );
257 if ( !QFile::exists( qsa ) ) {
258 QDir d;
259 d.mkdir( qsa );
260 }
261 if ( fn == singleProFileName )
262 return;
263 singleProFileName = fn;
264 static int counter = 0;
265 QString str_counter = QString::number( counter++ );
266 str_counter = "/.qsa/" + str_counter;
267 LanguageInterface *iface = MetaDataBase::languageInterface( language() );
268 filename = QString( getenv( "HOME" ) + str_counter + QString( "tmp_" ) +
269 QFileInfo( fn ).baseName() + "/" + QFileInfo( fn ).baseName() + ".pro" );
270 removeTempProject();
271 if ( iface && iface->supports( LanguageInterface::CompressProject ) ) {
272 filename = iface->uncompressProject( makeAbsolute( singleProFileName ),
273 QString( getenv( "HOME" ) +
274 str_counter + QString( "tmp_" ) +
275 QFileInfo( fn ).baseName() ) );
276 proName = makeAbsolute( singleProFileName );
277 }
278 } else {
279 filename = fn;
280 if ( !filename.endsWith( ".pro" ) )
281 filename += ".pro";
282 proName = filename;
283 }
284
285
286 if ( proName.contains( '.' ) )
287 proName = proName.left( proName.find( '.' ) );
288
289 if ( !doClear )
290 return;
291 clear();
292 if ( QFile::exists( filename ) )
293 parse();
294}
295
296QString Project::fileName( bool singlePro ) const
297{
298 if ( singlePro )
299 return singleProFileName;
300 return filename;
301}
302
303QString Project::databaseDescription() const
304{
305 return dbFile;
306}
307
308QString Project::projectName() const
309{
310 return proName;
311}
312
313static QString parse_part( const QString &part )
314{
315 QString res;
316 bool inName = FALSE;
317 QString currName;
318 for ( int i = 0; i < (int)part.length(); ++i ) {
319 QChar c = part[ i ];
320 if ( !inName ) {
321 if ( c != ' ' && c != '\t' && c != '\n' && c != '=' && c != '\\' && c != '+' )
322 inName = TRUE;
323 else
324 continue;
325 }
326 if ( inName ) {
327 if ( c == '\n' )
328 break;
329 res += c;
330 }
331 }
332 return res;
333}
334
335QStringList parse_multiline_part( const QString &contents, const QString &key, int *start = 0 )
336{
337 if ( start )
338 *start = -1;
339 QString lastWord;
340 // Account for things like win32: SOURCES
341 int extraWhiteSpaceCount = 0;
342 int braceCount = 0;
343 for ( int i = 0; i < (int)contents.length(); ++i ) {
344 QChar c( contents[ i ] );
345 switch ( c ) {
346 case '{':
347 braceCount++;
348 lastWord = "";
349 break;
350 case '}':
351 braceCount--;
352 lastWord = "";
353 break;
354 case ' ': case '\t':
355 if (!key.startsWith(lastWord)) {
356 lastWord = "";
357 extraWhiteSpaceCount = 0;
358 } else {
359 extraWhiteSpaceCount++;
360 }
361 break;
362 case '\\': case '\n':
363 lastWord = "";
364 break;
365 case '#':
366 while ( contents[ i ] != '\n' && i < (int)contents.length() )
367 ++i;
368 break;
369 default:
370 lastWord += c;
371 }
372
373 // ### we should read the 'bla { SOURCES= ... }' stuff as well (braceCount > 0)
374 if ( lastWord == key && braceCount == 0 ) {
375 if ( start )
376 *start = i - lastWord.length() - extraWhiteSpaceCount + 1;
377 QStringList lst;
378 bool inName = FALSE;
379 QString currName;
380 bool hadEqual = FALSE;
381 for ( ; i < (int)contents.length(); ++i ) {
382 c = contents[ i ];
383 if ( !hadEqual && c != '=' )
384 continue;
385 if ( !hadEqual ) {
386 hadEqual = TRUE;
387 continue;
388 }
389 if ( ( c.isLetter() ||
390 c.isDigit() ||
391 c == '.' ||
392 c == '/' ||
393 c == '_' ||
394 c == '\\' ||
395 c == '\"' ||
396 c == '\'' ||
397 c == '=' ||
398 c == '$' ||
399 c == '-' ||
400 c == '(' ||
401 c == ')' ||
402 c == ':' ||
403 c == '+' ||
404 c == ',' ||
405 c == '~' ||
406 c == '{' ||
407 c == '}' ||
408 c == '@' ) &&
409 c != ' ' && c != '\t' && c != '\n' ) {
410 if ( !inName )
411 currName = QString::null;
412 if ( c != '\\' || contents[i+1] != '\n' ) {
413 currName += c;
414 inName = TRUE;
415 }
416 } else {
417 if ( inName ) {
418 inName = FALSE;
419 if ( currName.simplifyWhiteSpace() != "\\" )
420 lst.append( currName );
421 }
422 if ( c == '\n' && i > 0 && contents[ (int)i - 1 ] != '\\' )
423 break;
424 }
425 }
426 return lst;
427 }
428 }
429
430 return QStringList();
431}
432
433void Project::parse()
434{
435 QFile f( filename );
436 if ( !f.exists() || !f.open( IO_ReadOnly ) )
437 return;
438 QTextStream ts( &f );
439 QString contents = ts.read();
440 f.close();
441
442 proName = QFileInfo( filename ).baseName();
443
444 QStringList::ConstIterator it;
445
446 int i = contents.find( "LANGUAGE" );
447 if ( i != -1 ) {
448 lang = "";
449 is_cpp = FALSE;
450 QString part = contents.mid( i + QString( "LANGUAGE" ).length() );
451 lang = parse_part( part );
452 is_cpp = lang == "C++";
453 }
454
455 i = contents.find( "DBFILE" );
456 if ( i != -1 ) {
457 dbFile = "";
458 QString part = contents.mid( i + QString( "DBFILE" ).length() );
459 dbFile = parse_part( part );
460 }
461
462 QStringList uifiles = parse_multiline_part( contents, "FORMS" );
463 uifiles += parse_multiline_part( contents, "INTERFACES" ); // compatibility
464 for ( it = uifiles.begin(); it != uifiles.end(); ++it ) {
465 if ( (*it).startsWith( "__APPOBJ" ) )
466 continue;
467 (void) new FormFile( *it, FALSE, this );
468 }
469
470
471 i = contents.find( "TEMPLATE" );
472 if ( i != -1 ) {
473 templ = "";
474 QString part = contents.mid( i + QString( "TEMPLATE" ).length() );
475 templ = parse_part( part );
476 }
477
478 readPlatformSettings( contents, "CONFIG", cfg );
479 readPlatformSettings( contents, "LIBS", lbs );
480 readPlatformSettings( contents, "INCLUDEPATH", inclPath );
481 readPlatformSettings( contents, "DEFINES", defs );
482 readPlatformSettings( contents, "SOURCES", sources );
483 readPlatformSettings( contents, "HEADERS", headers );
484
485 LanguageInterface *iface = MetaDataBase::languageInterface( lang );
486 if ( iface ) {
487 QStringList sourceKeys;
488 iface->sourceProjectKeys( sourceKeys );
489 for ( QStringList::Iterator it = sourceKeys.begin(); it != sourceKeys.end(); ++it ) {
490 QStringList lst = parse_multiline_part( contents, *it );
491 for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it )
492 (void) new SourceFile( *it, FALSE, this );
493 }
494 }
495
496 updateCustomSettings();
497
498 for ( it = csList.begin(); it != csList.end(); ++it ) {
499 i = contents.find( *it );
500 if ( i != -1 ) {
501 QString val = "";
502 QString part = contents.mid( i + QString( *it ).length() );
503 val = parse_part( part );
504 customSettings.replace( *it, val );
505 }
506 }
507
508 loadConnections();
509
510 QStringList images = parse_multiline_part( contents, "IMAGES" );
511
512 // ### remove that for the final - this is beta-compatibility
513 if ( images.isEmpty() && QDir( QFileInfo( filename ).dirPath( TRUE ) + "/images" ).exists() ) {
514 images = QDir( QFileInfo( filename ).dirPath( TRUE ) + "/images" ).entryList();
515 for ( int i = 0; i < (int)images.count(); ++i )
516 images[ i ].prepend( "images/" );
517 modified = TRUE;
518 }
519
520 for ( QStringList::ConstIterator pit = images.begin(); pit != images.end(); ++pit )
521 pixCollection->load( *pit );
522}
523
524void Project::clear()
525{
526 dbFile = "";
527 proName = "unnamed";
528 desc = "";
529}
530
531bool Project::removeSourceFile( SourceFile *sf )
532{
533 if ( !sourcefiles.containsRef( sf ) )
534 return FALSE;
535 if ( !sf->close() )
536 return FALSE;
537 sourcefiles.removeRef( sf );
538 modified = TRUE;
539 emit sourceFileRemoved( sf );
540 return TRUE;
541}
542
543void Project::setDatabaseDescription( const QString &db )
544{
545 dbFile = db;
546}
547
548void Project::setDescription( const QString &s )
549{
550 desc = s;
551}
552
553QString Project::description() const
554{
555 return desc;
556}
557
558
559bool Project::isValid() const
560{
561 // #### do more checking here?
562 if ( filename.isEmpty() || proName.isEmpty() )
563 return FALSE;
564
565 return TRUE;
566}
567
568QString Project::makeAbsolute( const QString &f )
569{
570 if ( isDummy() )
571 return f;
572 QString encodedUrl = QFileInfo( filename ).dirPath( TRUE );
573 QUrl::encode( encodedUrl );
574 QUrl u( encodedUrl, f );
575 return u.path();
576}
577
578QString Project::makeRelative( const QString &f )
579{
580 if ( isDummy() )
581 return f;
582 QString p = QFileInfo( filename ).dirPath( TRUE );
583 QString f2 = f;
584#if defined(Q_WS_WIN32)
585 if ( p.endsWith("/") )
586 p = p.left( p.length() - 1 );
587 if ( f2.left( p.length() ).lower() == p.lower() )
588#else
589 if ( f2.left( p.length() ) == p )
590#endif
591 f2.remove( 0, p.length() + 1 );
592 return f2;
593}
594
595static void remove_contents( QString &contents, const QString &s )
596{
597 int i = contents.find( s );
598 if ( i != -1 ) {
599 int start = i;
600 int end = contents.find( '\n', i );
601 if ( end == -1 )
602 end = contents.length() - 1;
603 contents.remove( start, end - start + 1 );
604 }
605}
606
607static void remove_multiline_contents( QString &contents, const QString &s, int *strt = 0 )
608{
609 int i = contents.find( s );
610 int startBrace = contents.findRev("{", i);
611 int endBrace = contents.findRev("}", i);
612 // We found a startBrace before i, but no endBrace after the startBrace before i
613 if (startBrace != -1 && endBrace < startBrace)
614 return;
615 if ( strt )
616 *strt = i;
617 int start = i;
618 bool lastWasBackspash = TRUE;
619 if ( i != -1 && ( i == 0 || contents[ i - 1 ] != '{' || contents[ i - 1 ] != ':' ) && !(i > 0 && contents[i-1] != '\n')) {
620 for ( ; i < (int)contents.length(); ++i ) {
621 if ( contents[ i ] == '\n' && !lastWasBackspash )
622 break;
623 lastWasBackspash = ( contents[ i ] == '\\' ||
624 lastWasBackspash && ( contents[ i ] == ' ' || contents[ i ] == '\t' ) );
625 }
626 contents.remove( start, i - start + 1 );
627 }
628}
629
630void Project::save( bool onlyProjectFile )
631{
632 bool anythingModified = FALSE;
633
634 // save sources and forms
635 if ( !onlyProjectFile ) {
636
637 saveConnections();
638
639 for ( SourceFile *sf = sourcefiles.first(); sf; sf = sourcefiles.next() ) {
640 anythingModified = anythingModified || sf->isModified();
641 if ( !sf->save() )
642 return;
643 }
644
645 for ( FormFile *ff = formfiles.first(); ff; ff = formfiles.next() ) {
646 anythingModified = anythingModified || ff->isModified();
647 if ( !ff->save() )
648 return;
649 }
650 }
651
652 if ( isDummy() || filename.isEmpty() )
653 return;
654
655 if ( !modified ) {
656 if ( singleProjectMode() ) {
657 LanguageInterface *iface = MetaDataBase::languageInterface( language() );
658 if ( iface && iface->supports( LanguageInterface::CompressProject ) )
659 iface->compressProject( makeAbsolute( filename ), singleProFileName, anythingModified );
660 }
661 return;
662 }
663
664 QFile f( filename );
665 QString original = "";
666
667 // read the existing file
668 bool hasPreviousContents = FALSE;
669 if ( f.open( IO_ReadOnly ) ) {
670 QTextStream ts( &f );
671 original = ts.read();
672 f.close();
673 hasPreviousContents = TRUE;
674 remove_contents( original, "{SOURCES+=" ); // ### compatibility with early 3.0 betas
675 remove_contents( original, "DBFILE" );
676 remove_contents( original, "LANGUAGE" );
677 remove_contents( original, "TEMPLATE" );
678 removePlatformSettings( original, "CONFIG" );
679 removePlatformSettings( original, "DEFINES" );
680 removePlatformSettings( original, "LIBS" );
681 removePlatformSettings( original, "INCLUDEPATH" );
682 removePlatformSettings( original, "SOURCES" );
683 removePlatformSettings( original, "HEADERS" );
684 remove_multiline_contents( original, "FORMS" );
685 remove_multiline_contents( original, "INTERFACES" ); // compatibility
686 remove_multiline_contents( original, "IMAGES" );
687 for ( QStringList::Iterator it = csList.begin(); it != csList.end(); ++it )
688 remove_contents( original, *it );
689 }
690
691 if (!original.isEmpty()) {
692 // Removes any new lines at the beginning of the file
693 while (original.startsWith("\n"))
694 original.remove(0, 1);
695 }
696
697 // the contents of the saved file
698 QString contents;
699
700 // template
701 contents += "TEMPLATE\t= " + templ + "\n";
702
703 // language
704 contents += "LANGUAGE\t= " + lang + "\n";
705 contents += "\n";
706
707 // config
708 writePlatformSettings( contents, "CONFIG", cfg );
709 LanguageInterface *iface = MetaDataBase::languageInterface( lang );
710 if ( iface ) {
711 QStringList sourceKeys;
712 iface->sourceProjectKeys( sourceKeys );
713 for ( QStringList::Iterator spit = sourceKeys.begin(); spit != sourceKeys.end(); ++spit )
714 remove_multiline_contents( contents, *spit );
715 }
716
717 // libs, defines, includes
718 writePlatformSettings( contents, "LIBS", lbs );
719 writePlatformSettings( contents, "DEFINES", defs );
720 writePlatformSettings( contents, "INCLUDEPATH", inclPath );
721 writePlatformSettings( contents, "SOURCES", sources );
722 writePlatformSettings( contents, "HEADERS", headers );
723
724 // unix
725 if ( !hasPreviousContents ) {
726 contents +=
727 "unix {\n"
728 " UI_DIR = .ui\n"
729 " MOC_DIR = .moc\n"
730 " OBJECTS_DIR = .obj\n"
731 "}\n\n";
732 }
733
734 // sources
735 if ( !sourcefiles.isEmpty() && iface ) {
736 QMap<QString, QStringList> sourceToKey;
737 for ( SourceFile *f = sourcefiles.first(); f; f = sourcefiles.next() ) {
738 QString key = iface->projectKeyForExtension( QFileInfo( f->fileName() ).extension() );
739 QStringList lst = sourceToKey[ key ];
740 lst << makeRelative( f->fileName() );
741 sourceToKey.replace( key, lst );
742 }
743
744 for ( QMap<QString, QStringList>::Iterator skit = sourceToKey.begin();
745 skit != sourceToKey.end(); ++skit ) {
746 QString part = skit.key() + "\t+= ";
747 QStringList lst = *skit;
748 for ( QStringList::Iterator sit = lst.begin(); sit != lst.end(); ++sit ) {
749 part += *sit;
750 part += ++sit != lst.end() ? " \\\n\t" : "";
751 --sit;
752 }
753 part += "\n\n";
754 contents += part;
755 }
756 }
757
758 // forms and interfaces
759 if ( !formfiles.isEmpty() ) {
760 contents += "FORMS\t= ";
761 for ( QPtrListIterator<FormFile> fit = formfiles; fit.current(); ++fit ) {
762 contents += fit.current()->fileName() +
763 (fit != formfiles.last() ? " \\\n\t" : "");
764 }
765 contents += "\n\n";
766 }
767
768 // images
769 if ( !pixCollection->isEmpty() ) {
770 contents += "IMAGES\t= ";
771 QValueList<PixmapCollection::Pixmap> pixmaps = pixCollection->pixmaps();
772 for ( QValueList<PixmapCollection::Pixmap>::Iterator it = pixmaps.begin();
773 it != pixmaps.end(); ++it ) {
774 contents += makeRelative( (*it).absname );
775 contents += ++it != pixmaps.end() ? " \\\n\t" : "";
776 --it;
777 }
778 contents += "\n\n";
779 }
780
781 // database
782 if ( !dbFile.isEmpty() )
783 contents += "DBFILE\t= " + dbFile + "\n";
784
785 // custom settings
786 for ( QStringList::Iterator it = csList.begin(); it != csList.end(); ++it ) {
787 QString val = *customSettings.find( *it );
788 if ( !val.isEmpty() )
789 contents += *it + "\t= " + val + "\n";
790 }
791
792 if ( !f.open( IO_WriteOnly | IO_Translate ) ) {
793 QMessageBox::warning( messageBoxParent(),
794 "Save Project Failed", "Couldn't write project file " + filename );
795 return;
796 }
797
798 QTextStream os( &f );
799 os << contents;
800 if (hasPreviousContents)
801 os << original;
802
803 f.close();
804
805 setModified( FALSE );
806
807 if ( singleProjectMode() ) {
808 LanguageInterface *iface = MetaDataBase::languageInterface( language() );
809 if ( iface && iface->supports( LanguageInterface::CompressProject ) )
810 iface->compressProject( makeAbsolute( filename ), singleProFileName, TRUE );
811 }
812}
813
814#ifndef QT_NO_SQL
815QPtrList<DatabaseConnection> Project::databaseConnections() const
816{
817 return dbConnections;
818}
819#endif
820
821#ifndef QT_NO_SQL
822void Project::setDatabaseConnections( const QPtrList<DatabaseConnection> &lst )
823{
824 dbConnections = lst;
825}
826#endif
827
828#ifndef QT_NO_SQL
829void Project::addDatabaseConnection( DatabaseConnection *conn )
830{
831 dbConnections.append( conn );
832 modified = TRUE;
833}
834#endif
835
836#ifndef QT_NO_SQL
837void Project::removeDatabaseConnection( const QString &c )
838{
839 for ( DatabaseConnection *conn = dbConnections.first(); conn; conn = dbConnections.next() ) {
840 if ( conn->name() == c ) {
841 conn->remove();
842 dbConnections.removeRef( conn );
843 delete conn;
844 return;
845 }
846 }
847}
848#endif
849
850#ifndef QT_NO_SQL
851QStringList Project::databaseConnectionList()
852{
853 QStringList lst;
854 for ( DatabaseConnection *conn = dbConnections.first(); conn; conn = dbConnections.next() )
855 lst << conn->name();
856 return lst;
857}
858#endif
859
860#ifndef QT_NO_SQL
861QStringList Project::databaseTableList( const QString &connection )
862{
863 DatabaseConnection *conn = databaseConnection( connection );
864 if ( !conn ) {
865 return QStringList();
866 }
867 return conn->tables();
868}
869#endif
870
871#ifndef QT_NO_SQL
872QStringList Project::databaseFieldList( const QString &connection, const QString &table )
873{
874 DatabaseConnection *conn = databaseConnection( connection );
875 if ( !conn )
876 return QStringList();
877 return conn->fields( table );
878}
879#endif
880
881#ifndef QT_NO_SQL
882static QString makeIndent( int indent )
883{
884 QString s;
885 s.fill( ' ', indent * 4 );
886 return s;
887}
888#endif
889
890#ifndef QT_NO_SQL
891static void saveSingleProperty( QTextStream &ts, const QString& name, const QString& value, int indent )
892{
893 ts << makeIndent( indent ) << "<property name=\"" << name << "\">" << endl;
894 ++indent;
895 ts << makeIndent( indent ) << "<string>" << value << "</string>" << endl;
896 --indent;
897 ts << makeIndent( indent ) << "</property>" << endl;
898}
899#endif
900
901void Project::saveConnections()
902{
903#ifndef QT_NO_SQL
904 if ( dbFile.isEmpty() ) {
905 QFileInfo fi( fileName() );
906 setDatabaseDescription( fi.baseName() + ".db" );
907 }
908
909 QFile f( makeAbsolute( dbFile ) );
910
911 if ( dbConnections.isEmpty() ) {
912 if ( f.exists() )
913 f.remove();
914 setDatabaseDescription( "" );
915 modified = TRUE;
916 return;
917 }
918
919 /* .db xml */
920 if ( f.open( IO_WriteOnly | IO_Translate ) ) {
921 QTextStream ts( &f );
922 ts.setCodec( QTextCodec::codecForName( "UTF-8" ) );
923 ts << "<!DOCTYPE DB><DB version=\"1.0\">" << endl;
924
925 /* db connections */
926 int indent = 0;
927 for ( DatabaseConnection *conn = dbConnections.first(); conn; conn = dbConnections.next() ) {
928 ts << makeIndent( indent ) << "<connection>" << endl;
929 ++indent;
930 saveSingleProperty( ts, "name", conn->name(), indent );
931 saveSingleProperty( ts, "driver", conn->driver(), indent );
932 saveSingleProperty( ts, "database", conn->database(), indent );
933 saveSingleProperty( ts, "username", conn->username(), indent );
934 saveSingleProperty( ts, "hostname", conn->hostname(), indent );
935 saveSingleProperty( ts, "port", QString::number( conn->port() ), indent );
936
937 /* connection tables */
938 QStringList tables = conn->tables();
939 for ( QStringList::Iterator it = tables.begin();
940 it != tables.end(); ++it ) {
941 ts << makeIndent( indent ) << "<table>" << endl;
942 ++indent;
943 saveSingleProperty( ts, "name", (*it), indent );
944
945 /* tables fields */
946 QStringList fields = conn->fields( *it );
947 for ( QStringList::Iterator it2 = fields.begin();
948 it2 != fields.end(); ++it2 ) {
949 ts << makeIndent( indent ) << "<field>" << endl;
950 ++indent;
951 saveSingleProperty( ts, "name", (*it2), indent );
952 --indent;
953 ts << makeIndent( indent ) << "</field>" << endl;
954 }
955
956 --indent;
957 ts << makeIndent( indent ) << "</table>" << endl;
958 }
959
960 --indent;
961 ts << makeIndent( indent ) << "</connection>" << endl;
962 }
963
964 ts << "</DB>" << endl;
965 f.close();
966 }
967#endif
968}
969
970#ifndef QT_NO_SQL
971static QDomElement loadSingleProperty( QDomElement e, const QString& name )
972{
973 QDomElement n;
974 for ( n = e.firstChild().toElement();
975 !n.isNull();
976 n = n.nextSibling().toElement() ) {
977 if ( n.tagName() == "property" && n.toElement().attribute("name") == name )
978 return n;
979 }
980 return n;
981}
982#endif
983
984void Project::loadConnections()
985{
986#ifndef QT_NO_SQL
987 if ( dbFile.isEmpty() || !QFile::exists( makeAbsolute( dbFile ) ) )
988 return;
989
990 QFile f( makeAbsolute( dbFile ) );
991 if ( f.open( IO_ReadOnly ) ) {
992 QDomDocument doc;
993 QString errMsg;
994 int errLine;
995 if ( doc.setContent( &f, &errMsg, &errLine ) ) {
996 QDomElement e;
997 e = doc.firstChild().toElement();
998
999 /* connections */
1000 QDomNodeList connections = e.toElement().elementsByTagName( "connection" );
1001 for ( uint i = 0; i < connections.length(); i++ ) {
1002 QDomElement connection = connections.item(i).toElement();
1003 QDomElement connectionName = loadSingleProperty( connection, "name" );
1004 QDomElement connectionDriver = loadSingleProperty( connection, "driver" );
1005 QDomElement connectionDatabase = loadSingleProperty( connection,
1006 "database" );
1007 QDomElement connectionUsername = loadSingleProperty( connection,
1008 "username" );
1009 QDomElement connectionHostname = loadSingleProperty( connection,
1010 "hostname" );
1011 QDomElement connectionPort = loadSingleProperty( connection,
1012 "port" );
1013
1014 DatabaseConnection *conn = new DatabaseConnection( this );
1015 conn->setName( connectionName.firstChild().firstChild().toText().data() );
1016 conn->setDriver( connectionDriver.firstChild().firstChild().toText().data() );
1017 conn->setDatabase( connectionDatabase.firstChild().firstChild().toText().data() );
1018 conn->setUsername( connectionUsername.firstChild().firstChild().toText().data() );
1019 conn->setHostname( connectionHostname.firstChild().firstChild().toText().data() );
1020 conn->setPort( QString( connectionPort.firstChild().firstChild().toText().data() ).toInt() );
1021
1022 /* connection tables */
1023 QDomNodeList tables = connection.toElement().elementsByTagName( "table" );
1024 for ( uint j = 0; j < tables.length(); j++ ) {
1025 QDomElement table = tables.item(j).toElement();
1026 QDomElement tableName = loadSingleProperty( table, "name" );
1027 conn->addTable( tableName.firstChild().firstChild().toText().data() );
1028
1029 /* table fields */
1030 QStringList fieldList;
1031 QDomNodeList fields = table.toElement().elementsByTagName( "field" );
1032 for ( uint k = 0; k < fields.length(); k++ ) {
1033 QDomElement field = fields.item(k).toElement();
1034 QDomElement fieldName = loadSingleProperty( field, "name" );
1035 fieldList.append( fieldName.firstChild().firstChild().toText().data() );
1036 }
1037 conn->setFields( tableName.firstChild().firstChild().toText().data(),
1038 fieldList );
1039 }
1040
1041 dbConnections.append( conn );
1042 }
1043 } else {
1044 qDebug( QString("Parse error: ") + errMsg + QString(" in line %d"), errLine );
1045 }
1046 f.close();
1047 }
1048#endif
1049}
1050
1051/*! Opens the database \a connection. The connection remains open and
1052can be closed again with closeDatabase().
1053*/
1054
1055bool Project::openDatabase( const QString &connection, bool suppressDialog )
1056{
1057#ifndef QT_NO_SQL
1058 DatabaseConnection *conn = databaseConnection( connection );
1059 if ( connection.isEmpty() && !conn )
1060 conn = databaseConnection( "(default)" );
1061 if ( !conn )
1062 return FALSE;
1063 bool b = conn->open( suppressDialog );
1064 return b;
1065#else
1066 Q_UNUSED( connection );
1067 Q_UNUSED( suppressDialog );
1068 return FALSE;
1069#endif
1070}
1071
1072/*! Closes the database \a connection.
1073*/
1074void Project::closeDatabase( const QString &connection )
1075{
1076#ifndef QT_NO_SQL
1077 DatabaseConnection *conn = databaseConnection( connection );
1078 if ( connection.isEmpty() && !conn )
1079 conn = databaseConnection( "(default)" );
1080 if ( !conn )
1081 return;
1082 conn->close();
1083#else
1084 Q_UNUSED( connection );
1085#endif
1086}
1087
1088// void Project::formClosed( FormWindow *fw )
1089// {
1090// formWindows.remove( fw );
1091// }
1092
1093QObjectList *Project::formList( bool resolveFakeObjects ) const
1094{
1095 QObjectList *l = new QObjectList;
1096 for ( QPtrListIterator<FormFile> forms(formfiles); forms.current(); ++forms ) {
1097 FormFile* f = forms.current();
1098 if ( f->formWindow() ) {
1099 if ( resolveFakeObjects && f->formWindow()->isFake() )
1100 l->append( objectForFakeForm( f->formWindow() ) );
1101 else
1102 l->append( f->formWindow()->child( 0, "QWidget" ) );
1103 } else if ( f->isFake() ) {
1104 l->append( objectForFakeFormFile( f ) );
1105 }
1106 }
1107 return l;
1108}
1109
1110DesignerProject *Project::iFace()
1111{
1112 if ( !iface )
1113 iface = new DesignerProjectImpl( this );
1114 return iface;
1115}
1116
1117void Project::setLanguage( const QString &l )
1118{
1119 if ( l == lang )
1120 return;
1121 lang = l;
1122 is_cpp = lang == "C++";
1123 updateCustomSettings();
1124 modified = TRUE;
1125}
1126
1127QString Project::language() const
1128{
1129 return lang;
1130}
1131
1132void Project::setCustomSetting( const QString &key, const QString &value )
1133{
1134 customSettings.remove( key );
1135 customSettings.insert( key, value );
1136 modified = TRUE;
1137}
1138
1139QString Project::customSetting( const QString &key ) const
1140{
1141 return *customSettings.find( key );
1142}
1143
1144void Project::updateCustomSettings()
1145{
1146 if ( !projectSettingsPluginManager )
1147 return;
1148
1149/*
1150 ProjectSettingsInterface *iface = 0;
1151 projectSettingsPluginManager->queryInterface( lang, (QUnknownInterface**)&iface );
1152 if ( !iface )
1153 return;
1154 csList = iface->projectSettings();
1155 iface->release();
1156*/
1157
1158 QInterfacePtr<ProjectSettingsInterface> iface;
1159 projectSettingsPluginManager->queryInterface( lang, &iface );
1160 if ( !iface )
1161 return;
1162 csList = iface->projectSettings();
1163 customSettings.clear();
1164
1165}
1166
1167void Project::setActive( bool b )
1168{
1169 pixCollection->setActive( b );
1170}
1171
1172void Project::addSourceFile( SourceFile *sf )
1173{
1174 sourcefiles.append( sf );
1175 modified = TRUE;
1176 emit sourceFileAdded( sf );
1177}
1178
1179
1180SourceFile* Project::findSourceFile( const QString& filename, SourceFile *ignore ) const
1181{
1182 QPtrListIterator<SourceFile> it(sourcefiles);
1183 while ( it.current() ) {
1184 if ( it.current() != ignore && it.current()->fileName() == filename )
1185 return it.current();
1186 ++it;
1187 }
1188 return 0;
1189}
1190
1191FormFile* Project::findFormFile( const QString& filename, FormFile *ignore ) const
1192{
1193 QPtrListIterator<FormFile> it(formfiles);
1194 while ( it.current() ) {
1195 if ( it.current() != ignore && it.current()->fileName() == filename )
1196 return it.current();
1197 ++it;
1198 }
1199 return 0;
1200}
1201
1202void Project::setIncludePath( const QString &platform, const QString &path )
1203{
1204 if ( inclPath[platform] == path )
1205 return;
1206 inclPath.replace( platform, path );
1207 modified = TRUE;
1208}
1209
1210void Project::setLibs( const QString &platform, const QString &path )
1211{
1212 lbs.replace( platform, path );
1213}
1214
1215void Project::setDefines( const QString &platform, const QString &path )
1216{
1217 defs.replace( platform, path );
1218}
1219
1220void Project::setConfig( const QString &platform, const QString &config )
1221{
1222 cfg.replace( platform, config );
1223}
1224
1225QString Project::config( const QString &platform ) const
1226{
1227 return cfg[ platform ];
1228}
1229
1230QString Project::libs( const QString &platform ) const
1231{
1232 return lbs[ platform ];
1233}
1234
1235QString Project::defines( const QString &platform ) const
1236{
1237 return defs[ platform ];
1238}
1239
1240QString Project::includePath( const QString &platform ) const
1241{
1242 return inclPath[ platform ];
1243}
1244
1245QString Project::templte() const
1246{
1247 return templ;
1248}
1249
1250void Project::setTemplate( const QString &t )
1251{
1252 templ = t;
1253}
1254
1255void Project::readPlatformSettings( const QString &contents,
1256 const QString &setting,
1257 QMap<QString, QString> &res )
1258{
1259 const QString platforms[] = { "", "win32", "unix", "mac", "os2", QString::null };
1260 for ( int i = 0; platforms[ i ] != QString::null; ++i ) {
1261 QString p = platforms[ i ];
1262 if ( !p.isEmpty() )
1263 p += ":";
1264 QStringList lst = parse_multiline_part( contents, p + setting );
1265 QString s = lst.join( " " );
1266 QString key = platforms[ i ];
1267 if ( key.isEmpty() )
1268 key = "(all)";
1269 res.replace( key, s );
1270 }
1271}
1272
1273void Project::removePlatformSettings( QString &contents, const QString &setting )
1274{
1275 const QString platforms[] = { "win32", "unix", "mac", "os2", "", QString::null };
1276 for ( int i = 0; platforms[ i ] != QString::null; ++i ) {
1277 QString p = platforms[ i ];
1278 if ( !p.isEmpty() )
1279 p += ":";
1280 remove_multiline_contents( contents, p + setting );
1281 }
1282}
1283
1284void Project::writePlatformSettings( QString &contents, const QString &setting,
1285 const QMap<QString, QString> &input )
1286{
1287 const QString platforms[] = { "", "win32", "unix", "mac", "os2", QString::null };
1288 int i;
1289 LanguageInterface *iface = MetaDataBase::languageInterface( lang );
1290 if (iface && (setting == "SOURCES" || setting == "HEADERS")) // The (all) part will be saved later on
1291 i = 1;
1292 else
1293 i = 0;
1294 for (; platforms[ i ] != QString::null; ++i ) {
1295 QString p = platforms[ i ];
1296 if ( !p.isEmpty() )
1297 p += ":";
1298 QString key = platforms[ i ];
1299 if ( key.isEmpty() )
1300 key = "(all)";
1301 QMap<QString, QString>::ConstIterator it = input.find( key );
1302 if ( it == input.end() || (*it).isEmpty() )
1303 continue;
1304 contents += p + setting + "\t+= " + *it + "\n\n";
1305 }
1306}
1307
1308void Project::addFormFile( FormFile *ff )
1309{
1310 formfiles.append( ff );
1311 modified = TRUE;
1312 emit formFileAdded( ff );
1313}
1314
1315bool Project::removeFormFile( FormFile *ff )
1316{
1317 if ( !formfiles.containsRef( ff ) )
1318 return FALSE;
1319 if ( !ff->close() )
1320 return FALSE;
1321 formfiles.removeRef( ff );
1322 modified = TRUE;
1323 emit formFileRemoved( ff );
1324 return TRUE;
1325}
1326
1327void Project::addObject( QObject *o )
1328{
1329 bool wasModified = modified;
1330 objs.append( o );
1331 FormFile *ff = new FormFile( "", FALSE, this, "qt_fakewindow" );
1332 ff->setFileName( "__APPOBJ" + QString( o->name() ) + ".ui" );
1333 fakeFormFiles.insert( (void*)o, ff );
1334 MetaDataBase::addEntry( o );
1335 if ( hasGUI() ) {
1336 QWidget *parent = MainWindow::self ? MainWindow::self->qWorkspace() : 0;
1337 FormWindow *fw = new FormWindow( ff, MainWindow::self, parent, "qt_fakewindow" );
1338 fw->setProject( this );
1339 if ( QFile::exists( ff->absFileName() ) )
1340 Resource::loadExtraSource( ff, ff->absFileName(),
1341 MetaDataBase::languageInterface( language() ), FALSE );
1342 if ( MainWindow::self )
1343 fw->setMainWindow( MainWindow::self );
1344 if ( MainWindow::self ) {
1345 QApplication::sendPostedEvents( MainWindow::self->qWorkspace(), QEvent::ChildInserted );
1346 connect( fw,
1347 SIGNAL( undoRedoChanged( bool, bool, const QString &, const QString & ) ),
1348 MainWindow::self,
1349 SLOT( updateUndoRedo( bool, bool, const QString &, const QString & ) )
1350 );
1351 }
1352 if ( fw->parentWidget() ) {
1353 fw->parentWidget()->setFixedSize( 1, 1 );
1354 fw->show();
1355 }
1356 } else {
1357 if ( QFile::exists( ff->absFileName() ) )
1358 Resource::loadExtraSource( ff, ff->absFileName(),
1359 MetaDataBase::languageInterface( language() ), FALSE );
1360 }
1361 emit objectAdded( o );
1362 modified = wasModified;
1363}
1364
1365void Project::setObjects( const QObjectList &ol )
1366{
1367 for ( QObjectListIt it( ol ); it.current(); ++it )
1368 addObject( it.current() );
1369}
1370
1371void Project::removeObject( QObject *o )
1372{
1373 bool wasModified = modified;
1374 objs.removeRef( o );
1375 MetaDataBase::removeEntry( o );
1376 fakeFormFiles.remove( (void*)o );
1377 emit objectRemoved( o );
1378 modified = wasModified;
1379}
1380
1381QObjectList Project::objects() const
1382{
1383 return objs;
1384}
1385
1386FormFile *Project::fakeFormFileFor( QObject *o ) const
1387{
1388 return fakeFormFiles.find( (void*)o );
1389}
1390
1391QObject *Project::objectForFakeForm( FormWindow *fw ) const
1392{
1393 for ( QPtrDictIterator<FormFile> it( fakeFormFiles ); it.current(); ++it ) {
1394 if ( it.current()->formWindow() == fw ||
1395 it.current() == fw->formFile() )
1396 return (QObject*)it.currentKey();
1397 }
1398 return 0;
1399}
1400
1401QObject *Project::objectForFakeFormFile( FormFile *ff ) const
1402{
1403 for ( QPtrDictIterator<FormFile> it( fakeFormFiles ); it.current(); ++it ) {
1404 if ( it.current() == ff )
1405 return (QObject*)it.currentKey();
1406 }
1407 return 0;
1408}
1409
1410void Project::removeTempProject()
1411{
1412 if ( !singleProjectMode() )
1413 return;
1414 QDir d( QFileInfo( filename ).dirPath() );
1415 if ( !d.exists( QFileInfo( filename ).dirPath() ) )
1416 return;
1417 QStringList files = d.entryList( QDir::Files );
1418 QStringList::Iterator it;
1419 for ( it = files.begin(); it != files.end(); ++it ) {
1420 d.remove( *it );
1421 }
1422 if ( d.exists( QFileInfo( filename ).dirPath() + "/images" ) ) {
1423 d = QDir( QFileInfo( filename ).dirPath() + "/images" );
1424 files = d.entryList( QDir::Files );
1425 for ( it = files.begin(); it != files.end(); ++it )
1426 d.remove( *it );
1427 d = QDir( QFileInfo( filename ).dirPath() );
1428 d.remove( "images" );
1429 }
1430 d.remove( QFileInfo( filename ).dirPath() );
1431#if defined(Q_OS_UNIX)
1432 // ##### implement for all platforms, ideally should be in Qt
1433 ::rmdir( d.absPath().latin1() );
1434#endif
1435}
1436
1437void Project::addAndEditFunction( const QString &function, const QString &functionBody, bool openDeveloper )
1438{
1439 for ( SourceFile *f = sourcefiles.first(); f; f = sourcefiles.next() ) {
1440 if ( QFileInfo( f->fileName() ).baseName() == "main" ) {
1441 QValueList<LanguageInterface::Function> funcs;
1442 LanguageInterface *iface = MetaDataBase::languageInterface( language() );
1443 if ( !iface )
1444 return;
1445 iface->functions( f->text(), &funcs );
1446 QString func = function;
1447 int i = func.find( '(' );
1448 if ( i != -1 )
1449 func = func.left( i );
1450
1451 bool found = FALSE;
1452 for ( QValueList<LanguageInterface::Function>::Iterator it = funcs.begin();
1453 it != funcs.end(); ++it ) {
1454 if ( (*it).name.left( (*it).name.find( '(' ) ) == func ) {
1455 found = TRUE;
1456 break;
1457 }
1458 }
1459
1460 if ( !found ) {
1461 QString code = f->text();
1462 if ( functionBody.isEmpty() )
1463 code += "\n\n" + iface->createFunctionStart( "", func, "", "" ) + "()\n{\n\n}\n";
1464 else
1465 code += "\n\n" + iface->createFunctionStart( "", func, "", "" ) +
1466 "()\n" + functionBody + "\n";
1467 f->setText( code );
1468 if ( f->editor() )
1469 f->editor()->refresh( FALSE );
1470 }
1471
1472 if ( openDeveloper ) {
1473 if ( MainWindow::self )
1474 MainWindow::self->editSource( f );
1475 f->editor()->setFunction( func, "" );
1476 }
1477
1478 break;
1479 }
1480 }
1481}
1482
1483bool Project::hasParentObject( QObject *o )
1484{
1485 for ( QObject *p = objs.first(); p; p = objs.next() ) {
1486 QObject *c = p->child( o->name(), o->className() );
1487 if ( c )
1488 return TRUE;
1489 }
1490 return FALSE;
1491}
1492
1493QString Project::qualifiedName( QObject *o )
1494{
1495 QString name = o->name();
1496 QObject *p = o->parent();
1497 while ( p ) {
1498 name.prepend( QString( p->name() ) + "." );
1499 if ( objs.findRef( p ) != -1 )
1500 break;
1501 p = p->parent();
1502 }
1503 return name;
1504}
1505
1506bool Project::singleProjectMode() const
1507{
1508 return !MainWindow::self || MainWindow::self->singleProjectMode();
1509}
1510
1511QWidget *Project::messageBoxParent() const
1512{
1513 return MainWindow::self;
1514}
1515
1516void Project::designerCreated()
1517{
1518 for ( FormFile *ff = formfiles.first(); ff; ff = formfiles.next() ) {
1519 FormWindow *fw = ff->formWindow();
1520 if ( !fw || fw->mainWindow() )
1521 continue;
1522 fw->setMainWindow( MainWindow::self );
1523 connect( fw, SIGNAL( undoRedoChanged( bool, bool, const QString &,
1524 const QString & ) ),
1525 MainWindow::self, SLOT( updateUndoRedo( bool, bool,
1526 const QString &, const QString & ) ) );
1527 fw->reparent( MainWindow::self->qWorkspace(), QPoint( 0, 0 ), FALSE );
1528 QApplication::sendPostedEvents( MainWindow::self->qWorkspace(),
1529 QEvent::ChildInserted );
1530 fw->parentWidget()->setFixedSize( 1, 1 );
1531 fw->show();
1532 }
1533}
1534
1535void Project::formOpened( FormWindow *fw )
1536{
1537 if ( fw->isFake() )
1538 return;
1539 emit newFormOpened( fw );
1540}
1541
1542QString Project::locationOfObject( QObject *o )
1543{
1544 if ( !o )
1545 return QString::null;
1546
1547 if ( MainWindow::self ) {
1548 QWidgetList windows = MainWindow::self->qWorkspace()->windowList();
1549 for ( QWidget *w = windows.first(); w; w = windows.next() ) {
1550 FormWindow *fw = ::qt_cast<FormWindow*>(w);
1551 SourceEditor *se = ::qt_cast<SourceEditor*>(w);
1552 if ( fw ) {
1553 if ( fw->isFake() )
1554 return objectForFakeForm( fw )->name() + QString( " [Source]" );
1555 else
1556 return fw->name() + QString( " [Source]" );
1557 } else if ( se ) {
1558 if ( !se->object() )
1559 continue;
1560 if ( se->formWindow() )
1561 return se->formWindow()->name() + QString( " [Source]" );
1562 else
1563 return makeRelative( se->sourceFile()->fileName() );
1564 }
1565 }
1566 }
1567
1568 if ( ::qt_cast<SourceFile*>(o) ) {
1569 for ( QPtrListIterator<SourceFile> sources = sourceFiles();
1570 sources.current(); ++sources ) {
1571 SourceFile* f = sources.current();
1572 if ( f == o )
1573 return makeRelative( f->fileName() );
1574 }
1575 }
1576
1577 extern QMap<QWidget*, QString> *qwf_forms;
1578 if ( !qwf_forms ) {
1579 qWarning( "Project::locationOfObject: qwf_forms is NULL!" );
1580 return QString::null;
1581 }
1582
1583 QString s = makeRelative( *qwf_forms->find( (QWidget*)o ) );
1584 s += " [Source]";
1585 return s;
1586}
1587
1588bool Project::hasGUI() const
1589{
1590 return qApp->type() != QApplication::Tty;
1591}
Note: See TracBrowser for help on using the repository browser.