diff options
Diffstat (limited to 'kdevdesigner/designer/project.cpp')
| -rw-r--r-- | kdevdesigner/designer/project.cpp | 1558 | 
1 files changed, 1558 insertions, 0 deletions
| diff --git a/kdevdesigner/designer/project.cpp b/kdevdesigner/designer/project.cpp new file mode 100644 index 00000000..0ab26894 --- /dev/null +++ b/kdevdesigner/designer/project.cpp @@ -0,0 +1,1558 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS.  All rights reserved. +** +**1 This file is part of TQt Designer. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid TQt Enterprise Edition or TQt Professional Edition +** licenses may use this file in accordance with the TQt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +**   information about TQt Commercial License Agreements. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "project.h" +#include "formwindow.h" +#include "designerappiface.h" +#include "../interfaces/languageinterface.h" +#include "pixmapcollection.h" +#ifndef TQT_NO_SQL +#include "dbconnectionimpl.h" +#endif +#include "resource.h" +#include <tqwidgetfactory.h> +#include "outputwindow.h" + +#include <tqfile.h> +#include <tqtextstream.h> +#include <tqurl.h> +#include <tqobjectlist.h> +#include <tqfeatures.h> +#include <tqtextcodec.h> +#include <tqdom.h> +#include <tqmessagebox.h> +#include <tqapplication.h> +#include "mainwindow.h" +#include <tqworkspace.h> + +#ifndef TQT_NO_SQL +#include <tqsqldatabase.h> +#include <tqsqlrecord.h> +#include <tqdatatable.h> +#endif + +#include <stdlib.h> +#ifdef Q_OS_UNIX +# include <unistd.h> +#endif + +#include <tdelocale.h> + +#ifndef TQT_NO_SQL +DatabaseConnection::~DatabaseConnection() +{ +    delete iface; +} + +bool DatabaseConnection::refreshCatalog() +{ +#ifndef TQT_NO_SQL +    if ( loaded ) +	return TRUE; +    if ( !open() ) +	return FALSE; +    tbls = conn->tables( TQSql::TableType( TQSql::Tables | TQSql::Views ) ); +    flds.clear(); +    for ( TQStringList::Iterator it = tbls.begin(); it != tbls.end(); ++it ) { +	TQSqlRecord fil = conn->record( *it ); +	TQStringList lst; +	for ( uint j = 0; j < fil.count(); ++j ) +	    lst << fil.field( j )->name(); +	flds.insert( *it, lst ); +    } +    loaded = TRUE; +    conn->close(); +    return loaded; +#else +    return FALSE; +#endif +} + +#ifndef TQT_NO_SQL +void DatabaseConnection::remove() +{ +    if ( nm == "(default)" ) +	TQSqlDatabase::removeDatabase( TQSqlDatabase::defaultConnection ); +    else +	TQSqlDatabase::removeDatabase( nm ); +    // the above will effectively delete the current connection +    conn = 0; +} +#endif + +bool DatabaseConnection::open( bool suppressDialog ) +{ +#ifndef TQT_NO_SQL +    // register our name, if nec +    if ( nm == "(default)" ) { +	if ( !TQSqlDatabase::contains() ) // default doesn't exists? +	    conn = TQSqlDatabase::addDatabase( drv ); +	else +	    conn = TQSqlDatabase::database(); +    } else { +	if ( !TQSqlDatabase::contains( nm ) ) +	    conn = TQSqlDatabase::addDatabase( drv, nm ); +	else +	    conn = TQSqlDatabase::database( nm ); +    } +    conn->setDatabaseName( dbName ); +    conn->setUserName( uname ); +    conn->setPassword( pword ); +    conn->setHostName( hname ); +    conn->setPort( prt ); +    bool success = conn->open(); +    for( ; suppressDialog == FALSE ; ) { +	bool done = FALSE; +	if ( !success ) { +	    DatabaseConnectionEditor dia( this, 0  , 0 , TRUE ); +	    switch( dia.exec() ) { +	    case TQDialog::Accepted: +		done = FALSE; +		break; +	    case TQDialog::Rejected: +		done = TRUE; +		break; +	    } +	} +	if ( done ) +	    break; +	conn->setUserName( uname ); +	conn->setPassword( pword ); +	conn->setHostName( hname ); +	conn->setPort( prt ); +	success = conn->open(); +	if ( !success ) { +	    switch( TQMessageBox::warning( project->messageBoxParent(), i18n( "Connection" ), +					  i18n( "Could not connect to the database.\n" +							    "Press 'OK' to continue or 'Cancel' to " +							    "specify different\nconnection information.\n" ) +					  + TQString( "[" + conn->lastError().driverText() + "\n" + +						     conn->lastError().databaseText() + "]\n" ), +					  i18n( "&OK" ), +					  i18n( "&Cancel" ), TQString(), 0, 1 ) ) { +	    case 0: // OK or Enter +		continue; +	    case 1: // Cancel or Escape +		done = TRUE; +		break; +	    } +	} else +	    break; +	if ( done ) +	    break; +    } +    if ( !success ) { +	dbErr = conn->lastError().driverText() + "\n" + conn->lastError().databaseText(); +	remove(); +    } +    return success; +#else +    return FALSE; +#endif +} + +void DatabaseConnection::close() +{ +    if ( !loaded ) +	return; +#ifndef TQT_NO_SQL +    if ( conn ) { +	conn->close(); +    } +#endif +} + +DesignerDatabase *DatabaseConnection::iFace() +{ +    if ( !iface ) +	iface = new DesignerDatabaseImpl( this ); +    return iface; +} + +#endif + +//////// + +bool Project::isDummy() const +{ +    return isDummyProject; +} + +Project::Project( const TQString &fn, const TQString &pName, +		  TQPluginManager<ProjectSettingsInterface> *pm, bool isDummy, +		  const TQString &l ) +    : proName( pName ), projectSettingsPluginManager( pm ), isDummyProject( isDummy ) +{ +    modified = TRUE; +    pixCollection = new PixmapCollection( this ); +    iface = 0; +    lang = l; +    is_cpp = lang == "C++"; +    cfg.insert( "(all)", "qt warn_on release" ); +    templ = "app"; +    setFileName( fn ); +    if ( !pName.isEmpty() ) +	proName = pName; +    sourcefiles.setAutoDelete( TRUE ); +    modified = FALSE; +    objs.setAutoDelete( FALSE ); +    fakeFormFiles.setAutoDelete( FALSE ); +} + +Project::~Project() +{ +    if ( singleProjectMode() ) +	removeTempProject(); +    delete iface; +    delete pixCollection; +} + +void Project::setModified( bool b ) +{ +    modified = b; +    emit projectModified(); +} + +#ifndef TQT_NO_SQL +DatabaseConnection *Project::databaseConnection( const TQString &name ) +{ +    for ( DatabaseConnection *conn = dbConnections.first(); +	  conn; +	  conn = dbConnections.next() ) { +	if ( conn->name() == name ) +	    return conn; +    } +    return 0; +} +#endif + +void Project::setFileName( const TQString &fn, bool doClear ) +{ +    if ( fn == filename ) +	return; + +    if ( singleProjectMode() ) { +	TQString qsa = TQString( getenv( "HOME" ) ) + TQString( "/.qsa" ); +	if ( !TQFile::exists( qsa ) ) { +	    TQDir d; +	    d.mkdir( qsa ); +	} +	if ( fn == singleProFileName ) +	    return; +	singleProFileName = fn; +	static int counter = 0; +	TQString str_counter = TQString::number( counter++ ); +	str_counter = "/.qsa/" + str_counter; +	LanguageInterface *iface = MetaDataBase::languageInterface( language() ); +	filename = TQString( getenv( "HOME" ) + str_counter + TQString( "tmp_" ) + +			    TQFileInfo( fn ).baseName() + "/" + TQFileInfo( fn ).baseName() + ".pro" ); +	removeTempProject(); +	if ( iface && iface->supports( LanguageInterface::CompressProject ) ) { +	    filename = iface->uncompressProject( makeAbsolute( singleProFileName ), +						 TQString( getenv( "HOME" ) + +							  str_counter + TQString( "tmp_" ) + +							  TQFileInfo( fn ).baseName() ) ); +	    proName = makeAbsolute( singleProFileName ); +	} +    } else { +	filename = fn; +	if ( !filename.endsWith( ".pro" ) ) +	    filename += ".pro"; +	proName = filename; +    } + + +    if ( proName.contains( '.' ) ) +	proName = proName.left( proName.find( '.' ) ); + +    if ( !doClear ) +	return; +    clear(); +    if ( TQFile::exists( filename ) ) +	parse(); +} + +TQString Project::fileName( bool singlePro ) const +{ +    if ( singlePro ) +	return singleProFileName; +    return filename; +} + +TQString Project::databaseDescription() const +{ +    return dbFile; +} + +TQString Project::projectName() const +{ +    return proName; +} + +static TQString parse_part( const TQString &part ) +{ +    TQString res; +    bool inName = FALSE; +    TQString currName; +    for ( int i = 0; i < (int)part.length(); ++i ) { +	TQChar c = part[ i ]; +	if ( !inName ) { +	    if ( c != ' ' && c != '\t' && c != '\n' && c != '=' && c != '\\' && c != '+' ) +		inName = TRUE; +	    else +		continue; +	} +	if ( inName ) { +	    if ( c == '\n' ) +		break; +	    res += c; +	} +    } +    return res; +} + +TQStringList parse_multiline_part( const TQString &contents, const TQString &key, int *start = 0 ) +{ +    if ( start ) +	*start = -1; +    TQString lastWord; +    // Account for things like win32: SOURCES +    int extraWhiteSpaceCount = 0; +    int braceCount = 0; +    for ( int i = 0; i < (int)contents.length(); ++i ) { +	TQChar c( contents[ i ] ); +	switch ( c ) { +	case '{': +	    braceCount++; +	    lastWord = ""; +	    break; +	case '}': +	    braceCount--; +	    lastWord = ""; +	    break; +	case ' ': case '\t': +	    if (!key.startsWith(lastWord)) { +		lastWord = ""; +		extraWhiteSpaceCount = 0; +	    } else { +		extraWhiteSpaceCount++; +	    } +	    break; +	case '\\': case '\n': +	    lastWord = ""; +	    break; +	default: +	    lastWord += c; +	} + +	// ### we should read the 'bla { SOURCES= ... }' stuff as well (braceCount > 0) +	if ( lastWord == key && braceCount == 0 ) { +	    if ( start ) +		*start = i - lastWord.length() - extraWhiteSpaceCount + 1; +	    TQStringList lst; +	    bool inName = FALSE; +	    TQString currName; +	    bool hadEqual = FALSE; +	    for ( ; i < (int)contents.length(); ++i ) { +		c = contents[ i ]; +		if ( !hadEqual && c != '=' ) +		    continue; +		if ( !hadEqual ) { +		    hadEqual = TRUE; +		    continue; +		} +		if ( ( c.isLetter() || c.isDigit() || c == '.' || c == '/' || c == '_' || c == '\\' || +		       c == '\"' || c == '\'' || c == '=' || +		       c == '$' || c == '-' || c == '(' || c == ')' || c == ':'  || c == '+' || c == ',' || c == '~' ) && +		     c != ' ' && c != '\t' && c != '\n' ) { +		    if ( !inName ) +			currName = TQString(); +		    if ( c != '\\' || contents[i+1] != '\n' ) { +			currName += c; +			inName = TRUE; +		    } +		} else { +		    if ( inName ) { +			inName = FALSE; +			if ( currName.simplifyWhiteSpace() != "\\" ) +			    lst.append( currName ); +		    } +		    if ( c == '\n' && i > 0 && contents[ (int)i - 1 ] != '\\' ) +			break; +		} +	    } +	    return lst; +	} +    } + +    return TQStringList(); +} + +void Project::parse() +{ +    TQFile f( filename ); +    if ( !f.exists() || !f.open( IO_ReadOnly ) ) +	return; +    TQTextStream ts( &f ); +    TQString contents = ts.read(); +    f.close(); + +    proName = TQFileInfo( filename ).baseName(); + +    TQStringList::ConstIterator it; + +    int i = contents.find( "LANGUAGE" ); +    if ( i != -1 ) { +	lang = ""; +	is_cpp = FALSE; +	TQString part = contents.mid( i + TQString( "LANGUAGE" ).length() ); +	lang = parse_part( part ); +	is_cpp = lang == "C++"; +    } + +    i = contents.find( "DBFILE" ); +    if ( i != -1 ) { +	dbFile = ""; +	TQString part = contents.mid( i + TQString( "DBFILE" ).length() ); +	dbFile = parse_part( part ); +    } + +    TQStringList uifiles = parse_multiline_part( contents, "FORMS" ); +    uifiles += parse_multiline_part( contents, "INTERFACES" ); // compatibility +    for ( it = uifiles.begin(); it != uifiles.end(); ++it ) { +	if ( (*it).startsWith( "__APPOBJ" ) ) +	    continue; +	(void) new FormFile( *it, FALSE, this ); +    } + + +    i = contents.find( "TEMPLATE" ); +    if ( i != -1 ) { +	templ = ""; +	TQString part = contents.mid( i + TQString( "TEMPLATE" ).length() ); +	templ = parse_part( part ); +    } + +    readPlatformSettings( contents, "CONFIG", cfg ); +    readPlatformSettings( contents, "LIBS", lbs ); +    readPlatformSettings( contents, "INCLUDEPATH", inclPath ); +    readPlatformSettings( contents, "DEFINES", defs ); +    readPlatformSettings( contents, "SOURCES", sources ); +    readPlatformSettings( contents, "HEADERS", headers ); + +    LanguageInterface *iface = MetaDataBase::languageInterface( lang ); +    if ( iface ) { +	TQStringList sourceKeys; +	iface->sourceProjectKeys( sourceKeys ); +	for ( TQStringList::Iterator it = sourceKeys.begin(); it != sourceKeys.end(); ++it ) { +	    TQStringList lst = parse_multiline_part( contents, *it ); +	    for ( TQStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) +		(void) new SourceFile( *it, FALSE, this ); +	} +    } + +    updateCustomSettings(); + +    for ( it = csList.begin(); it != csList.end(); ++it ) { +	i = contents.find( *it ); +	if ( i != -1 ) { +	    TQString val = ""; +	    TQString part = contents.mid( i + TQString( *it ).length() ); +	    val = parse_part( part ); +	    customSettings.replace( *it, val ); +	} +    } + +    loadConnections(); + +    TQStringList images = parse_multiline_part( contents, "IMAGES" ); + +    // ### remove that for the final - this is beta-compatibility +    if ( images.isEmpty() && TQDir( TQFileInfo( filename ).dirPath( TRUE ) + "/images" ).exists() ) { +	    images = TQDir( TQFileInfo( filename ).dirPath( TRUE ) + "/images" ).entryList(); +	    for ( int i = 0; i < (int)images.count(); ++i ) +		images[ i ].prepend( "images/" ); +	    modified = TRUE; +    } + +    for ( TQStringList::ConstIterator pit = images.begin(); pit != images.end(); ++pit ) +	pixCollection->load( *pit ); +} + +void Project::clear() +{ +    dbFile = ""; +    proName = "unnamed"; +    desc = ""; +} + +bool Project::removeSourceFile( SourceFile *sf ) +{ +    if ( !sourcefiles.containsRef( sf ) ) +	return FALSE; +    if ( !sf->close() ) +	return FALSE; +    sourcefiles.removeRef( sf ); +    modified = TRUE; +    emit sourceFileRemoved( sf ); +    return TRUE; +} + +void Project::setDatabaseDescription( const TQString &db ) +{ +    dbFile = db; +} + +void Project::setDescription( const TQString &s ) +{ +    desc = s; +} + +TQString Project::description() const +{ +    return desc; +} + + +bool Project::isValid() const +{ +     // #### do more checking here? +    if ( filename.isEmpty() || proName.isEmpty() ) +	return FALSE; + +    return TRUE; +} + +TQString Project::makeAbsolute( const TQString &f ) +{ +    if ( isDummy() ) +	return f; +    TQString encodedUrl = TQFileInfo( filename ).dirPath( TRUE ); +    TQUrl::encode( encodedUrl ); +    TQUrl u( encodedUrl, f ); +    return u.path(); +} + +TQString Project::makeRelative( const TQString &f ) +{ +    if ( isDummy() ) +	return f; +    TQString p = TQFileInfo( filename ).dirPath( TRUE ); +    TQString f2 = f; +    if ( f2.left( p.length() ) == p ) +	f2.remove( 0, p.length() + 1 ); +    return f2; +} + +static void remove_contents( TQString &contents, const TQString &s ) +{ +    int i = contents.find( s ); +    if ( i != -1 ) { +	int start = i; +	int end = contents.find( '\n', i ); +	if ( end == -1 ) +	    end = contents.length() - 1; +	contents.remove( start, end - start + 1 ); +    } +} + +static void remove_multiline_contents( TQString &contents, const TQString &s, int *strt = 0 ) +{ +    int i = contents.find( s ); +    if ( strt ) +	*strt = i; +    int start = i; +    bool lastWasBackspash = FALSE; +    if ( i != -1 && ( i == 0 || contents[ i - 1 ] != '{' || contents[ i - 1 ] != ':' ) ) { +	for ( ; i < (int)contents.length(); ++i ) { +	    if ( contents[ i ] == '\n' && !lastWasBackspash ) +		break; +	    lastWasBackspash = ( contents[ i ] == '\\' || +				 lastWasBackspash && ( contents[ i ] == ' ' || contents[ i ] == '\t' ) ); +	} +	contents.remove( start, i - start + 1 ); +    } +} + +void Project::save( bool onlyProjectFile ) +{ +    bool anythingModified = FALSE; + +    //  save sources and forms +    if ( !onlyProjectFile ) { + +	saveConnections(); + +	for ( SourceFile *sf = sourcefiles.first(); sf; sf = sourcefiles.next() ) { +	    anythingModified = anythingModified || sf->isModified(); +	    if ( !sf->save() ) +		return; +	} + +	for ( FormFile *ff = formfiles.first(); ff; ff = formfiles.next() ) { +	    anythingModified = anythingModified || ff->isModified(); +	    if ( !ff->save() ) +		return; +	} +    } + +    if ( isDummy() || filename.isEmpty() ) +	return; + +    if ( !modified ) { +	if ( singleProjectMode() ) { +	    LanguageInterface *iface = MetaDataBase::languageInterface( language() ); +	    if ( iface && iface->supports( LanguageInterface::CompressProject ) ) +		iface->compressProject( makeAbsolute( filename ), singleProFileName, anythingModified ); +	} + 	return; +    } + +    TQFile f( filename ); +    TQString original = ""; + +    // read the existing file +    bool hasPreviousContents = FALSE; +    if ( f.open( IO_ReadOnly ) ) { +	TQTextStream ts( &f ); +	original = ts.read(); +	f.close(); +	hasPreviousContents = TRUE; +	remove_contents( original, "{SOURCES+=" ); // ### compatibility with early 3.0 betas +	remove_contents( original, "DBFILE" ); +	remove_contents( original, "LANGUAGE" ); +	remove_contents( original, "TEMPLATE" ); +	removePlatformSettings( original, "CONFIG" ); +	removePlatformSettings( original, "DEFINES" ); +	removePlatformSettings( original, "LIBS" ); +	removePlatformSettings( original, "INCLUDEPATH" ); +	removePlatformSettings( original, "SOURCES" ); +	removePlatformSettings( original, "HEADERS" ); +	remove_multiline_contents( original, "FORMS" ); +	remove_multiline_contents( original, "INTERFACES" ); // compatibility +	remove_multiline_contents( original, "IMAGES" ); +	for ( TQStringList::Iterator it = csList.begin(); it != csList.end(); ++it ) +	    remove_contents( original, *it ); +    } + +    // the contents of the saved file +    TQString contents; + +    // template +    contents += "TEMPLATE\t= " + templ + "\n"; + +    // language +    contents += "LANGUAGE\t= " + lang + "\n"; +    contents += "\n"; + +    // config +    writePlatformSettings( contents, "CONFIG", cfg ); +    LanguageInterface *iface = MetaDataBase::languageInterface( lang ); +    if ( iface ) { +	TQStringList sourceKeys; +	iface->sourceProjectKeys( sourceKeys ); +	for ( TQStringList::Iterator spit = sourceKeys.begin(); spit != sourceKeys.end(); ++spit ) +	    remove_multiline_contents( contents, *spit ); +    } +    contents += "\n"; + +    // libs, defines, includes +    writePlatformSettings( contents, "LIBS", lbs ); +    writePlatformSettings( contents, "DEFINES", defs ); +    writePlatformSettings( contents, "INCLUDEPATH", inclPath ); +    writePlatformSettings( contents, "SOURCES", sources ); +    writePlatformSettings( contents, "HEADERS", headers ); + +    // unix +    if ( !hasPreviousContents ) { + 	contents += + 	    "unix {\n" + 	    "  UI_DIR = .ui\n" + 	    "  MOC_DIR = .moc\n" + 	    "  OBJECTS_DIR = .obj\n" + 	    "}\n"; +    } +    contents += "\n"; + +    // sources +    if ( !sourcefiles.isEmpty() && iface ) { +	TQMap<TQString, TQStringList> sourceToKey; +	for ( SourceFile *f = sourcefiles.first(); f; f = sourcefiles.next() ) { +	    TQString key = iface->projectKeyForExtension( TQFileInfo( f->fileName() ).extension() ); +	    TQStringList lst = sourceToKey[ key ]; +	    lst << makeRelative( f->fileName() ); +	    sourceToKey.replace( key, lst ); +	} + +	for ( TQMap<TQString, TQStringList>::Iterator skit = sourceToKey.begin(); +	      skit != sourceToKey.end(); ++skit ) { +	    TQString part = skit.key() + "\t+= "; +	    TQStringList lst = *skit; +	    for ( TQStringList::Iterator sit = lst.begin(); sit != lst.end(); ++sit ) { +		part += *sit; +		part += ++sit != lst.end() ? " \\\n\t" : ""; +		--sit; +	    } +	    part += "\n"; +	    contents += part; +	} +    } + +    // forms and interfaces +    if ( !formfiles.isEmpty() ) { +	contents += "FORMS\t= "; +	for ( TQPtrListIterator<FormFile> fit = formfiles; fit.current(); ++fit ) { +	    contents += fit.current()->fileName() + +		 (fit != formfiles.last() ? " \\\n\t" : ""); +	} +	contents += "\n"; +    } + +    // images +     if ( !pixCollection->isEmpty() ) { +	contents += "IMAGES\t= "; +	TQValueList<PixmapCollection::Pixmap> pixmaps = pixCollection->pixmaps(); +	for ( TQValueList<PixmapCollection::Pixmap>::Iterator it = pixmaps.begin(); +	      it != pixmaps.end(); ++it ) { +		  contents += makeRelative( (*it).absname ); +		  contents += ++it != pixmaps.end() ? " \\\n\t" : ""; +		  --it; +	} +	contents += "\n"; +    } + +    // database +    if ( !dbFile.isEmpty() ) +	contents += "DBFILE\t= " + dbFile + "\n"; +    contents += "\n"; + +    // custom settings +    for ( TQStringList::Iterator it = csList.begin(); it != csList.end(); ++it ) { +	TQString val = *customSettings.find( *it ); +	if ( !val.isEmpty() ) +	    contents += *it + "\t= " + val + "\n"; +    } + +    if ( !f.open( IO_WriteOnly | IO_Translate ) ) { +	TQMessageBox::warning( messageBoxParent(), +			      "Save Project Failed", "Couldn't write project file " + filename ); +	return; +    } + +    TQTextStream os( &f ); +    os << contents; +    if (hasPreviousContents) +        os << original; + +    f.close(); + +    setModified( FALSE ); + +    if ( singleProjectMode() ) { +	LanguageInterface *iface = MetaDataBase::languageInterface( language() ); +	if ( iface && iface->supports( LanguageInterface::CompressProject ) ) +	    iface->compressProject( makeAbsolute( filename ), singleProFileName, TRUE ); +    } +} + +#ifndef TQT_NO_SQL +TQPtrList<DatabaseConnection> Project::databaseConnections() const +{ +    return dbConnections; +} +#endif + +#ifndef TQT_NO_SQL +void Project::setDatabaseConnections( const TQPtrList<DatabaseConnection> &lst ) +{ +    dbConnections = lst; +} +#endif + +#ifndef TQT_NO_SQL +void Project::addDatabaseConnection( DatabaseConnection *conn ) +{ +    dbConnections.append( conn ); +    modified = TRUE; +} +#endif + +#ifndef TQT_NO_SQL +void Project::removeDatabaseConnection( const TQString &c ) +{ +    for ( DatabaseConnection *conn = dbConnections.first(); conn; conn = dbConnections.next() ) { +	if ( conn->name() == c ) { +	    conn->remove(); +	    dbConnections.removeRef( conn ); +	    delete conn; +	    return; +	} +    } +} +#endif + +#ifndef TQT_NO_SQL +TQStringList Project::databaseConnectionList() +{ +    TQStringList lst; +    for ( DatabaseConnection *conn = dbConnections.first(); conn; conn = dbConnections.next() ) +	lst << conn->name(); +    return lst; +} +#endif + +#ifndef TQT_NO_SQL +TQStringList Project::databaseTableList( const TQString &connection ) +{ +    DatabaseConnection *conn = databaseConnection( connection ); +    if ( !conn ) { +	return TQStringList(); +    } +    return conn->tables(); +} +#endif + +#ifndef TQT_NO_SQL +TQStringList Project::databaseFieldList( const TQString &connection, const TQString &table ) +{ +    DatabaseConnection *conn = databaseConnection( connection ); +    if ( !conn ) +	return TQStringList(); +    return conn->fields( table ); +} +#endif + +#ifndef TQT_NO_SQL +static TQString makeIndent( int indent ) +{ +    TQString s; +    s.fill( ' ', indent * 4 ); +    return s; +} +#endif + +#ifndef TQT_NO_SQL +static void saveSingleProperty( TQTextStream &ts, const TQString& name, const TQString& value, int indent ) +{ +    ts << makeIndent( indent ) << "<property name=\"" << name << "\">" << endl; +    ++indent; +    ts << makeIndent( indent ) << "<string>" << value << "</string>" << endl; +    --indent; +    ts << makeIndent( indent ) << "</property>" << endl; +} +#endif + +void Project::saveConnections() +{ +#ifndef TQT_NO_SQL +    if ( dbFile.isEmpty() ) { +	TQFileInfo fi( fileName() ); +	setDatabaseDescription( fi.baseName() + ".db" ); +    } + +    TQFile f( makeAbsolute( dbFile ) ); + +    if ( dbConnections.isEmpty() ) { +	if ( f.exists() ) +	    f.remove(); +	setDatabaseDescription( "" ); +	modified = TRUE; +	return; +    } + +    /* .db xml */ +    if ( f.open( IO_WriteOnly | IO_Translate ) ) { +	TQTextStream ts( &f ); +	ts.setCodec( TQTextCodec::codecForName( "UTF-8" ) ); +	ts << "<!DOCTYPE DB><DB version=\"1.0\">" << endl; + +	/* db connections */ +	int indent = 0; +	for ( DatabaseConnection *conn = dbConnections.first(); conn; conn = dbConnections.next() ) { +	    ts << makeIndent( indent ) << "<connection>" << endl; +	    ++indent; +	    saveSingleProperty( ts, "name", conn->name(), indent ); +	    saveSingleProperty( ts, "driver", conn->driver(), indent ); +	    saveSingleProperty( ts, "database", conn->database(), indent ); +	    saveSingleProperty( ts, "username", conn->username(), indent ); +	    saveSingleProperty( ts, "hostname", conn->hostname(), indent ); +	    saveSingleProperty( ts, "port", TQString::number( conn->port() ), indent ); + +	    /* connection tables */ +	    TQStringList tables = conn->tables(); +	    for ( TQStringList::Iterator it = tables.begin(); +		  it != tables.end(); ++it ) { +		ts << makeIndent( indent ) << "<table>" << endl; +		++indent; +		saveSingleProperty( ts, "name", (*it), indent ); + +		/* tables fields */ +		TQStringList fields = conn->fields( *it ); +		for ( TQStringList::Iterator it2 = fields.begin(); +		      it2 != fields.end(); ++it2 ) { +		    ts << makeIndent( indent ) << "<field>" << endl; +		    ++indent; +		    saveSingleProperty( ts, "name", (*it2), indent ); +		    --indent; +		    ts << makeIndent( indent ) << "</field>" << endl; +		} + +		--indent; +		ts << makeIndent( indent ) << "</table>" << endl; +	    } + +	    --indent; +	    ts << makeIndent( indent ) << "</connection>" << endl; +	} + +	ts << "</DB>" << endl; +	f.close(); +    } +#endif +} + +#ifndef TQT_NO_SQL +static TQDomElement loadSingleProperty( TQDomElement e, const TQString& name ) +{ +    TQDomElement n; +    for ( n = e.firstChild().toElement(); +	  !n.isNull(); +	  n = n.nextSibling().toElement() ) { +	if ( n.tagName() == "property" && n.toElement().attribute("name") == name ) +	    return n; +    } +    return n; +} +#endif + +void Project::loadConnections() +{ +#ifndef TQT_NO_SQL +    if ( dbFile.isEmpty() || !TQFile::exists( makeAbsolute( dbFile ) ) ) +	return; + +    TQFile f( makeAbsolute( dbFile ) ); +    if ( f.open( IO_ReadOnly ) ) { +	TQDomDocument doc; +	TQString errMsg; +	int errLine; +	if ( doc.setContent( &f, &errMsg, &errLine ) ) { +	    TQDomElement e; +	    e = doc.firstChild().toElement(); + +	    /* connections */ +	    TQDomNodeList connections = e.toElement().elementsByTagName( "connection" ); +	    for ( uint i = 0; i <  connections.length(); i++ ) { +		TQDomElement connection = connections.item(i).toElement(); +		TQDomElement connectionName = loadSingleProperty( connection, "name" ); +		TQDomElement connectionDriver = loadSingleProperty( connection, "driver" ); +		TQDomElement connectionDatabase = loadSingleProperty( connection, +								     "database" ); +		TQDomElement connectionUsername = loadSingleProperty( connection, +								     "username" ); +		TQDomElement connectionHostname = loadSingleProperty( connection, +								     "hostname" ); +		TQDomElement connectionPort = loadSingleProperty( connection, +								     "port" ); + +		DatabaseConnection *conn = new DatabaseConnection( this ); +		conn->setName( connectionName.firstChild().firstChild().toText().data() ); +		conn->setDriver( connectionDriver.firstChild().firstChild().toText().data() ); +		conn->setDatabase( connectionDatabase.firstChild().firstChild().toText().data() ); +		conn->setUsername( connectionUsername.firstChild().firstChild().toText().data() ); +		conn->setHostname( connectionHostname.firstChild().firstChild().toText().data() ); +		conn->setPort( TQString( connectionPort.firstChild().firstChild().toText().data() ).toInt() ); + +		/* connection tables */ +		TQDomNodeList tables = connection.toElement().elementsByTagName( "table" ); +		for ( uint j = 0; j <  tables.length(); j++ ) { +		    TQDomElement table = tables.item(j).toElement(); +		    TQDomElement tableName = loadSingleProperty( table, "name" ); +		    conn->addTable( tableName.firstChild().firstChild().toText().data() ); + +		    /* table fields */ +		    TQStringList fieldList; +		    TQDomNodeList fields = table.toElement().elementsByTagName( "field" ); +		    for ( uint k = 0; k <  fields.length(); k++ ) { +			TQDomElement field = fields.item(k).toElement(); +			TQDomElement fieldName = loadSingleProperty( field, "name" ); +			fieldList.append( fieldName.firstChild().firstChild().toText().data() ); +		    } +		    conn->setFields( tableName.firstChild().firstChild().toText().data(), +					 fieldList ); +		} + +		dbConnections.append( conn ); +	    } +	} else { +	    tqDebug( TQString("Parse error: ") + errMsg + TQString(" in line %d"), errLine ); +	} +	f.close(); +    } +#endif +} + +/*! Opens the database \a connection.  The connection remains open and +can be closed again with closeDatabase(). +*/ + +bool Project::openDatabase( const TQString &connection, bool suppressDialog ) +{ +#ifndef TQT_NO_SQL +    DatabaseConnection *conn = databaseConnection( connection ); +    if ( connection.isEmpty() && !conn ) +	conn = databaseConnection( "(default)" ); +    if ( !conn ) +	return FALSE; +    bool b = conn->open( suppressDialog ); +    return b; +#else +    Q_UNUSED( connection ); +    Q_UNUSED( suppressDialog ); +    return FALSE; +#endif +} + +/*! Closes the database \a connection. +*/ +void Project::closeDatabase( const TQString &connection ) +{ +#ifndef TQT_NO_SQL +    DatabaseConnection *conn = databaseConnection( connection ); +    if ( connection.isEmpty() && !conn ) +	conn = databaseConnection( "(default)" ); +    if ( !conn ) +	return; +    conn->close(); +#else +    Q_UNUSED( connection ); +#endif +} + +// void Project::formClosed( FormWindow *fw ) +// { +//     formWindows.remove( fw ); +// } + +TQObjectList *Project::formList( bool resolveFakeObjects ) const +{ +    TQObjectList *l = new TQObjectList; +    for ( TQPtrListIterator<FormFile> forms(formfiles);   forms.current(); ++forms ) { +	FormFile* f = forms.current(); +	if ( f->formWindow() ) { +	    if ( resolveFakeObjects && f->formWindow()->isFake() ) +		l->append( objectForFakeForm( f->formWindow() ) ); +	    else +		l->append( f->formWindow()->child( 0, TQWIDGET_OBJECT_NAME_STRING ) ); +	} else if ( f->isFake() ) { +	    l->append( objectForFakeFormFile( f ) ); +	} +    } +    return l; +} + +DesignerProject *Project::iFace() +{ +    if ( !iface ) +	iface = new DesignerProjectImpl( this ); +    return iface; +} + +void Project::setLanguage( const TQString &l ) +{ +    if ( l == lang ) +	return; +    lang = l; +    is_cpp = lang == "C++"; +    updateCustomSettings(); +    modified = TRUE; +} + +TQString Project::language() const +{ +    return lang; +} + +void Project::setCustomSetting( const TQString &key, const TQString &value ) +{ +    customSettings.remove( key ); +    customSettings.insert( key, value ); +    modified = TRUE; +} + +TQString Project::customSetting( const TQString &key ) const +{ +    return *customSettings.find( key ); +} + +void Project::updateCustomSettings() +{ +    if ( !projectSettingsPluginManager ) +	return; + +/* +    ProjectSettingsInterface *iface = 0; +    projectSettingsPluginManager->queryInterface( lang, (TQUnknownInterface**)&iface ); +    if ( !iface ) +	return; +    csList = iface->projectSettings(); +    iface->release(); +*/ + +    TQInterfacePtr<ProjectSettingsInterface> iface; +    projectSettingsPluginManager->queryInterface( lang, &iface ); +    if ( !iface ) +	return; +    csList = iface->projectSettings(); +    customSettings.clear(); + +} + +void Project::setActive( bool b ) +{ +    pixCollection->setActive( b ); +} + +void Project::addSourceFile( SourceFile *sf ) +{ +    sourcefiles.append( sf ); +    modified = TRUE; +    emit sourceFileAdded( sf ); +} + + +SourceFile* Project::findSourceFile( const TQString& filename, SourceFile *ignore ) const +{ +    TQPtrListIterator<SourceFile> it(sourcefiles); +    while ( it.current() ) { +	if ( it.current() != ignore && it.current()->fileName() == filename ) +	    return it.current(); +	++it; +    } +    return 0; +} + +FormFile* Project::findFormFile( const TQString& filename, FormFile *ignore ) const +{ +    TQPtrListIterator<FormFile> it(formfiles); +    while ( it.current() ) { +	if ( it.current() != ignore && it.current()->fileName() == filename ) +	    return it.current(); +	++it; +    } +    return 0; +} + +void Project::setIncludePath( const TQString &platform, const TQString &path ) +{ +    if ( inclPath[platform] == path ) +	return; +    inclPath.replace( platform, path ); +    modified = TRUE; +} + +void Project::setLibs( const TQString &platform, const TQString &path ) +{ +    lbs.replace( platform, path ); +} + +void Project::setDefines( const TQString &platform, const TQString &path ) +{ +    defs.replace( platform, path ); +} + +void Project::setConfig( const TQString &platform, const TQString &config ) +{ +    cfg.replace( platform, config ); +} + +TQString Project::config( const TQString &platform ) const +{ +    return cfg[ platform ]; +} + +TQString Project::libs( const TQString &platform ) const +{ +    return lbs[ platform ]; +} + +TQString Project::defines( const TQString &platform ) const +{ +    return defs[ platform ]; +} + +TQString Project::includePath( const TQString &platform ) const +{ +    return inclPath[ platform ]; +} + +TQString Project::templte() const +{ +    return templ; +} + +void Project::setTemplate( const TQString &t ) +{ +    templ = t; +} + +void Project::readPlatformSettings( const TQString &contents, +				    const TQString &setting, +				    TQMap<TQString, TQString> &res ) +{ +    const TQString platforms[] = { "", "win32", "unix", "mac", TQString() }; +    for ( int i = 0; platforms[ i ] != TQString(); ++i ) { +	TQString p = platforms[ i ]; +	if ( !p.isEmpty() ) +	    p += ":"; +	TQStringList lst = parse_multiline_part( contents, p + setting ); +	TQString s = lst.join( " " ); +	TQString key = platforms[ i ]; +	if ( key.isEmpty() ) +	    key = "(all)"; +	res.replace( key, s ); +    } +} + +void Project::removePlatformSettings( TQString &contents, const TQString &setting ) +{ +    const TQString platforms[] = { "win32", "unix", "mac", "", TQString() }; +    for ( int i = 0; platforms[ i ] != TQString(); ++i ) { +	TQString p = platforms[ i ]; +	if ( !p.isEmpty() ) +	    p += ":"; +	remove_multiline_contents( contents, p + setting ); +    } +} + +void Project::writePlatformSettings( TQString &contents, const TQString &setting, +				     const TQMap<TQString, TQString> &input ) +{ +    const TQString platforms[] = { "", "win32", "unix", "mac", TQString() }; +    int i; +    LanguageInterface *iface = MetaDataBase::languageInterface( lang ); +    if (iface && (setting == "SOURCES" || setting == "HEADERS")) // The (all) part will be saved later on +        i = 1; +    else +	i = 0; +    for (; platforms[ i ] != TQString(); ++i ) { +	TQString p = platforms[ i ]; +	if ( !p.isEmpty() ) +	    p += ":"; +	TQString key = platforms[ i ]; +	if ( key.isEmpty() ) +	    key = "(all)"; +	TQMap<TQString, TQString>::ConstIterator it = input.find( key ); +	if ( it == input.end() || (*it).isEmpty() ) +	    continue; +	contents += p + setting + "\t+= " + *it + "\n"; +    } +} + +void Project::addFormFile( FormFile *ff ) +{ +    formfiles.append( ff ); +    modified = TRUE; +    emit formFileAdded( ff ); +} + +bool Project::removeFormFile( FormFile *ff ) +{ +    if ( !formfiles.containsRef( ff ) ) +	return FALSE; +    if ( !ff->close() ) +	return FALSE; +    formfiles.removeRef( ff ); +    modified = TRUE; +    emit formFileRemoved( ff ); +    return TRUE; +} + +void Project::addObject( TQObject *o ) +{ +    bool wasModified = modified; +    objs.append( o ); +    FormFile *ff = new FormFile( "", FALSE, this, "qt_fakewindow" ); +    ff->setFileName( "__APPOBJ" + TQString( o->name() ) + ".ui" ); +    fakeFormFiles.insert( (void*)o, ff ); +    MetaDataBase::addEntry( o ); +    if ( hasGUI() ) { +	TQWidget *parent = MainWindow::self ? MainWindow::self->qWorkspace() : 0; +	FormWindow *fw = new FormWindow( ff, MainWindow::self, parent, "qt_fakewindow" ); +	fw->setProject( this ); +	if ( TQFile::exists( ff->absFileName() ) ) +	    Resource::loadExtraSource( ff, ff->absFileName(), +				       MetaDataBase::languageInterface( language() ), FALSE ); +	if ( MainWindow::self ) +	    fw->setMainWindow( MainWindow::self ); +	if ( MainWindow::self ) { +	    TQApplication::sendPostedEvents( MainWindow::self->qWorkspace(), TQEvent::ChildInserted ); +	    connect( fw, +		     TQT_SIGNAL( undoRedoChanged( bool, bool, const TQString &, const TQString & ) ), +		     MainWindow::self, +		     TQT_SLOT( updateUndoRedo( bool, bool, const TQString &, const TQString & ) ) +		); +	} +	if ( fw->parentWidget() ) { +	    fw->parentWidget()->setFixedSize( 1, 1 ); +	    fw->show(); +	} +    } else { +	if ( TQFile::exists( ff->absFileName() ) ) +	    Resource::loadExtraSource( ff, ff->absFileName(), +				       MetaDataBase::languageInterface( language() ), FALSE ); +    } +    emit objectAdded( o ); +    modified = wasModified; +} + +void Project::setObjects( const TQObjectList &ol ) +{ +    for ( TQObjectListIt it( ol ); it.current(); ++it ) +	addObject( it.current() ); +} + +void Project::removeObject( TQObject *o ) +{ +    bool wasModified = modified; +    objs.removeRef( o ); +    MetaDataBase::removeEntry( o ); +    fakeFormFiles.remove( (void*)o ); +    emit objectRemoved( o ); +    modified = wasModified; +} + +TQObjectList Project::objects() const +{ +    return objs; +} + +FormFile *Project::fakeFormFileFor( TQObject *o ) const +{ +    return fakeFormFiles.find( (void*)o ); +} + +TQObject *Project::objectForFakeForm( FormWindow *fw ) const +{ +    for ( TQPtrDictIterator<FormFile> it( fakeFormFiles ); it.current(); ++it ) { +	if ( it.current()->formWindow() == fw || +	    it.current() == fw->formFile() ) +	    return (TQObject*)it.currentKey(); +    } +    return 0; +} + +TQObject *Project::objectForFakeFormFile( FormFile *ff ) const +{ +    for ( TQPtrDictIterator<FormFile> it( fakeFormFiles ); it.current(); ++it ) { +	if ( it.current() == ff ) +	    return (TQObject*)it.currentKey(); +    } +    return 0; +} + +void Project::removeTempProject() +{ +    if ( !singleProjectMode() ) +	return; +    TQDir d( TQFileInfo( filename ).dirPath() ); +    if ( !d.exists( TQFileInfo( filename ).dirPath() ) ) +	return; +    TQStringList files = d.entryList( TQDir::Files ); +    TQStringList::Iterator it; +    for ( it = files.begin(); it != files.end(); ++it ) { +	d.remove( *it ); +    } +    if ( d.exists( TQFileInfo( filename ).dirPath() + "/images" ) ) { +	d = TQDir( TQFileInfo( filename ).dirPath() + "/images" ); +	files = d.entryList( TQDir::Files ); +	for ( it = files.begin(); it != files.end(); ++it ) +	    d.remove( *it ); +	d = TQDir( TQFileInfo( filename ).dirPath() ); +	d.remove( "images" ); +    } +    d.remove( TQFileInfo( filename ).dirPath() ); +#if defined(Q_OS_UNIX) +    // ##### implement for all platforms, ideally should be in TQt +    ::rmdir( TQFile::encodeName( d.absPath() ) ); +#endif +} + +void Project::addAndEditFunction( const TQString &function, const TQString &functionBody, bool openDeveloper ) +{ +    for ( SourceFile *f = sourcefiles.first(); f; f = sourcefiles.next() ) { +	if ( TQFileInfo( f->fileName() ).baseName() == "main" ) { +	    TQValueList<LanguageInterface::Function> funcs; +	    LanguageInterface *iface = MetaDataBase::languageInterface( language() ); +	    if ( !iface ) +		return; +	    iface->functions( f->text(), &funcs ); +	    TQString func = function; +	    int i = func.find( '(' ); +	    if ( i != -1 ) +		func = func.left( i ); + +	    bool found = FALSE; +	    for ( TQValueList<LanguageInterface::Function>::Iterator it = funcs.begin(); +		  it != funcs.end(); ++it ) { +		if ( (*it).name.left( (*it).name.find( '(' ) ) == func ) { +		    found = TRUE; +		    break; +		} +	    } + +	    if ( !found ) { +		TQString code = f->text(); +		if ( functionBody.isEmpty() ) +		    code += "\n\n" + iface->createFunctionStart( "", func, "", "" ) + "()\n{\n\n}\n"; +		else +		    code += "\n\n" + iface->createFunctionStart( "", func, "", "" ) + +			    "()\n" + functionBody + "\n"; +		f->setText( code ); +		if ( f->editor() ) +		    f->editor()->refresh( FALSE ); +	    } + +	    if ( openDeveloper ) { +		if ( MainWindow::self ) +		    MainWindow::self->editSource( f ); +		f->editor()->setFunction( func, "" ); +	    } + +	    break; +	} +    } +} + +bool Project::hasParentObject( TQObject *o ) +{ +    for ( TQObject *p = objs.first(); p; p = objs.next() ) { +	TQObject *c = p->child( o->name(), o->className() ); +	if ( c ) +	    return TRUE; +    } +    return FALSE; +} + +TQString Project::qualifiedName( TQObject *o ) +{ +    TQString name = o->name(); +    TQObject *p = o->parent(); +    while ( p ) { +	name.prepend( TQString( p->name() ) + "." ); +	if ( objs.findRef( p ) != -1 ) +	    break; +	p = p->parent(); +    } +    return name; +} + +bool Project::singleProjectMode() const +{ +    return !MainWindow::self || MainWindow::self->singleProjectMode(); +} + +TQWidget *Project::messageBoxParent() const +{ +    return MainWindow::self; +} + +void Project::designerCreated() +{ +    for ( FormFile *ff = formfiles.first(); ff; ff = formfiles.next() ) { +	FormWindow *fw = ff->formWindow(); +	if ( !fw || fw->mainWindow() ) +	    continue; +	fw->setMainWindow( MainWindow::self ); +	connect( fw, TQT_SIGNAL( undoRedoChanged( bool, bool, const TQString &, +					      const TQString & ) ), +		 MainWindow::self, TQT_SLOT( updateUndoRedo( bool, bool, +					 const TQString &, const TQString & ) ) ); +	fw->reparent( MainWindow::self->qWorkspace(), TQPoint( 0, 0 ), FALSE ); +	TQApplication::sendPostedEvents( MainWindow::self->qWorkspace(), +					TQEvent::ChildInserted ); +	fw->parentWidget()->setFixedSize( 1, 1 ); +	fw->show(); +    } +} + +void Project::formOpened( FormWindow *fw ) +{ +    if ( fw->isFake() ) +	return; +    emit newFormOpened( fw ); +} + +TQString Project::locationOfObject( TQObject *o ) +{ +    if ( !o ) +	return TQString(); + +    if ( MainWindow::self ) { +	TQWidgetList windows = MainWindow::self->qWorkspace()->windowList(); +	for ( TQWidget *w = windows.first(); w; w = windows.next() ) { +	    FormWindow *fw = ::tqqt_cast<FormWindow*>(w); +	    SourceEditor *se = ::tqqt_cast<SourceEditor*>(w); +	    if ( fw ) { +		if ( fw->isFake() ) +		    return objectForFakeForm( fw )->name() + TQString( " [Source]" ); +		else +		    return fw->name() + TQString( " [Source]" ); +	    } else if ( se ) { +		if ( !se->object() ) +		    continue; +		if ( se->formWindow() ) +		    return se->formWindow()->name() + TQString( " [Source]" ); +		else +		    return makeRelative( se->sourceFile()->fileName() ); +	    } +	} +    } + +    if ( ::tqqt_cast<SourceFile*>(o) ) { +	for ( TQPtrListIterator<SourceFile> sources = sourceFiles(); +	      sources.current(); ++sources ) { +	    SourceFile* f = sources.current(); +	    if ( f == o ) +		return makeRelative( f->fileName() ); +	} +    } + +    extern TQMap<TQWidget*, TQString> *qwf_forms; +    if ( !qwf_forms ) { +	tqWarning( "Project::locationOfObject: qwf_forms is NULL!" ); +	return TQString(); +    } + +    TQString s = makeRelative( *qwf_forms->find( (TQWidget*)o ) ); +    s += " [Source]"; +    return s; +} + +bool Project::hasGUI() const +{ +    return tqApp->type() != TQApplication::Tty; +} | 
