[pkg-kde-commits] rev 2845 - trunk/packages/kdesdk/debian/patches

Christopher Martin chrsmrtn at costa.debian.org
Fri Jan 13 02:57:53 UTC 2006


Author: chrsmrtn
Date: 2006-01-13 02:57:50 +0000 (Fri, 13 Jan 2006)
New Revision: 2845

Added:
   trunk/packages/kdesdk/debian/patches/01_kdesdk_branch_r497528.diff
Log:
kdesdk branch pull.


Added: trunk/packages/kdesdk/debian/patches/01_kdesdk_branch_r497528.diff
===================================================================
--- trunk/packages/kdesdk/debian/patches/01_kdesdk_branch_r497528.diff	2006-01-13 01:02:43 UTC (rev 2844)
+++ trunk/packages/kdesdk/debian/patches/01_kdesdk_branch_r497528.diff	2006-01-13 02:57:50 UTC (rev 2845)
@@ -0,0 +1,10806 @@
+#DPATCHLEVEL=0
+--- kbabel/kbabel/kbabelview.cpp	(revision 490305)
++++ kbabel/kbabel/kbabelview.cpp	(revision 497528)
+@@ -33,12 +33,6 @@
+ 
+ **************************************************************************** */
+ 
+-#include "config.h"
+-
+-#ifdef HAVE_UNISTD_H
+-#include <unistd.h>
+-#endif
+-
+ #include "kbabelview.h"
+ 
+ #include "catalogfileplugin.h"
+@@ -440,8 +434,8 @@
+ 
+        hb->addStretch(1);
+ 
+-       QString ledMsg=i18n("<qt><p><b>Status LEDS</b></p>\n"
+-       "<p>These LEDS display the status of the currently displayed message.\n"
++       QString ledMsg=i18n("<qt><p><b>Status LEDs</b></p>\n"
++       "<p>These LEDs display the status of the currently displayed message.\n"
+        "You can change their color in the preferences dialog section\n"
+        "<b>Editor</b> on page <b>Appearance</b></p></qt>");
+        QWhatsThis::add(_fuzzyLed,ledMsg);
+@@ -1518,7 +1512,7 @@
+ 	     case KMessageBox::Continue:
+ 	     {
+ 		// ask for new filename
+-		if ((url = KFileDialog::getSaveURL(currentURL().url(),i18n("*.po *.pot|Gettext Files"),this)).isEmpty())
++		if ((url = KFileDialog::getSaveURL(currentURL().url(), CatalogExportPlugin::availableExportMimeTypes().join(" "), this)).isEmpty())
+ 		{
+ 		   // if no filename was given cancel all
+ 		   return false;
+@@ -1616,7 +1610,7 @@
+ 	}
+     }
+     
+-    unlink(tmpname.local8Bit());
++    QFile::remove( tmpname );
+ 
+     return result;
+ }
+@@ -1654,7 +1648,7 @@
+           if(!msgOnlyAtError)
+           {
+     		KMessageBox::sorry(this
+-        	    ,i18n("You can use gettext tools only for checking GNU PO files."));
++        	    ,i18n("You can use gettext tools only for checking PO files."));
+ 	  }
+ 	  returnCode=true;
+ 	  break;
+--- kbabel/kbabel/kbabel.cpp	(revision 490305)
++++ kbabel/kbabel/kbabel.cpp	(revision 497528)
+@@ -1704,9 +1704,9 @@
+     QString oldproject = m_view->project();
+     if( oldproject == KBABEL_DEFAULTPROJECT )
+     {
+-        oldproject = "";
++        oldproject = QString();
+     }
+-    QString file = KFileDialog::getOpenFileName(oldproject, i18n("*|All Files"), this);
++    const QString file = KFileDialog::getOpenFileName(oldproject, QString::null, this);
+     if (file.isEmpty())
+     {
+         return;
+--- kbabel/kbabel/kbabelview2.cpp	(revision 490305)
++++ kbabel/kbabel/kbabelview2.cpp	(revision 497528)
+@@ -691,8 +691,8 @@
+ 
+     if(url.isEmpty())
+     {
+-        url = KFileDialog::getOpenURL(_project->settings()->diffBaseDir(), i18n("*.po *.pot|Gettext Files")
+-               ,this, i18n("Select File to Diff With"));
++        url = KFileDialog::getOpenURL(_project->settings()->diffBaseDir(), 
++"application/x-gettext", this, i18n("Select File to Diff With"));
+     }
+ 
+     if(url.isEmpty())
+--- kbabel/kbabel/main.cpp	(revision 490305)
++++ kbabel/kbabel/main.cpp	(revision 497528)
+@@ -507,7 +507,7 @@
+ {
+     KAboutData about("kbabel",I18N_NOOP("KBabel"),VERSION,
+        I18N_NOOP("An advanced PO file editor"),KAboutData::License_GPL,
+-       I18N_NOOP("(c) 1999,2000,2001,2002,2003,2004,2005 The KBabel developers"),0,"http://i18n.kde.org/tools/kbabel");
++       I18N_NOOP("(c) 1999,2000,2001,2002,2003,2004,2005,2006 The KBabel developers"),0,"http://i18n.kde.org/tools/kbabel");
+ 
+     about.addAuthor("Matthias Kiefer",I18N_NOOP("Original author"),"kiefer at kde.org");
+     about.addAuthor("Wolfram Diestel"
+--- kbabel/kbabel/sourceview.cpp	(revision 490305)
++++ kbabel/kbabel/sourceview.cpp	(revision 497528)
+@@ -61,8 +61,8 @@
+ {
+     if (isVisible ())
+     {
+-	_contextView->setContext(_catalog->packageDir()
+-            ,_catalog->packageName(), _catalog->context(_currentIndex));
++        // Note: we use Catalog::comment instead of Catalog::context as SourceContext::setContext has to repeat the major part of the code of Catalog::context, so SourceContext::setContext can do the whole job alone.
++	_contextView->setContext( _catalog->packageDir(), _catalog->packageName(), _catalog->comment(_currentIndex), _catalog->currentURL() );
+     }
+ }
+ 
+--- kbabel/kbabeldict/kbabeldict.desktop	(revision 490305)
++++ kbabel/kbabeldict/kbabeldict.desktop	(revision 497528)
+@@ -14,6 +14,7 @@
+ Name[fi]=KBabel sanakirja
+ Name[fr]=Dictionnaire de KBabel
+ Name[ga]=KBabel - Foclóir
++Name[he]=KBabel - מילון
+ Name[hu]=KBabel szótár
+ Name[is]=KBabel orðabók
+ Name[it]=Dizionario di KBabel
+@@ -46,6 +47,7 @@
+ GenericName[fi]=Käännöstyökalun kansio
+ GenericName[fr]=Dictionnaire d'un outil de traduction
+ GenericName[ga]=Uirlis Aistriúcháin - Foclóir
++GenericName[he]=מילון של כלי תרגום
+ GenericName[hu]=Fordítássegítő szótár
+ GenericName[is]=Þýðingaforrit orðabók
+ GenericName[it]=Dizionario di uno strumento di traduzione
+--- kbabel/kbabeldict/kbabeldict.cpp	(revision 490305)
++++ kbabel/kbabeldict/kbabeldict.cpp	(revision 497528)
+@@ -58,6 +58,9 @@
+     // HACK: hide default button, otherwise it would be Help button
+     showButtonOK(false);
+ 
++    // KBabelDict has not a separate help file, so point to the correct part of the KBabel documentation
++    setHelp( "using-kbabeldict", "kbabel" );
++
+     setMainWidget(view);
+ 
+     readConfig();
+--- kbabel/commonui/cmdedit.cpp	(revision 490305)
++++ kbabel/commonui/cmdedit.cpp	(revision 497528)
+@@ -48,7 +48,7 @@
+     QGridLayout* layout = new QGridLayout( this , 1 , 1 );
+     layout->setSpacing( KDialog::spacingHint() );
+ 
+-    QLabel* nameLabel = new QLabel( i18n("&Name:"), this);
++    QLabel* nameLabel = new QLabel( i18n("Command &Label:"), this);
+     QLabel* cmdLabel = new QLabel( i18n("Co&mmand:"), this);
+     layout->addWidget( nameLabel, 0 , 0 );
+     layout->addWidget( cmdLabel, 0 , 1 );
+--- kbabel/commonui/projectprefwidgets.cpp	(revision 490305)
++++ kbabel/commonui/projectprefwidgets.cpp	(revision 497528)
+@@ -317,7 +317,7 @@
+ "<li><b>Local</b> is the format specific to your country.\n"
+ "It can be configured in KDE's Control Center.</li>\n"
+ "<li><b>Custom</b> lets you define your own format.</li></ul></p> "
+-"<p>It is recommended that you use the default format to avoid to create non-standard PO files.</p>"
++"<p>It is recommended that you use the default format to avoid creating non-standard PO files.</p>"
+ "<p>For more information, see section <b>The Preferences Dialog</b> "
+ "in the online help.</p>"
+ "</qt>") );
+@@ -944,15 +944,15 @@
+     m_msgfmtButton = new QCheckBox( i18n("Run &msgfmt before processing a file"), box, "kcfg_msgfmt" );
+ 
+     QWhatsThis::add( m_msgfmtButton, i18n("<qt><p><b>Run msgfmt before processing a file</b></p>"
+-        "<p>If you check this, KBabel will run Gettext's "
++        "<p>If you enable this, KBabel will run Gettext's "
+         "msgfmt tool before processing a file.</p>"
+-        "<p>It is recommended to check this setting, even if it makes the processing slower. "
+-        "Checking this setting is the default.</p>"
+-        "<p>Unchecking is useful for slow computers and when you want "
++        "<p>Enabling this setting is recommended, even if it causes processing to be slower. "
++        "This setting is enabled by default.</p>"
++        "<p>Disabling is useful for slow computers and when you want "
+         "to translate PO files that are not supported by the current version "
+         "of the Gettext tools that are on your system. "
+-        "The drawback of unchecking is that barely not any syntax checking is done by the processing code, "
+-        "so that invalid PO files could be shown as good ones, "
++        "The drawback of disabling is that hardly any syntax checking is done by the processing code, "
++        "so invalid PO files could be shown as good ones, "
+         "even if Gettext tools would reject such files.</p></qt>") );
+ 
+     layout->addStretch(1);
+--- kbabel/commonui/projectpref.cpp	(revision 490305)
++++ kbabel/commonui/projectpref.cpp	(revision 497528)
+@@ -125,15 +125,11 @@
+ 		, "diff"
+                 , i18n("Searching for Differences"));
+ 
++    setHelp( "preferences-project-settings", "kbabel" );
++
+     adjustSize();
+ }
+ 
+-void ProjectDialog::slotHelp()
+-{
+-   //TODO
+-   kapp->invokeHelp("Preferences","");
+-}
+-
+ void ProjectDialog::slotDefault()
+ {
+     // redefine the KConfigDialog behavior to push default on the
+--- kbabel/commonui/context.cpp	(revision 490305)
++++ kbabel/commonui/context.cpp	(revision 497528)
+@@ -50,6 +50,9 @@
+ #include <kdialog.h>
+ #include <klocale.h>
+ #include <kmessagebox.h>
++#include <kurl.h>
++#include <kdeversion.h>
++#include <kio/netaccess.h>
+ 
+ #include <klibloader.h>
+ #include <ktrader.h>
+@@ -59,6 +62,7 @@
+ #include <ktexteditor/viewcursorinterface.h>
+ 
+ SourceContext::SourceContext(QWidget *parent, KBabel::Project::Ptr project): QWidget(parent)
++    , m_parent( parent )
+     , _part(0)
+     , _view(0)
+     , _referenceCombo(0)
+@@ -73,11 +77,11 @@
+     _layout->addWidget(_referenceCombo);
+ }
+ 
+-void SourceContext::setContext(const QString& packageDir, const QString& packageName, const QString& gettextComment)
++void SourceContext::setContext( const QString& packageDir, const QString& packageName, const QString& gettextComment, const KURL& urlPoFile )
+ {
+     if( !_part && !loadPart() ) return;
+     _referenceCombo->clear();
+-    _referenceList = resolvePath(packageDir,packageName,gettextComment);
++    _referenceList = resolvePath( packageDir, packageName, gettextComment, urlPoFile );
+     
+     for( QValueList<ContextInfo>::const_iterator it = _referenceList.constBegin(); it != _referenceList.constEnd(); ++it )
+ 	_referenceCombo->insertItem((*it).path);
+@@ -115,58 +119,138 @@
+     (dynamic_cast<KTextEditor::SelectionInterface *>(_part))->setSelection(ci.line-1,0,ci.line,0);
+ }
+ 
+-QValueList<ContextInfo> SourceContext::resolvePath(const QString& packageDir, const QString& packageName, const QString& gettextComment)
++QValueList<ContextInfo> SourceContext::resolvePath( const QString& packageDir, const QString& packageName, const QString& gettextComment, const KURL& urlPoFile )
+ {
++    //kdDebug() << "GETTEXTCOMMENT:" << gettextComment << endl;
++
++    // Find the directory name of the PO file, if the PO file is local
++    // ### TODO: find a way to allow remote files too
++    QString poDir;
++#if KDE_IS_VERSION( 3, 5, 0 )
++    const KURL localUrl( KIO::NetAccess::mostLocalURL( urlPoFile, m_parent ) );
++    if ( localUrl.isLocalFile() )
++    {
++        const QFileInfo fi( localUrl.path() );
++        poDir = fi.dirPath( true );
++    }
++#else
++    if ( urlPoFile.isLocalFile() )
++    {
++        const QFileInfo fi( urlPoFile.path() );
++        poDir = fi.dirPath( true );
++    }
++#endif
++
++#if 0
++    kdDebug() << "CONTEXT VARIABLE START" << endl;
++    kdDebug() << "@CODEROOT@: " << _project->settings()->codeRoot() << endl;
++    kdDebug() << "@PACKAGEDIR@: " << packageDir  << endl;
++    kdDebug() << "@PACKAGE@: " << packageName << endl;
++    kdDebug() << "@POFILEDIR@: " << poDir  << endl;
++    kdDebug() << "CONTEXT VARIABLE END" << endl;
++#endif
++    
+     QStringList prefixes;
+-    QStringList paths = _project->settings()->paths();
++    const QStringList paths = _project->settings()->paths();
+     
+-    for( QStringList::Iterator it = paths.begin() 
+-	; it!=paths.end() ; ++it)
++    for( QStringList::const_iterator it = paths.constBegin(); it!=paths.constEnd() ; ++it )
+     {
+ 	QString pref = (*it);
++
++        if ( !poDir.isEmpty() )
++        {
++            pref.replace( "@POFILEDIR@", poDir );
++        }
++        else if ( pref.find( "@POFILEDIR@ " ) != -1 )
++            continue; // No need to keep this path pattern, as we have no PO file dir
++        
+         pref.replace( "@PACKAGEDIR@", packageDir);
+         pref.replace( "@PACKAGE@", packageName);
+ 	pref.replace( "@CODEROOT@", _project->settings()->codeRoot());
+ 	prefixes.append(pref);
+     }
+ 
+-    QStringList references;
++    QValueList<ContextInfo> rawRefList; // raw references
++    QRegExp re("^\\s*(.+):(\\d+)\\s*$"); // Reg. exp. for Gettext references
++    QRegExp rex( "^#. i18n: file (.+) line (\\d+)\\s*$" ); //Reg. exp. for KDE extractrc/extractattr references
++    QRegExp res( "^# [Ff]ile: (.+), line(?: number)?: (\\d+)\\s*$"); // Reg. exp. for "strict" PO format
+     const QStringList lines = QStringList::split( "\n", gettextComment );
+     for ( QStringList::const_iterator it = lines.constBegin() ; it != lines.constEnd() ; ++it)
+     {
+-	QString curLine = (*it);
++	const QString curLine = (*it).stripWhiteSpace();
+ 	if( curLine.startsWith( "#:" ) )
+-            curLine = curLine.mid(2);
++        {
++            // We have a Gettext line with references
++            const QStringList references( QStringList::split( " ", curLine.mid( 2 ), false ) );
++            for ( QStringList::const_iterator it = references.constBegin(); it != references.constEnd(); ++it )
++            {
++                if ( re.exactMatch( (*it) ) )
++                {
++                    ContextInfo ref;
++                    ref.line = re.cap(2).toInt();
++                    ref.path = re.cap(1);
++                    // ### TODO KDE4: perhaps we should not do the replace if compiled for Windows
++                    ref.path.replace( QChar( '\\' ), QChar( '/' ) );
++                    rawRefList.append( ref );
++                }
++            }
++            
++        }
+         else if ( curLine.startsWith( "#," ) )
++        {
++            // We have a Gettext option line. There is no source reference here.
+             continue;
+-        references += QStringList::split( " ", curLine.stripWhiteSpace() );
++        }
++        else if ( curLine.startsWith( "#. i18n:") )
++        {
++            // We might have a KDE reference from extractrc/extractattr
++            if ( rex.exactMatch( (*it) ) )
++            {
++                ContextInfo ref;
++                ref.line = rex.cap(2).toInt();
++                ref.path = rex.cap(1);
++                // KDE is not extracted on Windows, so no backslash conversion is needed.
++                rawRefList.append( ref );
++            }
++        }
++        else if ( curLine.startsWith( "# F" ) || curLine.startsWith( "# f" ) )
++        {
++            // We might have a "strict PO" reference
++            if ( res.exactMatch( (*it) ) )
++            {
++                ContextInfo ref;
++                ref.line = res.cap(2).toInt();
++                ref.path = res.cap(1);
++                // ### TODO KDE4: perhaps we should not do the replace if compiled for Windows
++                ref.path.replace( QChar( '\\' ), QChar( '/' ) );
++                rawRefList.append( ref );
++            }
++        }
++        else
++            continue; 
+     }
+     
++    // Now that we have gathered the references, we need to convert them to absolute paths
+     QValueList<ContextInfo> results;
+-    QRegExp re("^\\s*(.+):(\\d+)\\s*$");
+-    
+-    for ( QStringList::const_iterator it = references.constBegin(); it != references.constEnd(); ++it )
++    for ( QValueList<ContextInfo>::const_iterator it = rawRefList.constBegin(); it != rawRefList.constEnd(); ++it )
+     {
+-        if ( re.exactMatch( (*it) ) )
+-	{
+-	    const QString lineNum = re.cap(2);
+-	    const QString fileName = re.cap(1);
+-	    for ( QStringList::const_iterator it1 = prefixes.constBegin(); it1 != prefixes.constEnd(); ++it1 )
+-	    {
+-		QString path = (*it1);
+-		path.replace( "@COMMENTPATH@", fileName);
++        const int lineNum = (*it).line;
++        const QString fileName = (*it).path;
++        for ( QStringList::const_iterator it1 = prefixes.constBegin(); it1 != prefixes.constEnd(); ++it1 )
++        {
++            QString path = (*it1);
++            path.replace( "@COMMENTPATH@", fileName);
+ 
+-                //kdDebug() << "CONTEXT PATH: " << path << endl; // DEBUG
+-		QFileInfo url(path);
+-		if( url.exists())
+-		{
+-		    ContextInfo ref;
+-		    ref.path = url.absFilePath();
+-		    ref.line = lineNum.toInt();
+-		    results.append(ref);
+-		}
+-	    }
+-	}
++            //kdDebug() << "CONTEXT PATH: " << path << endl; // DEBUG
++            QFileInfo pathInfo( path );
++            if( pathInfo.exists() )
++            {
++                ContextInfo ref;
++                ref.path = pathInfo.absFilePath();
++                ref.line = lineNum;
++                results.append(ref);
++            }
++        }
+     }
+     
+     return results;
+--- kbabel/commonui/projectwizard.cpp	(revision 490305)
++++ kbabel/commonui/projectwizard.cpp	(revision 497528)
+@@ -39,6 +39,7 @@
+ 
+ #include <qcombobox.h>
+ 
++#include <kapplication.h>
+ #include <kmessagebox.h>
+ #include <klineedit.h>
+ #include <klocale.h>
+@@ -72,6 +73,7 @@
+    
+     connect( _wizard->_projectName, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &)));
+     connect( _wizard->_projectFile, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &)));
++    connect( this, SIGNAL( helpClicked( void ) ), this, SLOT( slotHelpClicked( void ) ) );
+ 
+     addPage(_wizard, i18n("Basic Project Information"));
+     
+@@ -162,4 +164,9 @@
+     return 0;
+ }
+ 
++void ProjectWizard::slotHelpClicked( void )
++{
++    kapp->invokeHelp( "preferences-project-wizard", "kbabel" );
++}
++
+ #include "projectwizard.moc"
+--- kbabel/commonui/projectpref.h	(revision 490305)
++++ kbabel/commonui/projectpref.h	(revision 497528)
+@@ -62,7 +62,6 @@
+     ProjectDialog(Project::Ptr project);
+ 
+ protected slots:
+-   virtual void slotHelp();
+    virtual void slotDefault();
+    virtual void updateSettings();
+    virtual void updateWidgets();
+--- kbabel/commonui/context.h	(revision 490305)
++++ kbabel/commonui/context.h	(revision 497528)
+@@ -46,6 +46,7 @@
+ class QLineEdit;
+ class KListEditor;
+ class KConfig;
++class KURL;
+ 
+ struct ContextInfo
+ {
+@@ -54,14 +55,25 @@
+ };
+ 
+ /**
+-* Widget for displaying source code context of for the given GNU gettext comment.
+-* The searched paths can be configured using variables @PACKAGE@, @PACKAGEDIR@,
+-* @CODEROOT@ and @COMMENTPATH at . It requires a KPart implementing KTextEditor interface
+-* with selections.
+-*
+-* @short Class for displaying source code context
+-* @author Stanislav Visnovsky <visnovsky at kde.org>
+-*/
++ * @short Class for displaying source code context
++ *
++ * Widget for displaying source code context of for the given GNU gettext comment.
++ * The searched paths can be configured using variables.
++ *
++ * The possible variables are:
++ * - \@POFILEDIR\@   absolute directory of the PO file (to create paths relatives to the PO file)
++ * - \@PACKAGE\@     name of the PO file
++ * - \@PACKAGEDIR\@  relative directory of the PO file (relative to \@CODEROOT\@)
++ * - \@CODEROOT\@    base directory (especially of the catalog manager)
++ * - \@COMMENTPATH\@ (relative) path given as source code reference in a comment of the PO file
++ *
++ * @note The difference between \@POFILEDIR\@ and a path constructed by
++ * \@CODEROOT\@\@PACKAGEDIR\@/ is that \@POFILEDIR\@ will also work if the file is external
++ * to the catalog manager's root
++ *
++ * @note It requires a KPart implementing KTextEditor interface with selections.
++ * @author Stanislav Visnovsky <visnovsky at kde.org>
++ */
+ class SourceContext : public QWidget
+ {
+     Q_OBJECT
+@@ -76,13 +88,26 @@
+      * @param packageDir	path of the package, where to find the source file
+      * @param packageName	name of the package, where to find the source file
+      * @param gettextComment	comment string with context as generated by xgettext (can start with #:)
++     * @param urlPoFile         URL of the PO file
++     * @todo even if @p urlPoFile is an URL SourceContext::resolvePath is not remote-aware yet
+      */
+-    void setContext( const QString& packageDir, const QString& packageName, const QString& gettextComment );
++    void setContext( const QString& packageDir, const QString& packageName, const QString& gettextComment, const KURL& urlPoFile );
+ 
+ private:
+-    QValueList<ContextInfo> resolvePath( const QString& packageDir, const QString& packageName, const QString& gettextComment);
++    /**
++     * Get a list of paths from the source references in the comment @p gettextComment
++     * @param packageDir        path of the package, where to find the source file
++     * @param packageName       name of the package, where to find the source file
++     * @param gettextComment    comment string with context as generated by xgettext (can start with #:)
++     * @param urlPoFile         URL of the PO file
++     * @todo even if @p urlPoFile is an URL SourceContext::resolvePath is not remote-aware yet
++     * @private 
++     */
++    QValueList<ContextInfo> resolvePath( const QString& packageDir, const QString& packageName, const QString& gettextComment, const KURL& urlPoFile );
+     bool loadPart();
+-    
++
++    /// Parent widget (for KIO::NetAccess member functions)
++    QWidget* m_parent;
+     KTextEditor::Document* _part;
+     KTextEditor::View* _view;
+     QComboBox *_referenceCombo;
+--- kbabel/commonui/projectwizard.h	(revision 490305)
++++ kbabel/commonui/projectwizard.h	(revision 497528)
+@@ -59,6 +59,7 @@
+ 
+ private slots:
+     void textChanged(const QString &);
++    void slotHelpClicked( void );
+     virtual void next();
+     
+ private:
+--- kbabel/ChangeLog	(revision 490305)
++++ kbabel/ChangeLog	(revision 497528)
+@@ -1,8 +1,28 @@
+-Changes 1.11:
++Changes 1.11.1 (KDE 3.5.1)
++- Avoid user-visible strings that need to be translated in two ways (bug #114151)
++- Fix and improve source references
++- Add a new variable @POFILEDIR@ for source references.
++  This is for allowing search paths starting at the directory of the PO file,
++  like what is needed for GNU projects: starting at the parent directory (bug #114041)
++- Allow backslashes in source references in the PO file (bug #116393)
++- Clicking the help button of KBabelDict calls the corresponding section in the KBabel documentation
++- Improved documentation (including bug #85885)
++
++Changes 1.11 (KDE 3.5):
+ - Diff settings part of a project (Stanislav Visnovsky)
+ - View for current list of errors (Albert Cervera Areny)
+ - Datatool for generic regexp validation (Albert Cervera Areny)
+ - Separated editor color settings to its own page (Stanislav Visnovsky)
++- Improve CVS support of catalog manager
++- Allow the user to select an encoding for CVS (bug #66605)
++- Add SVN support to catalog manager (bug #105805)
++- Support for Gettext context (keyword "msgctxt")
++- Improve Gettext plural support
++- Abort load of a PO file with CVS/SVN conflict markers in it (bug #108285)
++- Make optional the ; character before the "charset" of a Content-Type declaration in a PO file (bug #106733)
++- Make the catalog manager work with PO files having CR/LF line endings (bug #105399)
++- Fix remote saving of files (bug #106738)
++- Improve writing the header while saving a PO file (bugs #64413, #107782, #115275, #115276, #115295)
+ 
+ Changes 1.10:
+ - XLIFF support (Stanislav Visnovsky)
+--- kbabel/common/catalog.h	(revision 490305)
++++ kbabel/common/catalog.h	(revision 497528)
+@@ -187,8 +187,9 @@
+    *
+    * @param index  index of the requested message
+    * @return       context information found in the message comment
++   * @deprecated
+    */
+-   QString context(uint index) const;
++   QString context(uint index) const KDE_DEPRECATED;
+ 
+    /**
+    * Get the header for the current file.
+--- kbabel/common/catalog.cpp	(revision 490305)
++++ kbabel/common/catalog.cpp	(revision 497528)
+@@ -833,20 +833,18 @@
+ 
+ void Catalog::setPackage(const QString& package )
+ {
+-    int pos=package.findRev("/");
+-    if( pos<0 )
++    const int pos = package.findRev( '/' );
++    if( pos < 0 )
+     {
+-	d->_packageDir = "";
++	d->_packageDir = QString();
+ 	d->_packageName = package;
+-	d->_packageName.replace( QRegExp("^/+"),"");
+     }
+     else
+     {
+-	d->_packageDir = package.left(pos);
+-	if( !d->_packageDir.endsWith("/") ) d->_packageDir+="/";
+-	d->_packageName = package.right(package.length()-pos);
+-	d->_packageName.replace( QRegExp("^/+"),"");
++	d->_packageDir = package.left( pos + 1 ); // We want the / included
++	d->_packageName = package.mid( pos + 1 ); // We do not want /
+     }
++    kdDebug() << k_funcinfo << " " << package << " => " << d->_packageDir << " + " << d->_packageName << endl;
+ }
+ 
+ QString Catalog::packageDir() const
+--- kbabel/common/kbabelfilter.desktop	(revision 490305)
++++ kbabel/common/kbabelfilter.desktop	(revision 497528)
+@@ -16,6 +16,7 @@
+ Comment[fi]=KBabel-suodin
+ Comment[fr]=Filtre pour KBabel
+ Comment[ga]=Scagaire KBabel
++Comment[he]=מסנן KBabel
+ Comment[hi]=के-बेबल फ़िल्टर
+ Comment[hu]=KBabel-szűrő
+ Comment[is]=KBabel sía
+--- kbabel/common/kbprojectsettings.kcfg	(revision 490305)
++++ kbabel/common/kbprojectsettings.kcfg	(revision 497528)
+@@ -348,7 +348,7 @@
+ 		<default></default>
+ 	</entry>
+ 	<entry name="Paths" type="StringList">
+-		<default>@PACKAGEDIR@/@PACKAGE@/@COMMENTPATH@, at CODEROOT@/@PACKAGEDIR@/@PACKAGE@/@COMMENTPATH@, at CODEROOT@/@PACKAGE@/@COMMENTPATH@</default>
++		<default>@PACKAGEDIR@/@PACKAGE@/@COMMENTPATH@, at CODEROOT@/@PACKAGEDIR@/@PACKAGE@/@COMMENTPATH@, at CODEROOT@/@PACKAGE@/@COMMENTPATH@, at POFILEDIR@/@COMMENTPATH@, at POFILEDIR@/../@COMMENTPATH@</default>
+ 	</entry>
+   </group>
+ </kcfg>
+--- kbabel/datatools/not-translated/kbabel_nottranslatedtool.desktop	(revision 490305)
++++ kbabel/datatools/not-translated/kbabel_nottranslatedtool.desktop	(revision 497528)
+@@ -50,6 +50,7 @@
+ Comment[eu]=Inglesa duten itzulpenak
+ Comment[fi]=Käännös sisältää englantia
+ Comment[fr]=Traductions contenant de l'anglais
++Comment[he]=תרגומים המכילים אנגלית
+ Comment[hi]=अंग्रेज़ी युक्त अनुवाद
+ Comment[hu]=Angol nyelvű részeket tartalmazó fordítások
+ Comment[is]=Þýðingar sem innihalda ensku
+--- kbabel/datatools/not-translated/main.cc	(revision 490305)
++++ kbabel/datatools/not-translated/main.cc	(revision 497528)
+@@ -57,7 +57,7 @@
+ NotTranslatedTool::NotTranslatedTool( QObject* parent, const char* name, const QStringList & )
+     : KDataTool( parent, name ) , _cache_origin( 0 )
+ {
+-    i18n("which check found errors","english text in translation");
++    i18n("which check found errors","English text in translation");
+ }
+ 
+ bool NotTranslatedTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+--- kbabel/datatools/xml/kbabel_xmltool.desktop	(revision 490305)
++++ kbabel/datatools/xml/kbabel_xmltool.desktop	(revision 497528)
+@@ -55,6 +55,7 @@
+ Comment[fi]=Tarkista tagit
+ Comment[fr]=Vérifier les balises
+ Comment[ga]=Seiceáil Clibeanna
++Comment[he]=בודק תגיות
+ Comment[hi]=टैग्स जांच करें
+ Comment[hu]=A tag-ek ellenőrzése
+ Comment[is]=Athuga tög
+--- kbabel/datatools/arguments/kbabel_argstool.desktop	(revision 490305)
++++ kbabel/datatools/arguments/kbabel_argstool.desktop	(revision 497528)
+@@ -53,6 +53,7 @@
+ Comment[fi]=Tarkista muuttujat
+ Comment[fr]=Vérification des arguments
+ Comment[ga]=Seiceáil Argóintí
++Comment[he]=בודק ארגומנטים
+ Comment[hi]=आर्गुमेंट जांच करें
+ Comment[hu]=Az argumentumok ellenőrzése
+ Comment[is]=Athuga viðföng
+--- kbabel/datatools/pluralforms/kbabel_pluralformstool.desktop	(revision 490305)
++++ kbabel/datatools/pluralforms/kbabel_pluralformstool.desktop	(revision 497528)
+@@ -52,6 +52,7 @@
+ Comment[eu]=Egiaztatu plural formak
+ Comment[fi]=Tarkista monikkomuodot
+ Comment[fr]=Vérifie les formes plurielles
++Comment[he]=בודק מצבי רבים
+ Comment[hi]=बहुवचन जाँचें
+ Comment[hu]=A többes számú alakok ellenőrzése
+ Comment[is]=Athuga fleirtöluform
+--- kbabel/datatools/accelerators/kbabel_accelstool.desktop	(revision 490305)
++++ kbabel/datatools/accelerators/kbabel_accelstool.desktop	(revision 497528)
+@@ -53,6 +53,7 @@
+ Comment[eu]=Egiaztatu bizkortzaileak
+ Comment[fi]=Tarkista pikavalinnat
+ Comment[fr]=Vérification des accélérateurs clavier
++Comment[he]=בודק מזנקים
+ Comment[hi]=त्वरक जांच करें
+ Comment[hu]=A gyorsbillentyűk ellenőrzése
+ Comment[is]=Athuga flýtilykla
+--- kbabel/datatools/equations/kbabel_equationstool.desktop	(revision 490305)
++++ kbabel/datatools/equations/kbabel_equationstool.desktop	(revision 497528)
+@@ -51,6 +51,7 @@
+ Comment[eu]=Egiaztatu ekuazioak
+ Comment[fi]=Tarkista yhtälöt
+ Comment[fr]=Vérifier les identités
++Comment[he]=בודק משוואות
+ Comment[hi]=समीकरण जांच करें
+ Comment[hu]=Az egyenletek ellenőrzése
+ Comment[is]=Athuga jöfnur
+--- kbabel/datatools/punctuation/kbabel_punctuationtool.desktop	(revision 490305)
++++ kbabel/datatools/punctuation/kbabel_punctuationtool.desktop	(revision 497528)
+@@ -52,6 +52,7 @@
+ Comment[fi]=Tarkista pilkutus
+ Comment[fr]=Vérifie la ponctuation
+ Comment[ga]=Seiceáil Poncaíocht
++Comment[he]=בודק ניקוד
+ Comment[hi]=विरामचिह्न जांच करें
+ Comment[hu]=Az írásjelek ellenőrzése
+ Comment[is]=Athuga greinamerki
+--- kbabel/datatools/regexp/kbabel_regexptool.desktop	(revision 490305)
++++ kbabel/datatools/regexp/kbabel_regexptool.desktop	(revision 497528)
+@@ -11,6 +11,7 @@
+ Name[eu]=Katalanaren gramatika
+ Name[fr]=Grammaire du catalan
+ Name[ga]=Gramadach na Catalóinise
++Name[he]=תחברי קטאלני
+ Name[hu]=Katalán nyelvtan
+ Name[is]=Katalónsk málfræði
+ Name[it]=Grammatica catalana
+--- kbabel/datatools/regexp/main.cc	(revision 490305)
++++ kbabel/datatools/regexp/main.cc	(revision 497528)
+@@ -150,7 +150,7 @@
+ 
+ 	QDomNode n = e.firstChild();
+ 	if ( n.isNull() ) {
+-		_error = i18n( "'item' first child is not a node" );
++		_error = i18n( "First child of 'item' is not a node" );
+ 		return;
+ 	}
+ 
+--- kbabel/datatools/whitespace/kbabel_whitespacetool.desktop	(revision 490305)
++++ kbabel/datatools/whitespace/kbabel_whitespacetool.desktop	(revision 497528)
+@@ -50,6 +50,7 @@
+ Comment[eu]=Zurigune itzulpenak
+ Comment[fi]=Välilyöntikäännökset
+ Comment[fr]=Traductions en espaces
++Comment[he]=תרגומים של תווים נקיים
+ Comment[hi]=व्हाइट-स्पेस अनुवाद
+ Comment[hu]=Az üres fordítások kiszűrése
+ Comment[is]=Þýðingar bila
+--- kbabel/catalogmanager/libcvs/cvsdialog.cpp	(revision 490305)
++++ kbabel/catalogmanager/libcvs/cvsdialog.cpp	(revision 497528)
+@@ -117,8 +117,8 @@
+     layout->addWidget( m_encodingComboBox );
+     QStringList encodingList;
+     // The last encoding will be added at the top of the list, when the seetings will be read.
+-    encodingList << i18n( "Descriptive encoding name", "Recommended (%1)" ).arg( "UTF-8" );
+-    encodingList << i18n( "Descriptive encoding name", "Locale (%1)" ).arg( QTextCodec::codecForLocale()->mimeName() );
++    encodingList << i18n( "Descriptive encoding name", "Recommended ( %1 )" ).arg( "UTF-8" );
++    encodingList << i18n( "Descriptive encoding name", "Locale ( %1 )" ).arg( QTextCodec::codecForLocale()->mimeName() );
+     encodingList += KGlobal::charsets()->descriptiveEncodingNames();
+     m_encodingComboBox->insertStringList( encodingList );
+     
+@@ -403,7 +403,7 @@
+       logedit->setText( m_squeezedLogMessages.first( ) );
+ 
+     m_encoding = config->readEntry( "CVSEncoding", "UTF-8" );
+-    m_encodingComboBox->insertItem( i18n( "Descriptive encoding name", "Last choice (%1)" ).arg( m_encoding ), 0);
++    m_encodingComboBox->insertItem( i18n( "Descriptive encoding name", "Last choice ( %1 )" ).arg( m_encoding ), 0);
+   }
+ }
+ 
+--- kbabel/catalogmanager/catalogmanager.cpp	(revision 490305)
++++ kbabel/catalogmanager/catalogmanager.cpp	(revision 497528)
+@@ -657,7 +657,7 @@
+ 	kapp->updateRemoteUserTimestamp ("kbabel");
+ 
+         if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+-            KMessageBox::error(this, i18n("Can not send a message to KBabel.\n"
++            KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+                                           "Please check your installation of KDE."));
+     }
+ }
+@@ -690,7 +690,7 @@
+ 	kapp->updateRemoteUserTimestamp ("kbabel");
+ 
+         if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+-            KMessageBox::error(this, i18n("Can not send a message to KBabel.\n"
++            KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+                                           "Please check your installation of KDE."));
+     }
+ }
+@@ -721,7 +721,7 @@
+ 	kapp->updateRemoteUserTimestamp ("kbabel");
+ 
+         if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+-            KMessageBox::error(this, i18n("Can not send a message to KBabel.\n"
++            KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+                                           "Please check your installation of KDE."));
+     }
+ }
+@@ -751,7 +751,7 @@
+ 	kapp->updateRemoteUserTimestamp ("kbabel");
+ 
+         if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+-            KMessageBox::error(this, i18n("Can not send a message to KBabel.\n"
++            KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+                                           "Please check your installation of KDE."));
+     }
+ }
+@@ -781,7 +781,7 @@
+ 	kapp->updateRemoteUserTimestamp ("kbabel");
+ 
+         if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+-            KMessageBox::error(this, i18n("Can not send a message to KBabel.\n"
++            KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+                                           "Please check your installation of KDE."));
+     }
+ }
+@@ -801,7 +801,7 @@
+ 	kapp->updateRemoteUserTimestamp ("kbabel");
+ 
+         if( !client->send("kbabel","KBabelIFace", "spellcheck(QStringList)", data) )
+-            KMessageBox::error(this, i18n("Can not send a message to KBabel.\n"
++            KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+                                           "Please check your installation of KDE."));
+     }
+ }
+@@ -821,7 +821,7 @@
+ 	kapp->updateRemoteUserTimestamp ("kbabel");
+ 
+         if( !client->send("kbabel","KBabelIFace", "spellcheck(QStringList)", data) )
+-            KMessageBox::error(this, i18n("Can not send a message to KBabel.\n"
++            KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+                                           "Please check your installation of KDE."));
+     }
+ }
+@@ -1194,7 +1194,7 @@
+     {
+         oldproject = QString();
+     }
+-    QString file = KFileDialog::getOpenFileName(oldproject, i18n("*|All Files"), this);
++    const QString file = KFileDialog::getOpenFileName(oldproject, QString::null, this);
+     if (file.isEmpty())
+     {
+         return;
+--- kbabel/catalogmanager/future.cpp	(revision 490305)
++++ kbabel/catalogmanager/future.cpp	(revision 497528)
+@@ -2,24 +2,8 @@
+ 
+ // Misc. messages already existing in the kbabel-svn branch
+ i18n("SVN");
+-i18n("SVN Dialog");
+ i18n( "CVS/SVN Status" );
+-i18n( "No version control" );
+ 
+-// Messages for support local/remome SVN status (remote = "svn stat -u")
+-i18n( "Status (Local)" );
+-i18n( "Status (Local) for Marked" );
+-i18n( "Status (Remote)" );
+-i18n( "Status (Remote) for Marked" );
+-i18n( "Get remote status for the following files:" );
+-i18n( "Get local status for the following files:" );
+-
+-// Messages for "svn info"
+-i18n( "Show Information" );
+-i18n( "Show Information for Marked" );
+-i18n( "Get information for the following files:" );
+-i18n( "&Get Information" );
+-
+ // Messages for further SVN functions
+ i18n( "Resolved" );
+ i18n( "Resolved for Marked" );
+@@ -28,20 +12,6 @@
+ i18n( "Cleanup" );
+ i18n( "Cleanup for Marked" );
+ 
+-// Messages for fixing bug #66605 in CVS support
+-i18n( "Descriptive encoding name", "Last choice ( %1 )" );
+-i18n( "Descriptive encoding name", "Recommended ( %1 )" );
+-i18n( "Descriptive encoding name", "Locale ( %1 )" );
+-i18n( "Cannot find encoding: %1" );
+-i18n( "E&ncoding:" );
+-i18n( "The commit log message cannot be encoded in the selected encoding: %1.\nDo you want to continue?" );
+-
+ // Messages that will probably not be needed
+ i18n( "No repository" );
+ 
+-// Messages for the SVN/CVS handler dialogs
+-i18n( "The commit log message is empty. Do you want to continue?" );
+-i18n( "The process could not be started." );
+-i18n( "Cannot open temporary file for writing. Aborting.");
+-i18n( "Cannot write to temporary file. Aborting." );
+-
+--- kbabel/catalogmanager/main.cpp	(revision 490305)
++++ kbabel/catalogmanager/main.cpp	(revision 497528)
+@@ -182,8 +182,8 @@
+ {
+     KLocale::setMainCatalogue("kbabel");
+     KAboutData about("catalogmanager",I18N_NOOP("KBabel - Catalog Manager"),VERSION,
+-                     I18N_NOOP("An advanced catalog manager for KBabel, PO file editor"),KAboutData::License_GPL,
+-                     I18N_NOOP("(c) 1999,2000,2001,2002,2003 The KBabel developers"),0,"http://i18n.kde.org/tools/kbabel");
++                     I18N_NOOP("An advanced catalog manager for KBabel"),KAboutData::License_GPL,
++                     I18N_NOOP("(c) 1999,2000,2001,2002,2003,2004,2005,2006 The KBabel developers"),0,"http://i18n.kde.org/tools/kbabel");
+ 
+     about.addAuthor("Matthias Kiefer",I18N_NOOP("Original author"),"kiefer at kde.org");
+     about.addAuthor("Stanislav Visnovsky",I18N_NOOP("Current maintainer, porting to KDE3/Qt3.")
+--- kbabel/catalogmanager/catalogmanager.desktop	(revision 490305)
++++ kbabel/catalogmanager/catalogmanager.desktop	(revision 497528)
+@@ -15,6 +15,7 @@
+ Name[fi]=KBabel luettelon hallinta
+ Name[fr]=Gestionnaire de catalogues de KBabel
+ Name[ga]=KBabel - Bainisteoir na gCatalóg
++Name[he]=KBabel - מנהל הקטלוגים
+ Name[hu]=KBabel listakezelő
+ Name[is]=KBabel Þýðingarstjóri
+ Name[it]=Gestore dei cataloghi di KBabel
+@@ -47,6 +48,7 @@
+ GenericName[fi]=Käännöstyökalun luettelon hallinta
+ GenericName[fr]=Gestionnaire de catalogues de traduction
+ GenericName[ga]=Uirlis Aistriúcháin - Bainisteoir na gCatalóg
++GenericName[he]=מנהל הקטלוגים של כלי התרגום
+ GenericName[hu]=Fordítássegítő
+ GenericName[is]=Þýðingarforrit - Þýðingarstjóri
+ GenericName[it]=Gestore dei cataloghi di uno strumento di traduzione
+--- kbabel/catalogmanager/catalogmanagerview.cpp	(revision 490305)
++++ kbabel/catalogmanager/catalogmanagerview.cpp	(revision 497528)
+@@ -838,12 +838,12 @@
+          }
+          case Msgfmt::NoExecutable:
+          {
+-            KMessageBox::sorry(this,i18n("Can not execute msgfmt. Please make sure you have msgfmt in your PATH!"));
++            KMessageBox::sorry(this,i18n("Cannot execute msgfmt. Please make sure that you have msgfmt in your PATH."));
+             break;
+          }
+ 	 case Msgfmt::Unsupported:
+ 	 {
+-    	    KMessageBox::sorry(this,i18n("You can use gettext tools only for checking GNU PO files."));
++    	    KMessageBox::sorry(this,i18n("You can use gettext tools only for checking PO files."));
+ 	    break;
+ 	 }
+       }
+@@ -927,12 +927,12 @@
+          }
+          case Msgfmt::NoExecutable:
+          {
+-            KMessageBox::sorry(this,i18n("Cannot execute msgfmt. Please make sure you have msgfmt in your PATH."));
++            KMessageBox::sorry(this,i18n("Cannot execute msgfmt. Please make sure that you have msgfmt in your PATH."));
+             break;
+          }
+ 	 case Msgfmt::Unsupported:
+ 	 {
+-    	    KMessageBox::sorry(this,i18n("You can use gettext tools only for checking GNU PO files."));
++    	    KMessageBox::sorry(this,i18n("You can use gettext tools only for checking PO files."));
+ 	    break;
+ 	 }
+       }
+@@ -3014,8 +3014,8 @@
+ 
+     if( !t )
+     {
+-	KMessageBox::error( this, i18n("Can not instantiate a validation tool.\n"
+-	"Please, check your installation."), i18n("Validation Tool Error") );
++	KMessageBox::error( this, i18n("Cannot instantiate a validation tool.\n"
++	"Please check your installation."), i18n("Validation Tool Error") );
+ 	return;
+     }
+ 
+--- kbabel/catalogmanager/validateprogress.cpp	(revision 490305)
++++ kbabel/catalogmanager/validateprogress.cpp	(revision 497528)
+@@ -96,7 +96,7 @@
+     if( !t )
+     {
+ 	KMessageBox::error( this, i18n("Cannot instantiate a validation tool.\n"
+-	"Please, check your installation."), i18n("Validation Tool Error") );
++	"Please check your installation."), i18n("Validation Tool Error") );
+ 	return;
+     }
+ 
+--- umbrello/uml.directory	(revision 490305)
++++ umbrello/uml.directory	(revision 497528)
+@@ -1,335 +0,0 @@
+-[IconPosition::.deps]
+-X=28
+-Y=5
+-
+-[IconPosition::.kdbgrc.uml]
+-X=360
+-Y=7
+-
+-[IconPosition::Makefile]
+-X=194
+-Y=437
+-
+-[IconPosition::Makefile.am]
+-X=272
+-Y=437
+-
+-[IconPosition::Makefile.in]
+-X=362
+-Y=437
+-
+-[IconPosition::actor.cpp]
+-X=453
+-Y=5
+-
+-[IconPosition::actor.h]
+-X=547
+-Y=5
+-
+-[IconPosition::actorwidget.cpp]
+-X=7
+-Y=77
+-
+-[IconPosition::actorwidget.h]
+-X=94
+-Y=77
+-
+-[IconPosition::association.cpp]
+-X=181
+-Y=77
+-
+-[IconPosition::association.h]
+-X=268
+-Y=77
+-
+-[IconPosition::assocpage.cpp]
+-X=356
+-Y=77
+-
+-[IconPosition::assocpage.h]
+-X=443
+-Y=77
+-
+-[IconPosition::assocpropdlg.cpp]
+-X=528
+-Y=77
+-
+-[IconPosition::assocpropdlg.h]
+-X=6
+-Y=149
+-
+-[IconPosition::attribute.cpp]
+-X=97
+-Y=149
+-
+-[IconPosition::attribute.h]
+-X=191
+-Y=149
+-
+-[IconPosition::classattpage.cpp]
+-X=268
+-Y=149
+-
+-[IconPosition::classattpage.h]
+-X=355
+-Y=149
+-
+-[IconPosition::classgenpage.cpp]
+-X=443
+-Y=149
+-
+-[IconPosition::classgenpage.h]
+-X=530
+-Y=149
+-
+-[IconPosition::classopspage.cpp]
+-X=9
+-Y=221
+-
+-[IconPosition::classopspage.h]
+-X=96
+-Y=221
+-
+-[IconPosition::classoptionspage.cpp]
+-X=180
+-Y=221
+-
+-[IconPosition::classoptionspage.h]
+-X=267
+-Y=221
+-
+-[IconPosition::classpropdlg.cpp]
+-X=355
+-Y=221
+-
+-[IconPosition::classpropdlg.h]
+-X=442
+-Y=221
+-
+-[IconPosition::concept.cpp]
+-X=531
+-Y=221
+-
+-[IconPosition::concept.h]
+-X=16
+-Y=293
+-
+-[IconPosition::conceptwidget.cpp]
+-X=95
+-Y=293
+-
+-[IconPosition::conceptwidget.h]
+-X=182
+-Y=293
+-
+-[IconPosition::diagramprintpage.cpp]
+-X=267
+-Y=293
+-
+-[IconPosition::diagramprintpage.h]
+-X=354
+-Y=293
+-
+-[IconPosition::floatingtext.cpp]
+-X=441
+-Y=293
+-
+-[IconPosition::floatingtext.h]
+-X=531
+-Y=293
+-
+-[IconPosition::hi16-app-uml.png]
+-X=7
+-Y=365
+-
+-[IconPosition::hi32-app-uml.png]
+-X=94
+-Y=365
+-
+-[IconPosition::infowidget.cpp]
+-X=181
+-Y=365
+-
+-[IconPosition::infowidget.h]
+-X=272
+-Y=365
+-
+-[IconPosition::listpopupmenu.cpp]
+-X=355
+-Y=365
+-
+-[IconPosition::listpopupmenu.h]
+-X=442
+-Y=365
+-
+-[IconPosition::lo16-app-uml.png]
+-X=529
+-Y=365
+-
+-[IconPosition::lo32-app-uml.png]
+-X=7
+-Y=437
+-
+-[IconPosition::main.cpp]
+-X=106
+-Y=437
+-
+-[IconPosition::messagewidget.cpp]
+-X=441
+-Y=437
+-
+-[IconPosition::messagewidget.h]
+-X=528
+-Y=437
+-
+-[IconPosition::mylistview.cpp]
+-X=7
+-Y=509
+-
+-[IconPosition::mylistview.h]
+-X=97
+-Y=509
+-
+-[IconPosition::mylistviewitem.cpp]
+-X=183
+-Y=509
+-
+-[IconPosition::mylistviewitem.h]
+-X=270
+-Y=509
+-
+-[IconPosition::notemultilineedit.cpp]
+-X=354
+-Y=509
+-
+-[IconPosition::notemultilineedit.h]
+-X=441
+-Y=509
+-
+-[IconPosition::notewidget.cpp]
+-X=531
+-Y=509
+-
+-[IconPosition::notewidget.h]
+-X=9
+-Y=581
+-
+-[IconPosition::objectwidget.cpp]
+-X=94
+-Y=581
+-
+-[IconPosition::objectwidget.h]
+-X=181
+-Y=581
+-
+-[IconPosition::operation.cpp]
+-X=267
+-Y=581
+-
+-[IconPosition::operation.h]
+-X=361
+-Y=581
+-
+-[IconPosition::ot.h]
+-X=463
+-Y=581
+-
+-[IconPosition::parmpropdlg.cpp]
+-X=530
+-Y=581
+-
+-[IconPosition::parmpropdlg.h]
+-X=8
+-Y=653
+-
+-[IconPosition::pics]
+-X=115
+-Y=5
+-
+-[IconPosition::pixmaps]
+-X=195
+-Y=5
+-
+-[IconPosition::selectopdlg.cpp]
+-X=94
+-Y=653
+-
+-[IconPosition::selectopdlg.h]
+-X=181
+-Y=653
+-
+-[IconPosition::templates]
+-X=279
+-Y=5
+-
+-[IconPosition::uml.cpp]
+-X=283
+-Y=653
+-
+-[IconPosition::uml.desktop]
+-X=359
+-Y=655
+-
+-[IconPosition::uml.h]
+-X=463
+-Y=653
+-
+-[IconPosition::umldoc.cpp]
+-X=534
+-Y=653
+-
+-[IconPosition::umldoc.h]
+-X=19
+-Y=725
+-
+-[IconPosition::umlobject.cpp]
+-X=96
+-Y=725
+-
+-[IconPosition::umlobject.h]
+-X=186
+-Y=725
+-
+-[IconPosition::umlui.rc]
+-X=283
+-Y=725
+-
+-[IconPosition::umlview.cpp]
+-X=357
+-Y=725
+-
+-[IconPosition::umlview.h]
+-X=451
+-Y=725
+-
+-[IconPosition::umlwidget.cpp]
+-X=530
+-Y=725
+-
+-[IconPosition::umlwidget.h]
+-X=11
+-Y=797
+-
+-[IconPosition::usecase.cpp]
+-X=95
+-Y=797
+-
+-[IconPosition::usecasewidget.cpp]
+-X=268
+-Y=797
+-
+-[IconPosition::usecasewidget.h]
+-X=355
+-Y=797
+-
+-[IconPosition::worktoolbar.cpp]
+-X=442
+-Y=797
+-
+-[IconPosition::worktoolbar.h]
+-X=529
+-Y=797
+-
+-[IconPosition::x-uml.desktop]
+-X=6
+-Y=869
+--- umbrello/umbrello/generatorinfo.h	(revision 490305)
++++ umbrello/umbrello/generatorinfo.h	(revision 497528)
+@@ -1,34 +0,0 @@
+-/***************************************************************************
+- *                                                                         *
+- *   This program is free software; you can redistribute it and/or modify  *
+- *   it under the terms of the GNU General Public License as published by  *
+- *   the Free Software Foundation; either version 2 of the License, or     *
+- *   (at your option) any later version.                                   *
+- *                                                                         *
+- ***************************************************************************/
+-
+-#ifndef GENERATORINFO_H
+-#define GENERATORINFO_H
+-
+-#include <qstring.h>
+-#include <qdict.h>
+-
+-/**
+- * This is really a leftover from the time when the code generators
+- * resided in a shared library. The QDict<GeneratorInfo> should
+- * probably be changed to a QStringList as the `object' member is
+- * no longer needed.
+- */
+-class GeneratorInfo {
+-public:
+-    QString language;
+-    QString object;
+-};
+-
+-/**
+- * Type for the dictionary of available languages and their generator names.
+- */
+-typedef QDict<GeneratorInfo> GeneratorDict;
+-typedef QDictIterator<GeneratorInfo> GeneratorDictIt;
+-
+-#endif
+--- umbrello/umbrello/uml.h	(revision 490305)
++++ umbrello/umbrello/uml.h	(revision 497528)
+@@ -20,7 +20,6 @@
+ #endif
+ 
+ #include "optionstate.h"
+-#include "generatorinfo.h"
+ 
+ #include <qmap.h>
+ #include <qdict.h>
+@@ -218,13 +217,6 @@
+     CodeGenerator* createGenerator();
+ 
+     /**
+-     * Returns the dictionary of available languages.
+-     *
+-     * @return  Pointer to the dictionary of available languages.
+-     */
+-    GeneratorDict& generatorDict();
+-
+-    /**
+      * Call the refactoring assistant on a classifier.
+      *
+      * @param   Pointer to the classifier to refactor.
+@@ -403,10 +395,8 @@
+ 
+ public slots:
+ 
+-
+     /**
+-     * Sets up generatorDict with all the available code
+-     * generators and calls updateLangSelectMenu()
++     * Fills in m_activeLanguage and calls updateLangSelectMenu()
+      */
+     void initGenerators();
+ 
+@@ -596,7 +586,7 @@
+     /**
+      * Get the language for import and code generation.
+      */
+-    QString getActiveLanguage() const;
++    Uml::Programming_Language getActiveLanguage() const;
+ 
+     /**
+      * Return true if the active language is case sensitive.
+@@ -764,16 +754,9 @@
+     /**
+      * Active language.
+      */
+-    QString m_activeLanguage;
++    Uml::Programming_Language m_activeLanguage;
+ 
+     /**
+-     * Dictionary containing all the info needed to load a Code Generator
+-     * at run time:
+-     * Language (so that the user can choose), library and object name.
+-     */
+-    GeneratorDict m_generatorDict;
+-
+-    /**
+      *  Returns whether we can decode the given mimesource
+      */
+     static bool canDecode(const QMimeSource* mimeSource);
+--- umbrello/umbrello/classifier.cpp	(revision 490305)
++++ umbrello/umbrello/classifier.cpp	(revision 497528)
+@@ -22,6 +22,7 @@
+ #include "umldoc.h"
+ #include "uml.h"
+ #include "umllistview.h"
++#include "object_factory.h"
+ #include "model_utils.h"
+ #include "clipboard/idchangelog.h"
+ #include "dialogs/umloperationdialog.h"
+@@ -744,7 +745,6 @@
+     return templateList;
+ }
+ 
+-
+ void UMLClassifier::saveToXMI(QDomDocument & qDoc, QDomElement & qElement) {
+     QDomElement classifierElement;
+     if (this->isInterface())
+@@ -803,8 +803,22 @@
+     qElement.appendChild( classifierElement );
+ }
+ 
++UMLClassifierListItem* UMLClassifier::makeChildObject(QString xmiTag) {
++    UMLClassifierListItem* pObject = NULL;
++    if (tagEq(xmiTag, "Operation")) {
++        pObject = new UMLOperation(this);
++    } else if (tagEq(xmiTag, "Attribute")) {
++        if (getBaseType() != Uml::ot_Class)
++            return NULL;
++        pObject = new UMLAttribute(this);
++    } else if (tagEq(xmiTag, "TemplateParameter")) {
++        pObject = new UMLTemplate(this);
++    }
++    return pObject;
++}
++
+ bool UMLClassifier::load(QDomElement& element) {
+-
++    UMLClassifierListItem *child = NULL;
+     for (QDomNode node = element.firstChild(); !node.isNull();
+             node = node.nextSibling()) {
+         if (node.isComment())
+@@ -817,44 +831,32 @@
+                 tagEq(tag, "Namespace.contents")) {
+             if (! load(element))
+                 return false;
+-        } else if (tagEq(tag, "TemplateParameter")) {
+-            UMLTemplate* tmplParm = new UMLTemplate(this);
+-            if (!tmplParm->loadFromXMI(element)) {
+-                delete tmplParm;
++        } else if ((child = makeChildObject(tag)) != NULL) {
++            if (child->loadFromXMI(element)) {
++                switch (child->getBaseType()) {
++                    case Uml::ot_Template:
++                        addTemplate( static_cast<UMLTemplate*>(child) );
++                        break;
++                    case Uml::ot_Operation:
++                        if (! addOperation(static_cast<UMLOperation*>(child)) ) {
++                            kdError() << "UMLClassifier::load: error from addOperation(op)"
++                                      << endl;
++                            delete child;
++                        }
++                        break;
++                    case Uml::ot_Attribute:
++                        addAttribute( static_cast<UMLAttribute*>(child) );
++                        break;
++                    default:
++                        break;
++                }
+             } else {
+-                addTemplate(tmplParm);
++                kdWarning() << "UMLClassifier::load: failed to load " << tag << endl;
++                delete child;
+             }
+-        } else if (tagEq(tag, "Operation")) {
+-            UMLOperation* op = new UMLOperation(this);
+-            if (!op->loadFromXMI(element)) {
+-                kdError() << "UMLClassifier::load: error from op->loadFromXMI()"
+-                << endl;
+-                delete op;
+-                return true;
+-                // Returning false here will spoil the entire load.
+-                // At this point the user has been warned that
+-                // something went wrong so let's still try to go on.
+-            }
+-            if (!addOperation(op) ) {
+-                kdError() << "UMLClassifier::load: error from addOperation(op)"
+-                << endl;
+-                delete op;
+-                //return false;
+-                // Returning false here will spoil the entire
+-                // load. At this point the user has been warned
+-                // that something went wrong so let's still try
+-                // our best effort.
+-            }
+-        } else if (Uml::tagEq(tag, "Attribute")) {
+-            UMLAttribute * pAtt = new UMLAttribute(this);
+-            if (!pAtt->loadFromXMI(element)) {
+-                delete pAtt;
+-                return false;
+-            }
+-            addAttribute(pAtt);
+         } else if (!Model_Utils::isCommonXMIAttribute(tag)) {
+             UMLDoc *umldoc = UMLApp::app()->getDocument();
+-            UMLObject *pObject = UMLDoc::makeNewUMLObject(tag);
++            UMLObject *pObject = Object_Factory::makeObjectFromXMI(tag);
+             if( !pObject )
+                 continue;
+             pObject->setUMLPackage(this);
+--- umbrello/umbrello/classifierlistitem.cpp	(revision 490305)
++++ umbrello/umbrello/classifierlistitem.cpp	(revision 497528)
+@@ -20,6 +20,7 @@
+ #include "uml.h"
+ #include "umldoc.h"
+ #include "model_utils.h"
++#include "object_factory.h"
+ 
+ UMLClassifierListItem::UMLClassifierListItem(const UMLObject *parent, QString Name, Uml::IDType id)
+         : UMLObject(parent, Name, id) {
+@@ -81,7 +82,7 @@
+     if (m_pSecondary == NULL) {
+         // Make data type for easily identified cases
+         if (Model_Utils::isCommonDataType(type) || type.contains('*')) {
+-            m_pSecondary = pDoc->createUMLObject(Uml::ot_Datatype, type);
++            m_pSecondary = Object_Factory::createUMLObject(Uml::ot_Datatype, type);
+             kdDebug() << "UMLClassifierListItem::setTypeName: "
+             << "created datatype for " << type << endl;
+         } else {
+--- umbrello/umbrello/nativeimportbase.cpp	(revision 490305)
++++ umbrello/umbrello/nativeimportbase.cpp	(revision 497528)
+@@ -13,6 +13,8 @@
+ #include "nativeimportbase.h"
+ 
+ // qt/kde includes
++#include <qfile.h>
++#include <qtextstream.h>
+ #include <qregexp.h>
+ #include <klocale.h>
+ #include <kdebug.h>
+@@ -135,6 +137,74 @@
+     }
+ }
+ 
++void NativeImportBase::initVars() {
++}
++
++void NativeImportBase::parseFile(QString filename) {
++    const QString msgPrefix = "NativeImportBase::parseFile(" + filename + "): ";
++    if (filename.contains('/')) {
++        QString path = filename;
++        path.remove( QRegExp("/[^/]+$") );
++        kdDebug() << msgPrefix << "adding path " << path << endl;
++        Import_Utils::addIncludePath(path);
++    }
++    if (! QFile::exists(filename)) {
++        if (filename.startsWith("/")) {
++            kdError() << msgPrefix << "cannot find file" << endl;
++            return;
++        }
++        bool found = false;
++        QStringList includePaths = Import_Utils::includePathList();
++        for (QStringList::Iterator pathIt = includePaths.begin();
++                                   pathIt != includePaths.end(); ++pathIt) {
++            QString path = (*pathIt);
++            if (! path.endsWith("/")) {
++                path.append("/");
++            }
++            if (QFile::exists(path + filename)) {
++                filename.prepend(path);
++                found = true;
++                break;
++            }
++        }
++        if (! found) {
++            kdError() << msgPrefix << "cannot find file" << endl;
++            return;
++        }
++    }
++    QFile file(filename);
++    if (! file.open(IO_ReadOnly)) {
++        kdError() << msgPrefix << "cannot open file" << endl;
++        return;
++    }
++    // Scan the input file into the QStringList m_source.
++    m_srcIndex = 0;
++    initVars();
++    QTextStream stream(&file);
++    while (! stream.atEnd()) {
++        QString line = stream.readLine();
++        scan(line);
++    }
++    file.close();
++    // Parse the QStringList m_source.
++    m_klass = NULL;
++    m_currentAccess = Uml::Visibility::Public;
++    m_scopeIndex = 0;
++    m_scope[0] = NULL;
++    const uint srcLength = m_source.count();
++    for (m_srcIndex = 0; m_srcIndex < srcLength; m_srcIndex++) {
++        const QString& firstToken = m_source[m_srcIndex];
++        //kdDebug() << '"' << firstToken << '"' << endl;
++        if (firstToken.startsWith(m_singleLineCommentIntro)) {
++            m_comment = firstToken.mid(m_singleLineCommentIntro.length());
++            continue;
++        }
++        if (! parseStmt())
++           skipStmt();
++        m_comment = QString::null;
++    }
++}
++
+ void NativeImportBase::importFiles(QStringList fileList) {
+     UMLDoc *umldoc = UMLApp::app()->getDocument();
+     m_parsedFiles.clear();
+--- umbrello/umbrello/model_utils.cpp	(revision 490305)
++++ umbrello/umbrello/model_utils.cpp	(revision 497528)
+@@ -22,15 +22,21 @@
+ #include <kdebug.h>
+ 
+ // app includes
++#include "inputdialog.h"
+ #include "umlobject.h"
+ #include "umlpackagelist.h"
+ #include "package.h"
+ #include "classifier.h"
++#include "enum.h"
++#include "entity.h"
+ #include "template.h"
++#include "operation.h"
++#include "attribute.h"
+ #include "association.h"
+ #include "umlrole.h"
+ #include "umldoc.h"
+ #include "uml.h"
++#include "codegenerator.h"
+ 
+ namespace Model_Utils {
+ 
+@@ -208,6 +214,88 @@
+     return NULL;
+ }
+ 
++QString uniqObjectName(Uml::Object_Type type, QString prefix,
++                       UMLPackage *parentPkg /* = NULL */) {
++    QString currentName = prefix;
++    if (currentName.isEmpty()) {
++        if(type == Uml::ot_Class)
++            currentName = i18n("new_class");
++        else if(type == Uml::ot_Actor)
++            currentName = i18n("new_actor");
++        else if(type == Uml::ot_UseCase)
++            currentName = i18n("new_usecase");
++        else if(type == Uml::ot_Package)
++            currentName = i18n("new_package");
++        else if(type == Uml::ot_Component)
++            currentName = i18n("new_component");
++        else if(type == Uml::ot_Node)
++            currentName = i18n("new_node");
++        else if(type == Uml::ot_Artifact)
++            currentName = i18n("new_artifact");
++        else if(type == Uml::ot_Interface)
++            currentName = i18n("new_interface");
++        else if(type == Uml::ot_Datatype)
++            currentName = i18n("new_datatype");
++        else if(type == Uml::ot_Enum)
++            currentName = i18n("new_enum");
++        else if(type == Uml::ot_Entity)
++            currentName = i18n("new_entity");
++        else if(type == Uml::ot_Association)
++            currentName = i18n("new_association");
++        else {
++            currentName = i18n("new_object");
++            kdWarning() << "unknown object type in umldoc::uniqObjectName()" << endl;
++        }
++    }
++    UMLDoc *doc = UMLApp::app()->getDocument();
++    QString name = currentName;
++    for (int number = 1; !doc->isUnique(name, parentPkg); number++)  {
++        name = currentName + "_" + QString::number(number);
++    }
++    return name;
++}
++
++UMLObject* createChildObject(UMLObject* umlobject, Uml::Object_Type type) {
++    UMLObject* returnObject = NULL;
++    switch (type) {
++    case Uml::ot_Attribute: {
++            UMLClassifier *c = dynamic_cast<UMLClassifier*>(umlobject);
++            if (c && !c->isInterface())
++                returnObject = c->createAttribute();
++            break;
++        }
++    case Uml::ot_Operation: {
++            UMLClassifier *c = dynamic_cast<UMLClassifier*>(umlobject);
++            if (c)
++                returnObject = c->createOperation();
++            break;
++        }
++    case Uml::ot_Template: {
++            UMLClassifier *c = dynamic_cast<UMLClassifier*>(umlobject);
++            if (c)
++                returnObject = c->createTemplate();
++            break;
++        }
++    case Uml::ot_EnumLiteral: {
++            UMLEnum* umlenum = dynamic_cast<UMLEnum*>(umlobject);
++            if (umlenum) {
++                returnObject = umlenum->createEnumLiteral();
++            }
++            break;
++        }
++    case Uml::ot_EntityAttribute: {
++            UMLEntity* umlentity = dynamic_cast<UMLEntity*>(umlobject);
++            if (umlentity) {
++                returnObject = umlentity->createEntityAttribute();
++            }
++            break;
++        }
++    default:
++        kdDebug() << "ERROR UMLDoc::createChildObject type:" << type << endl;
++    }
++    return returnObject;
++}
++
+ bool isCommonXMIAttribute( const QString &tag ) {
+     bool retval = (Uml::tagEq(tag, "name") ||
+                    Uml::tagEq(tag, "visibility") ||
+@@ -227,20 +315,16 @@
+ }
+ 
+ bool isCommonDataType(QString type) {
+-    const char *types[] = { "void", "string",
+-                            "bool", "boolean",
+-                            "char", "unsigned char",
+-                            "short", "unsigned short",
+-                            "int", "unsigned int",
+-                            "long", "unsigned long",
+-                            "float", "double"
+-                          };
+-    const int n_types = sizeof(types) / sizeof(const char *);
+-    const QString lcType = type.lower();
+-    int i = 0;
+-    for (; i < n_types; i++) {
+-        if (lcType == types[i])
++    const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
++    QStringList dataTypes = UMLApp::app()->getGenerator()->defaultDatatypes();
++    QStringList::Iterator end(dataTypes.end());
++    for (QStringList::Iterator it = dataTypes.begin(); it != end; ++it) {
++        if (caseSensitive) {
++            if (type == *it)
++                return true;
++        } else if (type.lower() == (*it).lower()) {
+             return true;
++        }
+     }
+     return false;
+ }
+@@ -346,13 +430,12 @@
+     if (pos == -1)
+         return PS_Illegal_MethodName;
+     desc.m_name = pat.cap(1);
+-    // Remove possible empty parentheses ()
+-    m.remove( QRegExp("\\s*\\(\\s*\\)") );
+     desc.m_pReturnType = NULL;
+-    pat = QRegExp( ":\\s*(\\w[\\w\\. ]*)$" );
++    pat = QRegExp("\\) *:(.*)$");
+     pos = pat.search(m);
+     if (pos != -1) {  // return type is optional
+         QString retType = pat.cap(1);
++        retType = retType.stripWhiteSpace();
+         if (retType != "void") {
+             UMLObject *pRetType = owningScope->findTemplate(retType);
+             if (pRetType == NULL) {
+@@ -363,6 +446,8 @@
+             desc.m_pReturnType = pRetType;
+         }
+     }
++    // Remove possible empty parentheses ()
++    m.remove( QRegExp("\\s*\\(\\s*\\)") );
+     desc.m_args.clear();
+     pat = QRegExp( "\\((.*)\\)" );
+     pos = pat.search(m);
+@@ -392,5 +477,77 @@
+     return text[(unsigned) value];
+ }
+ 
++QString progLangToString(Uml::Programming_Language pl) {
++    switch (pl) {
++        case Uml::pl_ActionScript:
++            return "ActionScript";
++        case Uml::pl_Ada:
++            return "Ada";
++        case Uml::pl_Cpp:
++            return "C++";
++        // case Uml::pl_Csharp:
++            // return "C#";
++        case Uml::pl_IDL:
++            return "IDL";
++        case Uml::pl_Java:
++            return "Java";
++        case Uml::pl_JavaScript:
++            return "JavaScript";
++        case Uml::pl_Perl:
++            return "Perl";
++        case Uml::pl_PHP:
++            return "PHP";
++        case Uml::pl_PHP5:
++            return "PHP5";
++        case Uml::pl_Python:
++            return "Python";
++        case Uml::pl_Ruby:
++            return "Ruby";
++        case Uml::pl_SQL:
++            return "SQL";
++        case Uml::pl_Tcl:
++            return "Tcl";
++        case Uml::pl_XMLSchema:
++            return "XMLSchema";
++        default:
++            break;
++    }
++    return QString::null;
++}
++
++Uml::Programming_Language stringToProgLang(QString str) {
++    if (str == "ActionScript")
++        return Uml::pl_ActionScript;
++    if (str == "Ada")
++        return Uml::pl_Ada;
++    if (str == "C++" || str == "Cpp")  // "Cpp" only for bkwd compatibility
++        return Uml::pl_Cpp;
++    // if (str == "C#")
++        // return Uml::pl_Csharp;
++    if (str == "IDL")
++        return Uml::pl_IDL;
++    if (str == "Java")
++        return Uml::pl_Java;
++    if (str == "JavaScript")
++        return Uml::pl_JavaScript;
++    if (str == "Perl")
++        return Uml::pl_Perl;
++    if (str == "PHP")
++        return Uml::pl_PHP;
++    if (str == "PHP5")
++        return Uml::pl_PHP5;
++    if (str == "Python")
++        return Uml::pl_Python;
++    if (str == "Ruby")
++        return Uml::pl_Ruby;
++    if (str == "SQL")
++        return Uml::pl_SQL;
++    if (str == "Tcl")
++        return Uml::pl_Tcl;
++    if (str == "XMLSchema")
++        return Uml::pl_XMLSchema;
++    return Uml::pl_Reserved;
++}
++
+ }  // namespace Model_Utils
+ 
+--- umbrello/umbrello/javaimport.h	(revision 0)
++++ umbrello/umbrello/javaimport.h	(revision 497528)
+@@ -0,0 +1,59 @@
++#ifndef JAVAIMPORT_H
++#define JAVAIMPORT_H
++
++/***************************************************************************
++ *                                                                         *
++ *   This program is free software; you can redistribute it and/or modify  *
++ *   it under the terms of the GNU General Public License as published by  *
++ *   the Free Software Foundation; either version 2 of the License, or     *
++ *   (at your option) any later version.                                   *
++ *                                                                         *
++ *  copyright (C) 2006                                                     *
++ *  Umbrello UML Modeller Authors <uml-devel@ uml.sf.net>                  *
++ ***************************************************************************/
++
++#include "nativeimportbase.h"
++
++/**
++ * Java code import
++ * @author Oliver Kellogg
++ * Bugs and comments to uml-devel at lists.sf.net or http://bugs.kde.org
++ */
++class JavaImport : public NativeImportBase {
++public:
++    JavaImport();
++    virtual ~JavaImport();
++
++protected:
++    /**
++     * Reimplement operation from NativeImportBase.
++     */
++    void initVars();
++
++    /**
++     * Implement abstract operation from NativeImportBase.
++     */
++    bool parseStmt();
++
++    /**
++     * Implement abstract operation from NativeImportBase.
++     */
++    void fillSource(QString word);
++
++    /**
++     * Advance NativeImportBase::m_srcIndex to the index of the
++     * corresponding closing character of the given opening.
++     * Nested opening/closing pairs are respected.
++     * Valid openers are:    '{'  '['  '('  '<'
++     *
++     * @return  True for success, false for misuse (invalid opener) or
++     *          if no matching closing character is found in m_source.
++     */
++    bool skipToClosing(QChar opener);
++
++    QString joinTypename();
++    bool m_isStatic;
++};
++
++#endif
++
+--- umbrello/umbrello/object_factory.cpp	(revision 0)
++++ umbrello/umbrello/object_factory.cpp	(revision 497528)
+@@ -0,0 +1,163 @@
++/***************************************************************************
++ *                                                                         *
++ *   This program is free software; you can redistribute it and/or modify  *
++ *   it under the terms of the GNU General Public License as published by  *
++ *   the Free Software Foundation; either version 2 of the License, or     *
++ *   (at your option) any later version.                                   *
++ *                                                                         *
++ *  copyright (C) 2006                                                     *
++ *  Umbrello UML Modeller Authors <uml-devel@ uml.sf.net>                  *
++ ***************************************************************************/
++
++// own header
++#include "object_factory.h"
++
++// qt/kde includes
++#include <qregexp.h>
++#include <qstringlist.h>
++#include <klocale.h>
++#include <kmessagebox.h>
++#include <kdebug.h>
++
++// app includes
++#include "inputdialog.h"
++#include "umlobject.h"
++#include "umlpackagelist.h"
++#include "package.h"
++#include "classifier.h"
++#include "datatype.h"
++#include "enum.h"
++#include "entity.h"
++#include "actor.h"
++#include "usecase.h"
++#include "component.h"
++#include "node.h"
++#include "artifact.h"
++#include "stereotype.h"
++#include "association.h"
++#include "umldoc.h"
++#include "uml.h"
++#include "codegenerator.h"
++#include "model_utils.h"
++
++namespace Object_Factory {
++
++UMLObject* createUMLObject(Uml::Object_Type type, const QString &n,
++                           UMLPackage *parentPkg /* = NULL */,
++                           bool prepend /* = false */) {
++    UMLDoc *doc = UMLApp::app()->getDocument();
++    bool ok = false;
++    QString name;
++    if( !n.isEmpty() && doc->isUnique(n, parentPkg) )
++    {
++        name = n;
++    }
++    else
++    {
++        name = Model_Utils::uniqObjectName(type, n, parentPkg);
++        bool bValidNameEntered = false;
++        do {
++            name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), name, &ok, (QWidget*)UMLApp::app());
++            if (!ok) {
++                return 0;
++            }
++            if (name.length() == 0) {
++                KMessageBox::error(0, i18n("That is an invalid name."),
++                                   i18n("Invalid Name"));
++                continue;
++            }
++            if (doc->getCurrentCodeGenerator() != NULL &&
++                    doc->getCurrentCodeGenerator()->isReservedKeyword(name)) {
++                KMessageBox::error(0, i18n("This is a reserved keyword for the language of the configured code generator."),
++                                   i18n("Reserved Keyword"));
++                continue;
++            }
++            if (! doc->isUnique(name, parentPkg)) {
++                KMessageBox::error(0, i18n("That name is already being used."),
++                                   i18n("Not a Unique Name"));
++                continue;
++            }
++            bValidNameEntered = true;
++        } while (bValidNameEntered == false);
++    }
++    UMLObject *o = NULL;
++    if(type == Uml::ot_Actor) {
++        o = new UMLActor(name);
++    } else if(type == Uml::ot_UseCase) {
++        o = new UMLUseCase(name);
++    } else if(type == Uml::ot_Class ) {
++        o = new UMLClassifier(name);
++    } else if(type == Uml::ot_Package) {
++        o = new UMLPackage(name);
++    } else if(type == Uml::ot_Component) {
++        o = new UMLComponent(name);
++    } else if(type == Uml::ot_Node) {
++        o = new UMLNode(name);
++    } else if(type == Uml::ot_Artifact) {
++        o = new UMLArtifact(name);
++    } else if(type == Uml::ot_Interface) {
++        UMLClassifier *c = new UMLClassifier(name);
++        c->setInterface();
++        o = c;
++    } else if(type == Uml::ot_Datatype) {
++        o = new UMLDatatype(name);
++    } else if(type == Uml::ot_Enum) {
++        o = new UMLEnum(name);
++    } else if(type == Uml::ot_Entity) {
++        o = new UMLEntity(name);
++    } else {
++        kdWarning() << "CreateUMLObject(int) error unknown type: " << type << endl;
++        return (UMLObject*)0L;
++    }
++    o->setUMLPackage(parentPkg);
++    doc->addUMLObject(o, prepend);
++    doc->signalUMLObjectCreated(o);
++    return o;
++}
++
++UMLObject* makeObjectFromXMI(const QString &xmiTag) {
++    UMLObject* pObject = 0;
++    if (Uml::tagEq(xmiTag, "UseCase")) {
++        pObject = new UMLUseCase();
++    } else if (Uml::tagEq(xmiTag, "Actor")) {
++        pObject = new UMLActor();
++    } else if (Uml::tagEq(xmiTag, "Class")) {
++        pObject = new UMLClassifier();
++    } else if (Uml::tagEq(xmiTag, "Package")) {
++        pObject = new UMLPackage();
++    } else if (Uml::tagEq(xmiTag, "Component")) {
++        pObject = new UMLComponent();
++    } else if (Uml::tagEq(xmiTag, "Node")) {
++        pObject = new UMLNode();
++    } else if (Uml::tagEq(xmiTag, "Artifact")) {
++        pObject = new UMLArtifact();
++    } else if (Uml::tagEq(xmiTag, "Interface")) {
++        UMLClassifier *c = new UMLClassifier();
++        c->setInterface();
++        pObject = c;
++    } else if (Uml::tagEq(xmiTag, "DataType") || Uml::tagEq(xmiTag, "Primitive")
++               || Uml::tagEq(xmiTag, "Datatype")) {   // for bkwd compat.
++        pObject = new UMLDatatype();
++    } else if (Uml::tagEq(xmiTag, "Enumeration") ||
++               Uml::tagEq(xmiTag, "Enum")) {   // for bkwd compat.
++        pObject = new UMLEnum();
++    } else if (Uml::tagEq(xmiTag, "Entity")) {
++        pObject = new UMLEntity();
++    } else if (Uml::tagEq(xmiTag, "Stereotype")) {
++        pObject = new UMLStereotype();
++    } else if (Uml::tagEq(xmiTag, "Association") ||
++               Uml::tagEq(xmiTag, "AssociationClass")) {
++        pObject = new UMLAssociation();
++    } else if (Uml::tagEq(xmiTag, "Generalization")) {
++        pObject = new UMLAssociation(Uml::at_Generalization);
++    } else if (Uml::tagEq(xmiTag, "Realization") ||
++               Uml::tagEq(xmiTag, "Abstraction")) {
++        pObject = new UMLAssociation(Uml::at_Realization);
++    } else if (Uml::tagEq(xmiTag, "Dependency")) {
++        pObject = new UMLAssociation(Uml::at_Dependency);
++    }
++    return pObject;
++}
++
++}  // end namespace Object_Factory
++
+--- umbrello/umbrello/umlrole.cpp	(revision 490305)
++++ umbrello/umbrello/umlrole.cpp	(revision 497528)
+@@ -118,7 +118,7 @@
+             roleElement.setAttribute("aggregation", "composite");
+             break;
+         case Uml::at_Aggregation:
+-            roleElement.setAttribute("aggregation", "shared");
++            roleElement.setAttribute("aggregation", "aggregate");
+             break;
+         default:
+             roleElement.setAttribute("aggregation", "none");
+--- umbrello/umbrello/pythonimport.h	(revision 0)
++++ umbrello/umbrello/pythonimport.h	(revision 497528)
+@@ -0,0 +1,76 @@
++#ifndef PYTHONIMPORT_H
++#define PYTHONIMPORT_H
++
++/***************************************************************************
++ *                                                                         *
++ *   This program is free software; you can redistribute it and/or modify  *
++ *   it under the terms of the GNU General Public License as published by  *
++ *   the Free Software Foundation; either version 2 of the License, or     *
++ *   (at your option) any later version.                                   *
++ *                                                                         *
++ *  copyright (C) 2006                                                     *
++ *  Umbrello UML Modeller Authors <uml-devel@ uml.sf.net>                  *
++ ***************************************************************************/
++
++#include "nativeimportbase.h"
++
++/**
++ * Python code import
++ * @author Oliver Kellogg
++ * Bugs and comments to uml-devel at lists.sf.net or http://bugs.kde.org
++ */
++class PythonImport : public NativeImportBase {
++public:
++    PythonImport();
++    virtual ~PythonImport();
++
++protected:
++    /**
++     * Reimplement operation from NativeImportBase.
++     */
++    void initVars();
++
++    /**
++     * Implement abstract operation from NativeImportBase.
++     */
++    bool parseStmt();
++
++    /**
++     * Implement abstract operation from NativeImportBase.
++     */
++    void fillSource(QString line);
++
++    /**
++     * Reimplement operation from NativeImportBase.
++     * In addition to handling multiline comments, this method transforms
++     * changes in leading indentation into braces (opening brace for increase
++     * in indentation, closing brace for decrease in indentation) in m_source.
++     * Removal of Python's indentation sensitivity simplifies subsequent
++     * processing using Umbrello's native import framework.
++     */
++    bool preprocess(QString& line);
++
++    /**
++     * Skip ahead to outermost closing brace
++     */
++    void skipBody();
++
++    /**
++     * Buffer for number of indentation characters (whitespace,
++     * i.e. tabs or spaces) at beginning of input line.
++     */
++    int m_srcIndent[100];
++
++    /**
++     * Index for m_srcIndent[]. Index 0 is reserved and contains 0.
++     */
++    int m_srcIndentIndex;
++
++    /**
++     * Auxiliary flag denoting the opening of a block
++     */
++    bool m_braceWasOpened;
++};
++
++#endif
++
+--- umbrello/umbrello/umlwidget.cpp	(revision 490305)
++++ umbrello/umbrello/umlwidget.cpp	(revision 497528)
+@@ -33,7 +33,8 @@
+ #include "dialogs/settingsdlg.h"
+ #include "codedocument.h"
+ #include "floatingtext.h"
+-
++#include "docwindow.h"
++#include "dialogs/classpropdlg.h"
+ #include "clipboard/idchangelog.h"
+ 
+ using namespace Uml;
+@@ -103,6 +104,7 @@
+     m_pObject = other.m_pObject;
+     m_pView = other.m_pView;
+     m_pMenu = other.m_pMenu;
++    m_bResizable = other.m_bResizable;
+     m_bResizing = other.m_bResizing;
+     m_nPressOffsetX = other.m_nPressOffsetX;
+     m_nPressOffsetY = other.m_nPressOffsetY;
+@@ -344,8 +346,9 @@
+     m_nOldH = height();
+     const int m = 10;
+     //see if clicked on bottom right corner
+-    if( (m_nOldX + m_nPressOffsetX) >= (getX() + width() - m) &&
+-        (m_nOldY + m_nPressOffsetY) >= (getY() + height() - m) && me->button() == Qt::LeftButton) {
++    if( m_bResizable && me->button() == Qt::LeftButton &&
++        (m_nOldX + m_nPressOffsetX) >= (getX() + width() - m) &&
++        (m_nOldY + m_nPressOffsetY) >= (getY() + height() - m)) {
+         m_bResizing = true;
+         m_pView->setCursor(WidgetBase::m_Type == Uml::wt_Message ?
+                            KCursor::sizeVerCursor() : KCursor::sizeFDiagCursor());
+@@ -446,6 +449,7 @@
+     for (int i = 0; i < (int)FT_INVALID; ++i)
+         m_pFontMetrics[(UMLWidget::FontType)i] = 0;
+ 
++    m_bResizable = true;
+     m_bResizing = false;
+     m_bMouseOver = false;
+ 
+@@ -495,9 +499,9 @@
+                 wt == wt_Component || wt == wt_Artifact ||
+                 wt == wt_Node || wt == wt_Enum || wt == wt_Entity ||
+                 (wt == wt_Class && m_pView -> getType() == dt_Class)) {
+-            m_pDoc -> showProperties(this);
++            showProperties();
+         } else if (wt == wt_Object) {
+-            m_pDoc -> showProperties(m_pObject);
++            m_pObject->showProperties();
+         } else {
+             kdWarning() << "making properties dialogue for unknown widget type" << endl;
+         }
+@@ -675,7 +679,7 @@
+     update();
+ }
+ 
+-void UMLWidget::drawSelected(QPainter * p, int offsetX, int offsetY, bool resizeable) {
++void UMLWidget::drawSelected(QPainter * p, int offsetX, int offsetY) {
+     int w = width();
+     int h = height();
+     int s = 4;
+@@ -685,7 +689,7 @@
+     p -> fillRect(offsetX + w - s, offsetY, s, s, brush);
+ 
+     // Draw the resize anchor in the lower right corner.
+-    if (resizeable) {
++    if (m_bResizable) {
+         brush.setColor(Qt::red);
+         const int right = offsetX + w;
+         const int bottom = offsetY + h;
+@@ -802,6 +806,23 @@
+     }
+ }
+ 
++bool UMLWidget::showProperties() {
++    // will already be selected so make sure docWindow updates the doc
++    // back it the widget
++    DocWindow *docwindow = UMLApp::app()->getDocWindow();
++    docwindow->updateDocumentation( false );
++    ClassPropDlg *dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this);
++
++    bool modified = false;
++    if (dlg->exec()) {
++        docwindow->showDocumentation( getUMLObject() , true );
++        UMLApp::app()->getDocument()->setModified(true);
++        modified = true;
++    }
++    dlg->close(true); //wipe from memory
++    return modified;
++}
++
+ void UMLWidget::startPopupMenu( const QPoint &At) {
+     slotRemovePopupMenu();
+ 
+--- umbrello/umbrello/toolbarstateother.cpp	(revision 490305)
++++ umbrello/umbrello/toolbarstateother.cpp	(revision 497528)
+@@ -34,6 +34,7 @@
+ #include "activitywidget.h"
+ #include "forkjoinwidget.h"
+ #include "statewidget.h"
++#include "object_factory.h"
+ 
+ using namespace Uml;
+ 
+@@ -166,7 +167,7 @@
+             // Is UMLObject?
+ 
+             m_pUMLView->setCreateObject(true);
+-            UMLApp::app()->getDocument()->createUMLObject(getObjectType(getButton()));
++            Object_Factory::createUMLObject(getObjectType(getButton()));
+         }
+     }
+ }
+--- umbrello/umbrello/floatingtext.cpp	(revision 490305)
++++ umbrello/umbrello/floatingtext.cpp	(revision 497528)
+@@ -57,6 +57,7 @@
+     m_Type = Uml::wt_Text;
+     // initialize non-saved (i.e. volatile) data
+     m_pLink = NULL;
++    UMLWidget::m_bResizable = false;
+ }
+ 
+ FloatingText::~FloatingText() {
+@@ -111,7 +112,7 @@
+                     m_pLink->setCustomOpText(opText);
+                 return;
+             }
+-            UMLObject* umlObj = UMLApp::app()->getDocument()->createChildObject(c, Uml::ot_Operation);
++            UMLObject* umlObj = Model_Utils::createChildObject(c, Uml::ot_Operation);
+             if (umlObj) {
+                 UMLOperation* newOperation = static_cast<UMLOperation*>( umlObj );
+                 m_pLink->setOperation(newOperation);
+--- umbrello/umbrello/forkjoinwidget.cpp	(revision 490305)
++++ umbrello/umbrello/forkjoinwidget.cpp	(revision 497528)
+@@ -52,11 +52,7 @@
+     }
+ }
+ 
+-void ForkJoinWidget::drawSelected(QPainter * p, int offsetX, int offsetY, bool resizeable) {
+-    if (! resizeable) {
+-        UMLWidget::drawSelected(p, offsetX, offsetY, false);
+-        return;
+-    }
++void ForkJoinWidget::drawSelected(QPainter *, int /*offsetX*/, int /*offsetY*/) {
+ }
+ 
+ void ForkJoinWidget::constrain(int& width, int& height) {
+--- umbrello/umbrello/messagewidget.cpp	(revision 490305)
++++ umbrello/umbrello/messagewidget.cpp	(revision 497528)
+@@ -41,6 +41,7 @@
+         y -= m_pOw[Uml::B]->getHeight() / 2;
+         m_pOw[Uml::B]->setY(y);
+     }
++    UMLWidget::m_bResizable = (m_pOw[Uml::A] == m_pOw[Uml::B]);
+ 
+     calculateWidget();
+     y = y < getMinHeight() ? getMinHeight() : y;
+@@ -213,7 +214,7 @@
+     }
+ 
+     if (m_bSelected)
+-        drawSelected(&p, offsetX, offsetY, m_pOw[Uml::A] == m_pOw[Uml::B]);
++        drawSelected(&p, offsetX, offsetY);
+ }
+ 
+ void MessageWidget::drawCreation(QPainter& p, int offsetX, int offsetY) {
+@@ -242,7 +243,7 @@
+     }
+ 
+     if (m_bSelected)
+-        drawSelected(&p, offsetX, offsetY, false);
++        drawSelected(&p, offsetX, offsetY);
+ }
+ 
+ int MessageWidget::onWidget(const QPoint & p) {
+@@ -335,7 +336,7 @@
+     emit sigMessageMoved();
+ }
+ 
+-void MessageWidget::resizeEvent(QResizeEvent */*re*/) {
++void MessageWidget::resizeEvent(QResizeEvent* /*re*/) {
+ }
+ 
+ void MessageWidget::calculateWidget() {
+@@ -736,6 +737,7 @@
+ 
+ void MessageWidget::setWidget(ObjectWidget * ow, Uml::Role_Type role) {
+     m_pOw[role] = ow;
++    UMLWidget::m_bResizable = (m_pOw[Uml::A] == m_pOw[Uml::B]);
+ }
+ 
+ ObjectWidget* MessageWidget::getWidget(Uml::Role_Type role) {
+@@ -803,6 +805,7 @@
+         << ID2STR(bId) << " is not an ObjectWidget" << endl;
+         return false;
+     }
++    UMLWidget::m_bResizable = (m_pOw[Uml::A] == m_pOw[Uml::B]);
+ 
+     UMLClassifier *c = dynamic_cast<UMLClassifier*>( pWB->getUMLObject() );
+     if (c) {
+--- umbrello/umbrello/Makefile.am	(revision 490305)
++++ umbrello/umbrello/Makefile.am	(revision 497528)
+@@ -17,6 +17,7 @@
+ classifiercodedocument.cpp \
+ classifierlistitem.cpp \
+ classifierwidget.cpp \
++classimport.cpp \
+ codeaccessormethod.cpp \
+ codeblock.cpp \
+ codeblockwithcomments.cpp \
+@@ -52,6 +53,7 @@
+ idlimport.cpp \
+ import_utils.cpp \
+ infowidget.cpp \
++javaimport.cpp \
+ kstartuplogo.cpp \
+ linepath.cpp \
+ linkwidget.cpp \
+@@ -64,6 +66,7 @@
+ nodewidget.cpp \
+ notewidget.cpp \
+ objectwidget.cpp \
++object_factory.cpp \
+ operation.cpp \
+ ownedcodeblock.cpp \
+ ownedhierarchicalcodeblock.cpp \
+@@ -71,6 +74,7 @@
+ packagewidget.cpp \
+ plugin.cpp \
+ pluginloader.cpp \
++pythonimport.cpp \
+ seqlinewidget.cpp \
+ statewidget.cpp \
+ stereotype.cpp \
+--- umbrello/umbrello/umlobject.h	(revision 490305)
++++ umbrello/umbrello/umlobject.h	(revision 497528)
+@@ -247,6 +247,17 @@
+     void setInPaste(bool bInPaste = true);
+ 
+     /**
++     * This method is called if you wish to see the properties of a
++     * UMLObject.  A dialog box will be displayed from which you
++     * can change the object's properties.
++     *
++     * @param page              The page to show.
++     * @param assoc             Whether to show association page.
++     * @return          True if we modified the object.
++     */
++    bool showProperties(int page = 0, bool assoc = false);
++
++    /**
+      * Resolve referenced objects (if any.)
+      * Needs to be called after all UML objects are loaded from file.
+      * This needs to be done after all model objects are loaded because
+--- umbrello/umbrello/linepath.cpp	(revision 490305)
++++ umbrello/umbrello/linepath.cpp	(revision 497528)
+@@ -810,15 +810,13 @@
+ QColor LinePath::getLineColor() {
+     if( !m_pAssociation )
+         return Qt::black;
+-    UMLView * view =  (UMLView *)m_pAssociation -> parent();
+-    return view -> getLineColor();
++    return m_pAssociation -> getLineColor();
+ }
+ 
+ uint LinePath::getLineWidth() {
+     if( !m_pAssociation )
+         return 0;
+-    UMLView * view =  (UMLView *)m_pAssociation -> parent();
+-    int viewLineWidth = view->getLineWidth();
++    int viewLineWidth = m_pAssociation -> getLineWidth();
+     if ( viewLineWidth >= 0 && viewLineWidth <= 10 )
+         return viewLineWidth;
+     else {
+--- umbrello/umbrello/operation.h	(revision 490305)
++++ umbrello/umbrello/operation.h	(revision 497528)
+@@ -184,6 +184,16 @@
+     bool isLifeOperation();
+ 
+     /**
++     * Sets whether this operation is a query (C++ "const".)
++     */
++    void setConst(bool b);
++
++    /**
++     * Returns whether this operation is a query (C++ "const".)
++     */
++    bool getConst() const;
++
++    /**
+      * Saves to the <UML:Operation> XMI element.
+      */
+     void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
+@@ -196,6 +206,7 @@
+ 
+ private:
+     UMLAttributeList m_List;
++    bool m_bConst;
+ };
+ 
+ #endif
+--- umbrello/umbrello/classimport.h	(revision 490305)
++++ umbrello/umbrello/classimport.h	(revision 497528)
+@@ -36,6 +36,11 @@
+      */
+     virtual void importFiles(QStringList files) = 0;
+ 
++    /**
++     * Factory method.
++     */
++    static ClassImport *createImporterByFileExt(QString filename);
++
+ };
+ 
+ #endif
+--- umbrello/umbrello/javaimport.cpp	(revision 0)
++++ umbrello/umbrello/javaimport.cpp	(revision 497528)
+@@ -0,0 +1,321 @@
++/***************************************************************************
++ *                                                                         *
++ *   This program is free software; you can redistribute it and/or modify  *
++ *   it under the terms of the GNU General Public License as published by  *
++ *   the Free Software Foundation; either version 2 of the License, or     *
++ *   (at your option) any later version.                                   *
++ *                                                                         *
++ *  copyright (C) 2006                                                     *
++ *  Umbrello UML Modeller Authors <uml-devel@ uml.sf.net>                  *
++ ***************************************************************************/
++
++// own header
++#include "javaimport.h"
++
++// qt/kde includes
++#include <qfile.h>
++#include <qtextstream.h>
++#include <qstringlist.h>
++#include <qregexp.h>
++#include <kdebug.h>
++// app includes
++#include "import_utils.h"
++#include "uml.h"
++#include "umldoc.h"
++#include "umlpackagelist.h"
++#include "package.h"
++#include "classifier.h"
++#include "enum.h"
++#include "operation.h"
++#include "attribute.h"
++
++JavaImport::JavaImport() : NativeImportBase("//") {
++    initVars();
++}
++
++JavaImport::~JavaImport() {
++}
++
++void JavaImport::initVars() {
++    m_isStatic = false;
++}
++
++/// Catenate possible template arguments/array dimensions to the end of the type name.
++QString JavaImport::joinTypename() {
++    QString typeName = m_source[m_srcIndex];
++    if (m_source[m_srcIndex + 1] == "<" ||
++        m_source[m_srcIndex + 1] == "[") {
++        uint start = ++m_srcIndex;
++        if (! skipToClosing(m_source[start][0]))
++            return typeName;
++        for (uint i = start; i <= m_srcIndex; i++) {
++            typeName += m_source[i];
++        }
++    }
++    return typeName;
++}
++
++void JavaImport::fillSource(QString word) {
++    QString lexeme;
++    const uint len = word.length();
++    bool inString = false;
++    for (uint i = 0; i < len; i++) {
++        const QChar& c = word[i];
++        if (c == '"') {
++            lexeme += c;
++            if (i == 0 || word[i - 1] != '\\') {
++                if (inString) {
++                    m_source.append(lexeme);
++                    lexeme = QString::null;
++                }
++                inString = !inString;
++            }
++        } else if (inString ||
++                   c.isLetterOrNumber() || c == '_' || c == '.') {
++            lexeme += c;
++        } else {
++            if (!lexeme.isEmpty()) {
++                m_source.append(lexeme);
++                lexeme = QString::null;
++            }
++            m_source.append(QString(c));
++        }
++    }
++    if (!lexeme.isEmpty())
++        m_source.append(lexeme);
++}
++
++bool JavaImport::skipToClosing(QChar opener) {
++    QString closing;
++    switch (opener) {
++        case '{':
++            closing = "}";
++            break;
++        case '[':
++            closing = "]";
++            break;
++        case '(':
++            closing = ")";
++            break;
++        case '<':
++            closing = ">";
++            break;
++        default:
++            kdError() << "JavaImport::skipToClosing(" << opener
++                << "): " << "illegal input character" << endl;
++            return false;
++    }
++    const QString opening(opener);
++    skipStmt(opening);
++    const uint srcLength = m_source.count();
++    int nesting = 0;
++    while (m_srcIndex < srcLength) {
++        QString nextToken = advance();
++        if (nextToken == closing) {
++            if (nesting <= 0)
++                break;
++            nesting--;
++        } else if (nextToken == opening) {
++            nesting++;
++        }
++    }
++    if (m_srcIndex == srcLength)
++        return false;
++    return true;
++}
++
++bool JavaImport::parseStmt() {
++    const uint srcLength = m_source.count();
++    const QString& keyword = m_source[m_srcIndex];
++    //kdDebug() << '"' << keyword << '"' << endl;
++    if (keyword == "package") {
++        const QString& qualifiedName = advance();
++        QStringList names = QStringList::split(".", qualifiedName);
++        for (QStringList::Iterator it = names.begin(); it != names.end(); ++it) {
++            QString name = (*it);
++            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
++                            name, m_scope[m_scopeIndex], m_comment);
++            m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
++        }
++        if (advance() != ";") {
++            kdError() << "importJava: unexpected: " << m_source[m_srcIndex] << endl;
++            skipStmt();
++        }
++        return true;
++    }
++    if (keyword == "class" || keyword == "interface") {
++        const QString& name = advance();
++        const Uml::Object_Type t = (keyword == "class" ? Uml::ot_Class : Uml::ot_Interface);
++        UMLObject *ns = Import_Utils::createUMLObject(t, name, m_scope[m_scopeIndex], m_comment);
++        m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
++        m_klass->setAbstract(m_isAbstract);
++        m_klass->setStatic(m_isStatic);
++        m_isAbstract = m_isStatic = false;
++        if (advance() == ";")   // forward declaration
++            return true;
++        if (m_source[m_srcIndex] == "<") {
++            // template args - preliminary, rudimentary implementation
++            // @todo implement all template arg syntax
++            uint start = m_srcIndex;
++            if (! skipToClosing('<')) {
++                kdError() << "importJava(" << name << "): template syntax error" << endl;
++                return false;
++            }
++            while (1) {
++                const QString arg = m_source[++start];
++                if (! arg.contains( QRegExp("^[A-Za-z_]") )) {
++                    kdDebug() << "importJava(" << name << "): cannot handle template syntax ("
++                        << arg << ")" << endl;
++                    break;
++                }
++                /* UMLTemplate *tmpl = */ m_klass->addTemplate(arg);
++                const QString next = m_source[++start];
++                if (next == ">")
++                    break;
++                if (next != ",") {
++                    kdDebug() << "importJava(" << name << "): can't handle template syntax ("
++                        << next << ")" << endl;
++                    break;
++                }
++            }
++            advance();  // skip over ">"
++        }
++        if (m_source[m_srcIndex] == "extends") {
++            const QString& baseName = advance();
++            Import_Utils::createGeneralization(m_klass, baseName);
++            advance();
++        }
++        if (m_source[m_srcIndex] == "implements") {
++            while (m_srcIndex < srcLength - 1 && advance() != "{") {
++                const QString& baseName = m_source[m_srcIndex];
++                Import_Utils::createGeneralization(m_klass, baseName);
++                if (advance() != ",")
++                    break;
++            }
++        }
++        if (m_source[m_srcIndex] != "{") {
++            kdError() << "importJava: ignoring excess chars at " << name
++                << " (" << m_source[m_srcIndex] << ")" << endl;
++            skipStmt("{");
++        }
++        return true;
++    }
++    if (keyword == "enum") {
++        const QString& name = advance();
++        UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
++                        name, m_scope[m_scopeIndex], m_comment);
++        UMLEnum *enumType = static_cast<UMLEnum*>(ns);
++        advance();  // skip name
++        while (m_srcIndex < srcLength - 1 && advance() != "}") {
++            Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
++            if (advance() != ",")
++                break;
++        }
++        return true;
++    }
++    if (keyword == "static") {
++        m_isStatic = true;
++        return true;
++    }
++    if (keyword == "abstract") {
++        m_isAbstract = true;
++        return true;
++    }
++    if (keyword == "public") {
++        m_currentAccess = Uml::Visibility::Public;
++        return true;
++    }
++    if (keyword == "protected") {
++        m_currentAccess = Uml::Visibility::Protected;
++        return true;
++    }
++    if (keyword == "private") {
++        m_currentAccess = Uml::Visibility::Private;
++        return true;
++    }
++    if (keyword == "final" ||
++        keyword == "native" ||
++        keyword == "synchronized" ||
++        keyword == "transient" ||
++        keyword == "volatile") {
++        //@todo anything to do here?
++        return true;
++    }
++    if (keyword == "import") {
++        skipStmt();
++        return true;
++    }
++    if (keyword == "}") {
++        if (m_scopeIndex)
++            m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
++        else
++            kdError() << "importJava: too many }" << endl;
++        return true;
++    }
++    // At this point, we expect `keyword' to be a type name
++    // (of a member of class or interface, or return type
++    // of an operation.) Up next is the name of the attribute
++    // or operation.
++    if (! keyword.contains( QRegExp("^\\w") )) {
++        kdError() << "importJava: ignoring " << keyword << endl;
++        return false;
++    }
++    QString typeName = joinTypename();
++    QString name;
++    if (typeName == m_klass->getName()) {
++        // Constructor.
++        name = typeName;
++        typeName = QString::null;
++    } else {
++        name = advance();
++    }
++    if (name.contains( QRegExp("\\W") )) {
++        kdError() << "importJava: expecting name in " << name << endl;
++        return false;
++    }
++    // At this point we need a class.
++    if (m_klass == NULL) {
++        kdError() << "importJava: no class set for " << name << endl;
++        return false;
++    }
++    QString nextToken = advance();
++    if (nextToken == "(") {
++        // operation
++        UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
++        m_srcIndex++;
++        while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
++            QString typeName = joinTypename();
++            QString parName = advance();
++            UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName);
++            if (advance() != ",")
++                break;
++            m_srcIndex++;
++        }
++        Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, typeName,
++                                   m_isStatic, m_isAbstract, false /*isFriend*/,
++                                   false /*isConstructor*/, m_comment);
++        m_isAbstract = m_isStatic = false;
++        return skipToClosing('{');
++    }
++    // At this point we know it's some kind of attribute declaration.
++    while (1) {
++        while (nextToken != "," && nextToken != ";") {
++            name += nextToken;  // add possible array dimensions to `name'
++            nextToken = advance();
++        }
++        UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name, typeName, m_comment);
++        UMLAttribute *attr = static_cast<UMLAttribute*>(o);
++        if (nextToken != ",")
++            break;
++        name = advance();
++        nextToken = advance();
++    }
++    m_currentAccess = Uml::Visibility::Public;
++    if (m_source[m_srcIndex] != ";") {
++        kdError() << "importJava: ignoring trailing items at " << name << endl;
++        skipStmt();
++    }
++    return true;
++}
++
++
+--- umbrello/umbrello/umlnamespace.h	(revision 490305)
++++ umbrello/umbrello/umlnamespace.h	(revision 497528)
+@@ -244,6 +244,28 @@
+ enum Parameter_Direction { pd_In, pd_InOut, pd_Out };
+ 
+ /**
++ * Supported programming languages
++ */
++enum Programming_Language {
++    pl_ActionScript,
++    pl_Ada,
++    pl_Cpp,
++    // pl_Csharp,
++    pl_IDL,
++    pl_Java,
++    pl_JavaScript,
++    pl_Perl,
++    pl_PHP,
++    pl_PHP5,
++    pl_Python,
++    pl_Ruby,
++    pl_SQL,
++    pl_Tcl,
++    pl_XMLSchema,
++    pl_Reserved
++};
++
++/**
+  * The data type used for unique IDs.
+  */
+ typedef std::string IDType;
+--- umbrello/umbrello/refactoring/refactoringassistant.cpp	(revision 490305)
++++ umbrello/umbrello/refactoring/refactoringassistant.cpp	(revision 497528)
+@@ -20,6 +20,7 @@
+ #include "../dialogs/classpropdlg.h"
+ #include "../dialogs/umloperationdialog.h"
+ #include "../dialogs/umlattributedialog.h"
++#include "../object_factory.h"
+ 
+ #include <qpoint.h>
+ #include <qpopupmenu.h>
+@@ -344,7 +345,7 @@
+ 
+     //classes have classes and interfaces interfaces as super/derived classifiers
+     Uml::Object_Type t = obj->getBaseType();
+-    UMLClassifier *super = static_cast<UMLClassifier*>(m_doc->createUMLObject(t));
++    UMLClassifier *super = static_cast<UMLClassifier*>(Object_Factory::createUMLObject(t));
+     if(!super)
+         return;
+     m_doc->createUMLAssociation( obj, super, Uml::at_Generalization );
+@@ -385,7 +386,7 @@
+ 
+     //classes have classes and interfaces interfaces as super/derived classifiers
+     Uml::Object_Type t = obj->getBaseType();
+-    UMLClassifier *derived = static_cast<UMLClassifier*>(m_doc->createUMLObject(t));
++    UMLClassifier *derived = static_cast<UMLClassifier*>(Object_Factory::createUMLObject(t));
+     if(!derived)
+         return;
+     m_doc->createUMLAssociation( derived, obj, Uml::at_Generalization );
+@@ -417,7 +418,7 @@
+     //  UMLObject *obj = findUMLObject( item );
+     //  if( !dynamic_cast<UMLClassifier*>(obj) )
+     //          return;
+-    //  UMLObject *n = m_doc->createUMLObject( Uml::ot_Interface) );
++    //  UMLObject *n = Object_Factory::createUMLObject( Uml::ot_Interface) );
+     //  if(!n)
+     //          return;
+     //  m_doc->createUMLAssociation( n, obj, Uml::at_Realization );
+--- umbrello/umbrello/uml.cpp	(revision 490305)
++++ umbrello/umbrello/uml.cpp	(revision 497528)
+@@ -48,12 +48,9 @@
+ // app includes
+ #include "aligntoolbar.h"
+ #include "infowidget.h"
+-#include "cppimport.h"
+-#include "idlimport.h"
+-#include "adaimport.h"
++#include "classimport.h"
+ #include "docwindow.h"
+ #include "codegenerator.h"
+-#include "generatorinfo.h"
+ #include "codegenerationpolicy.h"
+ #include "codegenerators/codegenfactory.h"
+ #include "widget_utils.h"
+@@ -64,7 +61,7 @@
+ #ifdef HAVE_DOT
+ # include "autolayout/autolayoutdlg.h" //dimitri
+ #endif
+-
++#include "model_utils.h"
+ #include "clipboard/umlclipboard.h"
+ #include "dialogs/classwizard.h"
+ #include "dialogs/codegenerationwizard.h"
+@@ -85,13 +82,13 @@
+     m_pDocWindow = 0;
+     m_config = kapp->config();
+     m_listView = 0;
+-    m_generatorDict.setAutoDelete(true);
+     m_langSelect = NULL;
+     m_zoomSelect = NULL;
+     m_loading = false;
+     m_clipTimer = 0;
+     m_copyTimer = 0;
+     m_defaultcodegenerationpolicy = 0;
++    m_activeLanguage = Uml::pl_Reserved;
+     ///////////////////////////////////////////////////////////////////
+     // call inits to invoke all other construction parts
+     readOptionState();
+@@ -111,7 +108,7 @@
+     editUndo->setEnabled(false);
+     editRedo->setEnabled(false);
+ 
+-    //get a reference to the Code->Active Lanugage and to the Diagram->Zoom menu
++    //get a reference to the Code->Active Language and to the Diagram->Zoom menu
+     QPopupMenu* menu = findMenu( menuBar(), QString("code") );
+     m_langSelect = findMenu( menu, QString("active_lang_menu") );
+ 
+@@ -570,10 +567,8 @@
+         m_defaultcodegenerationpolicy->setDefaults(gen->getPolicy());
+ 
+     // write the config for each language-specific code gen policies
+-    GeneratorDictIt it( m_generatorDict );
+-    for(it.toFirst() ; it.current(); ++it )
+-    {
+-        CodeGenerator * gen = m_doc->findCodeGeneratorByLanguage(it.current()->language);
++    for (int i = 0; i < Uml::pl_Reserved; i++) {
++        CodeGenerator * gen = m_doc->findCodeGeneratorByLanguage((Uml::Programming_Language) i);
+         if (gen)
+             gen->getPolicy()->writeConfig(m_config);
+     }
+@@ -583,7 +578,7 @@
+ 
+     // next, we record the activeLanguage in the Code Generation Group
+     m_config->setGroup("Code Generation");
+-    m_config->writeEntry("activeLanguage", m_activeLanguage);
++    m_config->writeEntry("activeLanguage", Model_Utils::progLangToString(m_activeLanguage));
+ }
+ 
+ void UMLApp::readOptions() {
+@@ -1234,22 +1229,14 @@
+ }
+ 
+ CodeGenerator* UMLApp::createGenerator() {
+-    GeneratorInfo* info;
+     CodeGenerator* g = 0;
+ 
+-    if(m_activeLanguage.isEmpty()) {
++    if (m_activeLanguage == Uml::pl_Reserved) {
+         KMessageBox::sorry(this,i18n("There is no active language defined.\nPlease select "
+                                      "one of the installed languages to generate the code with."),
+                            i18n("No Language Selected"));
+         return 0;
+     }
+-    info = m_generatorDict.find(m_activeLanguage);
+-    if(!info) {
+-        KMessageBox::sorry(this,i18n("Could not find active language.\nPlease select "
+-                                     "one of the installed languages to generate the code with."),
+-                           i18n("No Language Selected"));
+-        return 0;
+-    }
+ 
+     // does the code generator for our activeLanguage already exist?
+     // then simply return that
+@@ -1259,8 +1246,7 @@
+     }
+ 
+     CodeGeneratorFactory codeGeneratorFactory;
+-    QString generatorName = codeGeneratorFactory.generatorName(m_activeLanguage);
+-    g = codeGeneratorFactory.createObject(getDocument(), generatorName.latin1());
++    g = codeGeneratorFactory.createObject(m_activeLanguage);
+     if (getDocument()->getCurrentCodeGenerator() == NULL)
+         getDocument()->setCurrentCodeGenerator(g);
+ 
+@@ -1273,7 +1259,8 @@
+     g->getPolicy()->setDefaults(m_defaultcodegenerationpolicy, false);
+ 
+     // configure it from XMI
+-    QDomElement elem = getDocument()->getCodeGeneratorXMIParams( g->getLanguage() );
++    QString language = Model_Utils::progLangToString( g->getLanguage() );
++    QDomElement elem = getDocument()->getCodeGeneratorXMIParams(language);
+     g->loadFromXMI(elem);
+ 
+     // add to our UML document
+@@ -1283,10 +1270,6 @@
+ 
+ }
+ 
+-GeneratorDict& UMLApp::generatorDict() {
+-    return m_generatorDict;
+-}
+-
+ void UMLApp::generateAllCode() {
+     CodeGenerator* gen = getGenerator();
+     if (gen) {
+@@ -1299,20 +1282,22 @@
+     wizard.exec();
+ }
+ 
+-void UMLApp::setActiveLanguage(int id) {
++void UMLApp::setActiveLanguage(int menuId) {
+ 
+     // only change the active language IF different from one we currently have
+-    if (!m_langSelect->isItemChecked(id))
++    if (!m_langSelect->isItemChecked(menuId))
+     {
+-
++        uint index = 0;
+         for(unsigned int i=0; i < m_langSelect->count(); i++) {
+-            m_langSelect->setItemChecked(m_langSelect->idAt(i),false);  //uncheck everything
++            int id = m_langSelect->idAt(i);
++            m_langSelect->setItemChecked(id, false);  //uncheck everything
++            if (id == menuId)
++                index = i;
+         }
+ 
++        m_langSelect->setItemChecked(menuId,true);
++        m_activeLanguage = (Uml::Programming_Language)index;
+ 
+-        m_langSelect->setItemChecked(id,true);
+-        m_activeLanguage = m_langSelect->text(id).remove('&');
+-
+         // update the generator
+         setGenerator(createGenerator());
+     }
+@@ -1333,23 +1318,24 @@
+         //uncheck everything except the active language
+         m_langSelect->setItemChecked(m_langSelect->idAt(i), isActiveLang);
+     }
+-    this->m_activeLanguage = activeLanguage;
++    this->m_activeLanguage = Model_Utils::stringToProgLang(activeLanguage);
+ 
+     setGenerator(createGenerator());
+ }
+ 
+-QString UMLApp::getActiveLanguage() const {
++Uml::Programming_Language UMLApp::getActiveLanguage() const {
+     return m_activeLanguage;
+ }
+ 
+ bool UMLApp::activeLanguageIsCaseSensitive() const {
+-    return (m_activeLanguage != "Ada");
++    return (m_activeLanguage != Uml::pl_Ada);
+ }
+ 
+ QString UMLApp::activeLanguageScopeSeparator() const {
+-    if (m_activeLanguage == "Ada" ||
+-        m_activeLanguage == "Java" ||
+-        m_activeLanguage == "JavaScript")  // CHECK: more?
++    if (m_activeLanguage == Uml::pl_Ada ||
++        m_activeLanguage == Uml::pl_Java ||
++        m_activeLanguage == Uml::pl_JavaScript ||
++        m_activeLanguage == Uml::pl_Python)  // CHECK: more?
+         return ".";
+     return "::";
+ }
+@@ -1418,9 +1404,13 @@
+     // because the user might decide to choose a language different from
+     // the m_activeLanguage (by using the "All Files" option).
+     QString preselectedExtension;
+-    if (m_activeLanguage == "IDL") {
++    if (m_activeLanguage == Uml::pl_IDL) {
+         preselectedExtension = i18n("*.idl|IDL Files (*.idl)");
+-    } else if (m_activeLanguage == "Ada") {
++    } else if (m_activeLanguage == Uml::pl_Python) {
++        preselectedExtension = i18n("*.py|Python Files (*.py)");
++    } else if (m_activeLanguage == Uml::pl_Java) {
++        preselectedExtension = i18n("*.java|Java Files (*.java)");
++    } else if (m_activeLanguage == Uml::pl_Ada) {
+         preselectedExtension = i18n("*.ads *.ada|Ada Files (*.ads *.ada)");
+     } else {
+         preselectedExtension = i18n("*.h *.hh *.hpp *.hxx *.H|Header Files (*.h *.hh *.hpp *.hxx *.H)");
+@@ -1428,14 +1418,8 @@
+     preselectedExtension.append("\n*|" + i18n("All Files"));
+     QStringList fileList = KFileDialog::getOpenFileNames(":import-classes", preselectedExtension,
+                            this, i18n("Select Code to Import") );
+-    ClassImport *classImporter = NULL;
+     const QString& firstFile = fileList.first();
+-    if (firstFile.endsWith(".idl"))
+-        classImporter = new IDLImport();
+-    else if (firstFile.contains( QRegExp("\\.ad[sba]$") ))
+-        classImporter = new AdaImport();
+-    else
+-        classImporter = new CppImport();  // the default.
++    ClassImport *classImporter = ClassImport::createImporterByFileExt(firstFile);
+     classImporter->importFiles(fileList);
+     delete classImporter;
+     m_doc->setLoading(false);
+@@ -1487,32 +1471,19 @@
+ 
+ void UMLApp::initGenerators() {
+     m_config->setGroup("Code Generation");
+-    m_activeLanguage = m_config->readEntry("activeLanguage", "Cpp");
+-
+-    CodeGeneratorFactory codeGeneratorFactory;
+-    QStringList languages = codeGeneratorFactory.languagesAvailable();
+-
+-    QStringList::Iterator end(languages.end());
+-    for ( QStringList::Iterator langit(languages.begin()); langit != end; ++langit ) {
+-        GeneratorInfo* info;
+-        info = new GeneratorInfo;
+-        info->language = *langit;  //language name
+-        info->object = codeGeneratorFactory.generatorName(*langit);
+-        m_generatorDict.insert(info->language,info);
+-    }
+-
++    QString activeLanguage = m_config->readEntry("activeLanguage", "C++");
++    m_activeLanguage = Model_Utils::stringToProgLang(activeLanguage);
+     updateLangSelectMenu();
+ }
+ 
+ void UMLApp::updateLangSelectMenu() {
+     m_langSelect->clear();
+     m_langSelect->setCheckable(true);
+-    int id;
+     bool foundActive = false;
+-    GeneratorDictIt it( m_generatorDict );
+-    for(it.toFirst() ; it.current(); ++it ) {
+-        id = m_langSelect->insertItem(it.current()->language,this,SLOT(setActiveLanguage(int)));
+-        if(m_activeLanguage == it.current()->language) {
++    for (int i = 0; i < Uml::pl_Reserved; i++) {
++        QString language = Model_Utils::progLangToString((Uml::Programming_Language) i);
++        int id = m_langSelect->insertItem(language,this,SLOT(setActiveLanguage(int)));
++        if (m_activeLanguage == i) {
+             m_langSelect->setItemChecked(id,true);
+             foundActive = true;
+         } else
+@@ -1521,20 +1492,22 @@
+ 
+     //if we could not find the active language, we try to fall back to C++
+     if(!foundActive) {
+-        for(uint index=0; index <m_langSelect->count(); index++)
+-            if ( m_langSelect->text(m_langSelect->idAt(index)) == "Cpp" ) {
++        for(uint index=0; index < m_langSelect->count(); index++)
++            if ( m_langSelect->text(m_langSelect->idAt(index)) == "C++" ) {
+                 m_langSelect->setItemChecked(m_langSelect->idAt(index),true);
+-                m_activeLanguage = m_langSelect->text(m_langSelect->idAt(index));
++                m_activeLanguage = Uml::pl_Cpp;
+                 break;
+             }
+     }
+     //last try... if we dont have an activeLanguage and we have no Cpp installed we just
+     //take the first language we find as "active"
+-    if(m_activeLanguage.isEmpty() && m_langSelect->count() > 0) {
+-        m_langSelect -> setItemChecked(m_langSelect->idAt(0),true);
+-        m_activeLanguage = m_langSelect -> text(m_langSelect->idAt(0));
++    if (m_activeLanguage == Uml::pl_Reserved && m_langSelect->count() > 0) {
++        int id = m_langSelect->idAt(0);
++        m_langSelect -> setItemChecked(id, true);
++        QString language = m_langSelect->text(id);
++        m_activeLanguage = Model_Utils::stringToProgLang(language);
++        kdDebug() << "UMLApp::updateLangSelectMenu: defaulting to " << language << endl;
+     }
+-
+ }
+ 
+ void UMLApp::tipOfTheDay()
+@@ -1621,17 +1594,11 @@
+ }
+ 
+ void UMLApp::initSavedCodeGenerators() {
+-    QString activeLang = m_activeLanguage;
+-    GeneratorDictIt it( m_generatorDict );
+-    for(it.toFirst() ; it.current(); ++it )
+-    {
+-        m_activeLanguage = it.current()->language;
+-        if( m_doc->hasCodeGeneratorXMIParams(m_activeLanguage))
++    for (int i = 0; i < Uml::pl_Reserved; i++) {
++        QString activeLang = Model_Utils::progLangToString((Uml::Programming_Language) i);
++        if (m_doc->hasCodeGeneratorXMIParams(activeLang))
+             createGenerator();
+     }
+-
+-    // now set back to old activeLanguage
+-    m_activeLanguage = activeLang;
+     setGenerator(createGenerator());
+ }
+ 
+--- umbrello/umbrello/enumwidget.cpp	(revision 490305)
++++ umbrello/umbrello/enumwidget.cpp	(revision 497528)
+@@ -22,6 +22,7 @@
+ #include "umldoc.h"
+ #include "uml.h"
+ #include "listpopupmenu.h"
++#include "model_utils.h"
+ 
+ #include <kdebug.h>
+ #include <qpainter.h>
+@@ -170,7 +171,7 @@
+ void EnumWidget::slotMenuSelection(int sel) {
+     switch(sel) {
+     case ListPopupMenu::mt_EnumLiteral:
+-        if ( UMLApp::app()->getDocument()->createChildObject(m_pObject, Uml::ot_EnumLiteral) )  {
++        if (Model_Utils::createChildObject(m_pObject, Uml::ot_EnumLiteral) )  {
+             UMLApp::app()->getDocument()->setModified();
+         }
+         break;
+--- umbrello/umbrello/pythonimport.cpp	(revision 0)
++++ umbrello/umbrello/pythonimport.cpp	(revision 497528)
+@@ -0,0 +1,250 @@
++/***************************************************************************
++ *                                                                         *
++ *   This program is free software; you can redistribute it and/or modify  *
++ *   it under the terms of the GNU General Public License as published by  *
++ *   the Free Software Foundation; either version 2 of the License, or     *
++ *   (at your option) any later version.                                   *
++ *                                                                         *
++ *  copyright (C) 2006                                                     *
++ *  Umbrello UML Modeller Authors <uml-devel@ uml.sf.net>                  *
++ ***************************************************************************/
++
++// own header
++#include "pythonimport.h"
++
++// qt/kde includes
++#include <qstringlist.h>
++#include <qregexp.h>
++#include <kdebug.h>
++// app includes
++#include "import_utils.h"
++#include "uml.h"
++#include "umldoc.h"
++#include "umlpackagelist.h"
++#include "package.h"
++#include "classifier.h"
++#include "enum.h"
++#include "operation.h"
++#include "attribute.h"
++
++PythonImport::PythonImport() : NativeImportBase("#") {
++    initVars();
++}
++
++PythonImport::~PythonImport() {
++}
++
++void PythonImport::initVars() {
++    m_srcIndentIndex = 0;
++    m_srcIndent[m_srcIndentIndex] = 0;
++    m_braceWasOpened = false;
++}
++
++bool PythonImport::preprocess(QString& line) {
++    // Check for end of multi line comment.
++    if (m_inComment) {
++        int pos = line.find("\"\"\"");
++        if (pos == -1) {
++            m_comment += line + "\n";
++            return true;  // done
++        }
++        if (pos > 0) {
++            QString text = line.mid(0, pos - 1);
++            m_comment += text.stripWhiteSpace();
++        }
++        m_source.append(m_singleLineCommentIntro + m_comment);  // denotes comments in `m_source'
++        m_comment = "";
++        m_inComment = false;
++        pos += 3;  // pos now points behind the closed comment
++        if (pos == (int)line.length())
++            return true;  // done
++        line = line.mid(pos);
++    }
++    // If we get here then m_inComment is false.
++    // Check for start of multi line comment.
++    int pos = line.find("\"\"\"");
++    if (pos != -1) {
++        int endpos = line.find("\"\"\"", pos + 3);
++        if (endpos == -1) {
++            m_inComment = true;
++            if (pos + 3 < (int)line.length()) {
++                QString cmnt = line.mid(pos + 3);
++                m_comment += cmnt.stripWhiteSpace() + "\n";
++            }
++            if (pos == 0)
++                return true;  // done
++            line = line.left(pos);
++        } else {   // It's a multiline comment on a single line.
++            if (endpos > pos + 3)  {
++                QString cmnt = line.mid(pos + 3, endpos - pos - 3);
++                cmnt = cmnt.stripWhiteSpace();
++                if (!cmnt.isEmpty())
++                    m_source.append(m_singleLineCommentIntro + cmnt);
++            }
++            endpos += 3;  // endpos now points behind the closed comment
++            QString pre;
++            if (pos > 0)
++                pre = line.left(pos);
++            QString post;
++            if (endpos < (int)line.length())
++                post = line.mid(endpos);
++            line = pre + post;
++        }
++        if (line.contains( QRegExp("^\\s*$") ))
++            return true;
++    }
++    // Handle single line comment
++    pos = line.find(m_singleLineCommentIntro);
++    if (pos != -1) {
++        QString cmnt = line.mid(pos);
++        m_source.append(cmnt);
++        if (pos == 0)
++            return true;
++        line = line.left(pos);
++        line.remove( QRegExp("\\s+$") );
++    }
++    // Transform changes in indentation into braces a la C++/Java/Perl/...
++    pos = line.find( QRegExp("\\S") );
++    if (pos == -1)
++        return true;
++    bool isContinuation = false;
++    int leadingWhite = line.left(pos).contains( QRegExp("\\s") );
++    if (leadingWhite > m_srcIndent[m_srcIndentIndex]) {
++        if (m_srcIndex == 0) {
++            kdError() << "PythonImport::preprocess(): internal error 1" << endl;
++            return true;
++        }
++        if (m_braceWasOpened) {
++            m_srcIndent[++m_srcIndentIndex] = leadingWhite;
++            m_braceWasOpened = false;
++        } else {
++            isContinuation = true;
++        }
++    } else {
++        while (m_srcIndentIndex > 0 && leadingWhite < m_srcIndent[m_srcIndentIndex]) {
++            m_srcIndentIndex--;
++            m_source.append("}");
++            m_srcIndex++;
++        }
++    }
++    if (line.endsWith(":")) {
++        line.replace( QRegExp(":$"), "{" );
++        m_braceWasOpened = true;
++    } else {
++        m_braceWasOpened = false;
++    }
++    if (!isContinuation && !m_braceWasOpened)
++        line += ';';
++    return false;  // The input was not completely consumed by preprocessing.
++}
++
++void PythonImport::fillSource(QString word) {
++    QString lexeme;
++    const uint len = word.length();
++    QChar stringIntro = 0;  // buffers the string introducer character
++    for (uint i = 0; i < len; i++) {
++        const QChar& c = word[i];
++        if (stringIntro) {        // we are in a string
++            lexeme += c;
++            if (c == stringIntro) {
++                if (word[i - 1] != '\\') {
++                    m_source.append(lexeme);
++                    m_srcIndex++;
++                    lexeme = QString::null;
++                }
++                stringIntro = 0;  // we are no longer in a string
++            }
++        } else if (c == '"' || c == '\'') {
++            if (!lexeme.isEmpty()) {
++                m_source.append(lexeme);
++                m_srcIndex++;
++            }
++            lexeme = stringIntro = c;
++        } else if (c.isLetterOrNumber() || c == '_' || c == '.') {
++            lexeme += c;
++        } else {
++            if (!lexeme.isEmpty()) {
++                m_source.append(lexeme);
++                m_srcIndex++;
++                lexeme = QString::null;
++            }
++            m_source.append(QString(c));
++            m_srcIndex++;
++        }
++    }
++    if (!lexeme.isEmpty()) {
++        m_source.append(lexeme);
++        m_srcIndex++;
++    }
++}
++
++void PythonImport::skipBody() {
++    if (m_source[m_srcIndex] != "{")
++        skipStmt("{");
++    int braceNesting = 0;
++    QString token;
++    while ((token = advance()) != QString::null) {
++        if (token == "}") {
++            if (braceNesting <= 0)
++                break;
++            braceNesting--;
++        } else if (token == "{") {
++            braceNesting++;
++        }
++    }
++}
++
++bool PythonImport::parseStmt() {
++    const uint srcLength = m_source.count();
++    const QString& keyword = m_source[m_srcIndex];
++    if (keyword == "class") {
++        const QString& name = advance();
++        UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
++                        name, m_scope[m_scopeIndex], m_comment);
++        m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
++        m_comment = QString::null;
++        if (advance() == "(") {
++            while (m_srcIndex < srcLength - 1 && advance() != ")") {
++                const QString& baseName = m_source[m_srcIndex];
++                Import_Utils::createGeneralization(m_klass, baseName);
++                if (advance() != ",")
++                    break;
++            }
++        }
++        if (m_source[m_srcIndex] != "{") {
++            skipStmt("{");
++        }
++        return true;
++    }
++    if (keyword == "def") {
++        const QString& name = advance();
++        // operation
++        UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
++        if (advance() != "(") {
++            kdError() << "importPython def " << name << ": expecting \"(\"" << endl;
++            skipBody();
++            return true;
++        }
++        while (m_srcIndex < srcLength && advance() != ")") {
++            const QString& parName = m_source[m_srcIndex];
++            UMLAttribute *att = Import_Utils::addMethodParameter(op, "string", parName);
++            if (advance() != ",")
++                break;
++        }
++        Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, "string",
++                                   false /*isStatic*/, false /*isAbstract*/, false /*isFriend*/,
++                                   false /*isConstructor*/, m_comment);
++        skipBody();
++        return true;
++    }
++    if (keyword == "}") {
++        if (m_scopeIndex)
++            m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
++        else
++            kdError() << "importPython: too many }" << endl;
++        return true;
++    }
++    return false;  // @todo parsing of attributes
++}
++
++
+--- umbrello/umbrello/umlwidget.h	(revision 490305)
++++ umbrello/umbrello/umlwidget.h	(revision 497528)
+@@ -418,10 +418,13 @@
+      */
+     virtual void setShowStereotype(bool _status);
+ 
+-    virtual void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
++    /**
++     * Show a properties dialog for a UMLWidget.
++     *
++     * @return  True if the widget was modified.
++     */
++    bool showProperties();
+ 
+-    virtual bool loadFromXMI( QDomElement & qElement );
+-
+     /**
+      * Returns true if the Activate method has been called for this instance
+      *
+@@ -514,6 +517,10 @@
+      */
+     virtual void moveEvent(QMoveEvent *) { }
+ 
++    virtual void saveToXMI( QDomDocument & qDoc, QDomElement & qElement );
++
++    virtual bool loadFromXMI( QDomElement & qElement );
++
+ protected:
+     /**
+      * Apply possible constraints to the given candidate width and height.
+@@ -533,7 +540,7 @@
+      * @param offsetX The x-coordinate for drawing.
+      * @param offsetY The y-coordinate for drawing.
+      */
+-    virtual void drawSelected(QPainter * p, int offsetX, int offsetY, bool resizeable = true);
++    virtual void drawSelected(QPainter * p, int offsetX, int offsetY);
+ 
+     /**
+      * Overrides default method.
+@@ -654,7 +661,7 @@
+     int            m_nOldX, m_nOldY, m_nPosX, m_origZ;
+     ListPopupMenu *m_pMenu;
+     UMLDoc        *m_pDoc;  ///< shortcut for UMLApp::app()->getDocument()
+-    bool           m_bResizing;
++    bool           m_bResizable, m_bResizing;
+     int            m_nPressOffsetX, m_nPressOffsetY;
+     int            m_nOldH, m_nOldW;
+     QFontMetrics  *m_pFontMetrics[FT_INVALID];
+--- umbrello/umbrello/idlimport.h	(revision 490305)
++++ umbrello/umbrello/idlimport.h	(revision 497528)
+@@ -27,6 +27,12 @@
+     /**
+      * Implement abstract operation from NativeImportBase.
+      */
++    bool parseStmt();
++
++    /**
++     * Reimplement operation from NativeImportBase.
++     * Need to do this because we use the external C preprocessor.
++     */
+     void parseFile(QString file);
+ 
+     /**
+--- umbrello/umbrello/codegenerator.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerator.cpp	(revision 497528)
+@@ -41,27 +41,28 @@
+ #include "classifiercodedocument.h"
+ #include "codedocument.h"
+ #include "operation.h"
++#include "uml.h"
+ #include "umldoc.h"
+ #include "umlobject.h"
+ #include "umlview.h"
+ #include "umlattributelist.h"
+ #include "umloperationlist.h"
++#include "model_utils.h"
+ 
+-
+ // Constructors/Destructors
+ //
+ 
+-CodeGenerator::CodeGenerator ( UMLDoc * doc , const char *name )
+-        : QObject ( (QObject*) doc, name )
++CodeGenerator::CodeGenerator ()
++        : QObject (UMLApp::app()->getDocument())
+ {
+-    initFields( doc);
++    initFields(UMLApp::app()->getDocument());
+ }
+ 
+ // FIX
+ // hmm. this should be pure virtual so that implemented in sub-class
+-CodeGenerator::CodeGenerator ( UMLDoc * doc,  const char *name, QDomElement & element )
+-        : QObject ( (QObject *)doc, name) {
+-    initFields( doc);
++CodeGenerator::CodeGenerator (QDomElement & element )
++        : QObject (UMLApp::app()->getDocument()) {
++    initFields(UMLApp::app()->getDocument());
+     loadFromXMI(element); // hmm. cant call this here.. its 'pure' virtual
+ }
+ 
+@@ -212,39 +213,38 @@
+     //now look for our particular child element
+     QDomNode node = qElement.firstChild();
+     QDomElement element = node.toElement();
+-    QString langType = getLanguage();
++    QString langType = Model_Utils::progLangToString( getLanguage() );
+ 
+-    if( qElement.tagName() == "codegenerator"
+-            && qElement.attribute( "language", "UNKNOWN" ) == langType )
+-    {
+-        // got our code generator element, now load
+-        // codedocuments
+-        QDomNode codeDocNode = qElement.firstChild();
+-        QDomElement codeDocElement = codeDocNode.toElement();
+-        while( !codeDocElement.isNull() ) {
++    if (qElement.tagName() != "codegenerator"
++            || qElement.attribute("language", "UNKNOWN") != langType)
++        return;
++    // got our code generator element, now load
++    // codedocuments
++    QDomNode codeDocNode = qElement.firstChild();
++    QDomElement codeDocElement = codeDocNode.toElement();
++    while( !codeDocElement.isNull() ) {
+ 
+-            QString docTag = codeDocElement.tagName();
+-            if( docTag == "codedocument" ||
+-                    docTag == "classifiercodedocument"
+-              ) {
+-                QString id = codeDocElement.attribute( "id", "-1" );
+-                CodeDocument * codeDoc = findCodeDocumentByID(id);
+-                if(codeDoc)
+-                    codeDoc->loadFromXMI(codeDocElement);
+-                else {
+-                    kdWarning()<<" loadFromXMI: missing code document w/ id:"<<id<<", plowing ahead with pre-generated one."<<endl;
+-                }
+-            } else
+-                kdWarning()<<" loadFromXMI : got strange codegenerator child node:"<<docTag<<", ignoring."<<endl;
++        QString docTag = codeDocElement.tagName();
++        if( docTag == "codedocument" ||
++                docTag == "classifiercodedocument"
++          ) {
++            QString id = codeDocElement.attribute( "id", "-1" );
++            CodeDocument * codeDoc = findCodeDocumentByID(id);
++            if(codeDoc)
++                codeDoc->loadFromXMI(codeDocElement);
++            else {
++                kdWarning()<<" loadFromXMI: missing code document w/ id:"<<id<<", plowing ahead with pre-generated one."<<endl;
++            }
++        } else
++            kdWarning()<<" loadFromXMI : got strange codegenerator child node:"<<docTag<<", ignoring."<<endl;
+ 
+-            codeDocNode = codeDocElement.nextSibling();
+-            codeDocElement = codeDocNode.toElement();
+-        }
++        codeDocNode = codeDocElement.nextSibling();
++        codeDocElement = codeDocNode.toElement();
+     }
+ }
+ 
+ void CodeGenerator::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+-    QString langType = getLanguage();
++    QString langType = Model_Utils::progLangToString( getLanguage() );
+     QDomElement docElement = doc.createElement( "codegenerator" );
+     docElement.setAttribute("language",langType);
+ 
+@@ -780,9 +780,9 @@
+     return m_codegeneratorpolicy->getCodeVerboseSectionComments();
+ }
+ 
+-void CodeGenerator::createDefaultDatatypes()  {
++QStringList CodeGenerator::defaultDatatypes()  {
++    return QStringList();
+     //empty by default, override in your code generator
+-    //e.g.  m_document->createDatatype("int");
+ }
+ 
+ bool CodeGenerator::isReservedKeyword(const QString & keyword) {
+--- umbrello/umbrello/umlobject.cpp	(revision 490305)
++++ umbrello/umbrello/umlobject.cpp	(revision 497528)
+@@ -22,8 +22,11 @@
+ #include "umllistviewitem.h"
+ #include "package.h"
+ #include "stereotype.h"
++#include "object_factory.h"
+ #include "model_utils.h"
+ #include "import_utils.h"
++#include "docwindow.h"
++#include "dialogs/classpropdlg.h"
+ 
+ UMLObject::UMLObject(const UMLObject * parent, const QString &name, Uml::IDType id)
+         : QObject(const_cast<UMLObject*>(parent), "UMLObject" ) {
+@@ -68,6 +71,19 @@
+     m_pSecondary = NULL;
+ }
+ 
++bool UMLObject::showProperties(int page, bool assoc) {
++    DocWindow *docwindow = UMLApp::app()->getDocWindow();
++    docwindow->updateDocumentation(false);
++    ClassPropDlg* dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this, page, assoc);
++    bool modified = false;
++    if (dlg->exec()) {
++        docwindow->showDocumentation(this, true);
++        UMLApp::app()->getDocument()->setModified(true);
++        modified = true;
++    }
++    dlg->close(true); //wipe from memory
++    return modified;
++}
+ 
+ bool UMLObject::isSavedInSeparateFile() {
+     if (UMLApp::app()->getOptionState().generalState.tabdiagrams) {
+@@ -197,7 +213,7 @@
+     rhs->m_pUMLPackage = m_pUMLPackage;
+ 
+     // We don't want the same name existing twice.
+-    rhs->m_Name = umldoc->uniqObjectName(m_BaseType, m_Name, m_pUMLPackage);
++    rhs->m_Name = Model_Utils::uniqObjectName(m_BaseType, m_Name, m_pUMLPackage);
+ 
+     // Create a new ID.
+     rhs->m_nId = umldoc->getUniqueID();
+@@ -407,10 +423,10 @@
+         return true;
+     }
+     //pDoc->setIsOldFile(true);
+-    // Work around UMLDoc::createUMLObject()'s incapability
++    // Work around Object_Factory::createUMLObject()'s incapability
+     // of on-the-fly scope creation:
+     if (m_SecondaryId.contains("::")) {
+-        // TODO: Merge Import_Utils::createUMLObject() into UMLDoc::createUMLObject()
++        // TODO: Merge Import_Utils::createUMLObject() into Object_Factory::createUMLObject()
+         m_pSecondary = Import_Utils::createUMLObject(Uml::ot_UMLObject, m_SecondaryId, NULL);
+         if (m_pSecondary) {
+             if (Import_Utils::newUMLObjectWasCreated()) {
+@@ -443,7 +459,7 @@
+         if (Model_Utils::isCommonDataType(m_SecondaryId))
+             ot = Uml::ot_Datatype;
+     }
+-    m_pSecondary = pDoc->createUMLObject(ot, m_SecondaryId, NULL);
++    m_pSecondary = Object_Factory::createUMLObject(ot, m_SecondaryId, NULL);
+     if (m_pSecondary == NULL)
+         return false;
+     m_SecondaryId = "";
+--- umbrello/umbrello/model_utils.h	(revision 490305)
++++ umbrello/umbrello/model_utils.h	(revision 497528)
+@@ -30,6 +30,7 @@
+ 
+ // forward declarations
+ class UMLClassifier;
++class UMLPackage;
+ 
+ namespace Model_Utils {
+ 
+@@ -72,6 +73,31 @@
+                           UMLObject *currentObj = NULL);
+ 
+ /**
++ * Returns a name for the new object, appended with a number
++ * if the default name is taken e.g. new_actor, new_actor_1
++ * etc.
++ * @param type              The object type.
++ * @param prefix    The prefix to use (optional.)
++ *                  If no prefix is given then a type related
++ *                  prefix will be chosen internally.
++ * @param parentPkg The package in which to compare the name (optional.)
++ *                  If not given then comparisons are done in the global scope.
++ */
++QString uniqObjectName(Uml::Object_Type type,
++                       QString prefix = QString::null,
++                       UMLPackage *parentPkg = 0);
++
++/**
++ * Creates an operation, attribute, template, or enum literal
++ * for the parent concept.
++ *
++ * @param o The parent concept
++ * @param type      The type to create
++ * @return  The UMLObject created
++ */
++UMLObject* createChildObject(UMLObject* o, Uml::Object_Type type);
++
++/**
+  * Return true if the given tag is a one of the common XMI
+  * attributes, such as:
+  * "name" | "visibility" | "isRoot" | "isLeaf" | "isAbstract" |
+@@ -98,6 +124,16 @@
+ int stringToDirection(QString input, Uml::Parameter_Direction & result);
+ 
+ /**
++ * Return string corresponding to the given Uml::Programming_Language.
++ */
++QString progLangToString(Uml::Programming_Language pl);
++
++/**
++ * Return Uml::Programming_Language corresponding to the given string.
++ */
++Uml::Programming_Language stringToProgLang(QString str);
++
++/**
+  * Return type of parseOperation()
+  */
+ enum Parse_Status {
+--- umbrello/umbrello/umldoc.h	(revision 490305)
++++ umbrello/umbrello/umldoc.h	(revision 497528)
+@@ -204,31 +204,6 @@
+     bool isUnique(const QString &name, UMLPackage *package);
+ 
+     /**
+-     * Creates a @ref UMLObject of the given type.
+-     *
+-     * @param type              The type of @ref UMLObject to create.
+-     *                  Used to create Actors, Use Cases and concepts.
+-     * @param n         A name to give to the object (optional.)
+-     * @param parentPkg The object's parent package (optional.)
+-     * @param prepend   Set true if it is desired to prepend the new
+-     *                  object to the list of objects.
+-     *                  The default is to append.
+-     */
+-    UMLObject* createUMLObject(Uml::Object_Type type,
+-                               const QString &n = QString::null,
+-                               UMLPackage *parentPkg = NULL,
+-                               bool prepend = false);
+-
+-    /**
+-     * Creates either an operation or attribute for the parent concept.
+-     *
+-     * @param o The parent concept
+-     * @param type      The type to create, either an operation or attribute.
+-     * @return  The UMLObject created
+-     */
+-    UMLObject* createChildObject(UMLObject* o, Uml::Object_Type type);
+-
+-    /**
+      * Finds or creates a stereotype for the parent object.
+      */
+     UMLStereotype* findOrCreateStereotype(const QString &name);
+@@ -312,16 +287,6 @@
+     void renameDiagram(Uml::IDType id);
+ 
+     /**
+-     * Returns a list of the predefined programming-language types
+-     * supported.
+-     *
+-     * @return  A string list of the programming language types.
+-     */
+-    QStringList getModelTypes();
+-    // FIXME: Investigate how to make this language dependent.
+-    //        Currently only a fixed set of default types is supported.
+-
+-    /**
+      * Used to rename a @ref UMLObject.  The @ref UMLObject is to be an
+      * actor, use case or concept.
+      *
+@@ -445,18 +410,6 @@
+     Uml::IDType getUniqueID();
+ 
+     /**
+-     * This method is called if you wish to see the properties of a
+-     * @ref UMLObject.  A dialog box will be displayed from which you
+-     * can change the object's properties.
+-     *
+-     * @param o         The object to show properties for.
+-     * @param page              The page to show.
+-     * @param assoc             Whether to show association page.
+-     * @return          True if we modified the object.
+-     */
+-    bool showProperties(UMLObject *o, int page = 0, bool assoc = false);
+-
+-    /**
+      * This method is called for saving the given model as a XMI file.
+      * It is virtual and calls the corresponding saveToXMI() functions
+      * of the derived classes.
+@@ -532,17 +485,6 @@
+     bool loadDiagramsFromXMI( QDomNode & node );
+ 
+     /**
+-     * Creates a new Classifier UMLObject (attribute, operation, template).
+-     * Used by the clipboard when pasteing them.
+-     */
+-    static UMLObject* makeNewClassifierObject(QString type, UMLClassifier *parent);
+-
+-    /**
+-     * Make a new UMLObject, used by loadFromXMI and clipboard paste.
+-     */
+-    static UMLObject* makeNewUMLObject(const QString &type);
+-
+-    /**
+      * Signal a view/diagram has been renamed.
+      */
+     void signalDiagramRenamed(UMLView * pView );
+@@ -560,22 +502,6 @@
+     void signalUMLObjectCreated(UMLObject * o);
+ 
+     /**
+-     * Show a properties dialog for an @ref ObjectWidget.
+-     *
+-     * @param o The ObjectWidget to represent.
+-     * @return  True if we modified the object.
+-     */
+-    bool showProperties(ObjectWidget * o);
+-
+-    /**
+-     * Show a properties dialog for an @ref UMLWidget.
+-     *
+-     * @param o The UMLWidget to represent.
+-     * @return  True if we modified the object.
+-     */
+-    bool showProperties(UMLWidget * o);
+-
+-    /**
+      * Returns the current view.
+      *
+      * @return  Pointer to the current UMLView.
+@@ -665,9 +591,11 @@
+      * any ids or signal.  Use AddUMLObjectPaste if pasting.
+      *
+      * @param object   The object to add.
++     * @param prepend  True if wish to prepend the object to the object list
++     *                 (default: append)
+      * @return  True if the object was actually added.
+      */
+-    bool addUMLObject(UMLObject * object);
++    bool addUMLObject(UMLObject * object, bool prepend = false);
+ 
+     /**
+      * Adds an already created UMLView to the document, it gets
+@@ -810,7 +738,7 @@
+     /**
+      * Find a code generator by the given language.
+      */
+-    CodeGenerator * findCodeGeneratorByLanguage (const QString &lang);
++    CodeGenerator * findCodeGeneratorByLanguage (Uml::Programming_Language lang);
+ 
+     /**
+      * Add a CodeGenerator object to this UMLDoc
+@@ -871,20 +799,6 @@
+     const UMLStereotypeList& getStereotypes();
+ 
+     /**
+-     * Returns a name for the new object, appended with a number
+-     * if the default name is taken e.g. new_actor, new_actor_1
+-     * etc.
+-     * @param type              The object type.
+-     * @param prefix    The prefix to use (optional.)
+-     *                  If no prefix is given then a type related
+-     *                  prefix will be chosen internally.
+-     * @param parentPkg The package in which to compare the name (optional.)
+-     *                  If not given then comparisons are done in the global scope.
+-     */
+-    QString uniqObjectName(const Uml::Object_Type type, QString prefix = QString::null,
+-                           UMLPackage *parentPkg = 0);
+-
+-    /**
+      * Write text to the status bar.
+      */
+     void writeToStatusBar(const QString &text);
+@@ -942,8 +856,6 @@
+     bool m_modified;
+     KURL m_doc_url;
+     UMLView* m_currentView;
+-    /// Auxiliary variable for loading foreign XMI files
+-    int m_highestIDforForeignFile;
+ 
+     /**
+      * A dictionary of the parameters in the save XMI file
+@@ -955,7 +867,9 @@
+      * A dictionary of various code generators we currently have
+      * configured for this UML document.
+      */
+-    QDict<CodeGenerator> m_codeGeneratorDictionary;
++    typedef QPtrList<CodeGenerator> CodeGeneratorList;
++    typedef QPtrListIterator<CodeGenerator> CodeGeneratorListIt;
++    CodeGeneratorList m_codeGenerators;
+ 
+     /**
+      * Contains all the UMLObject id changes of paste session.
+--- umbrello/umbrello/idlimport.cpp	(revision 490305)
++++ umbrello/umbrello/idlimport.cpp	(revision 497528)
+@@ -122,238 +122,234 @@
+         const QString& keyword = m_source[m_srcIndex];
+         //kdDebug() << '"' << keyword << '"' << endl;
+         if (keyword.startsWith(m_singleLineCommentIntro)) {
+-            m_comment = keyword.mid(2);
++            m_comment = keyword.mid(m_singleLineCommentIntro.length());
+             continue;
+         }
+-        if (keyword == "module") {
+-            const QString& name = advance();
+-            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
+-                            name, m_scope[m_scopeIndex], m_comment);
+-            m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+-            m_scope[m_scopeIndex]->setStereotype("CORBAModule");
+-            if (advance() != "{") {
+-                kdError() << "importIDL: unexpected: " << m_source[m_srcIndex] << endl;
+-                skipStmt("{");
+-            }
+-            m_comment = QString::null;
+-            continue;
++        if (! parseStmt())
++            skipStmt();
++        m_currentAccess = Uml::Visibility::Public;
++        m_comment = QString::null;
++    }
++    pclose(fp);
++}
++
++bool IDLImport::parseStmt() {
++    const QString& keyword = m_source[m_srcIndex];
++    const uint srcLength = m_source.count();
++    if (keyword == "module") {
++        const QString& name = advance();
++        UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
++                        name, m_scope[m_scopeIndex], m_comment);
++        m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
++        m_scope[m_scopeIndex]->setStereotype("CORBAModule");
++        if (advance() != "{") {
++            kdError() << "importIDL: unexpected: " << m_source[m_srcIndex] << endl;
++            skipStmt("{");
+         }
+-        if (keyword == "interface") {
+-            const QString& name = advance();
+-            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+-                            name, m_scope[m_scopeIndex], m_comment);
+-            m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+-            m_klass->setStereotype("CORBAInterface");
+-            m_klass->setAbstract(m_isAbstract);
+-            m_isAbstract = false;
+-            m_comment = QString::null;
+-            if (advance() == ";")   // forward declaration
+-                continue;
+-            if (m_source[m_srcIndex] == ":") {
+-                while (++m_srcIndex < srcLength && m_source[m_srcIndex] != "{") {
+-                    const QString& baseName = m_source[m_srcIndex];
+-                    Import_Utils::createGeneralization(m_klass, baseName);
+-                    if (advance() != ",")
+-                        break;
+-                }
+-            }
+-            if (m_source[m_srcIndex] != "{") {
+-                kdError() << "importIDL: ignoring excess chars at "
+-                << name << endl;
+-                skipStmt("{");
+-            }
+-            continue;
+-        }
+-        if (keyword == "struct" || keyword == "exception") {
+-            const QString& name = advance();
+-            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+-                            name, m_scope[m_scopeIndex], m_comment);
+-            m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+-            if (keyword == "struct")
+-                m_klass->setStereotype("CORBAStruct");
+-            else
+-                m_klass->setStereotype("CORBAException");
+-            if (advance() != "{") {
+-                kdError() << "importIDL: expecting '{' at " << name << endl;
+-                skipStmt("{");
+-            }
+-            m_comment = QString::null;
+-            continue;
+-        }
+-        if (keyword == "union") {
+-            // TBD. <gulp>
+-            skipStmt("}");
+-            m_srcIndex++;  // advance to ';'
+-            continue;
+-        }
+-        if (keyword == "enum") {
+-            const QString& name = advance();
+-            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+-                            name, m_scope[m_scopeIndex], m_comment);
+-            UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+-            m_srcIndex++;  // skip name
+-            while (++m_srcIndex < srcLength && m_source[m_srcIndex] != "}") {
+-                Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
++        return true;
++    }
++    if (keyword == "interface") {
++        const QString& name = advance();
++        UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
++                        name, m_scope[m_scopeIndex], m_comment);
++        m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
++        m_klass->setStereotype("CORBAInterface");
++        m_klass->setAbstract(m_isAbstract);
++        m_isAbstract = false;
++        m_comment = QString::null;
++        if (advance() == ";")   // forward declaration
++            return true;
++        if (m_source[m_srcIndex] == ":") {
++            while (++m_srcIndex < srcLength && m_source[m_srcIndex] != "{") {
++                const QString& baseName = m_source[m_srcIndex];
++                Import_Utils::createGeneralization(m_klass, baseName);
+                 if (advance() != ",")
+                     break;
+             }
+-            skipStmt();
+-            m_comment = QString::null;
+-            continue;
+         }
+-        if (keyword == "typedef") {
+-            const QString& existingType = advance();
+-            const QString& newType = advance();
+-            Import_Utils::createUMLObject(Uml::ot_Class, newType, m_scope[m_scopeIndex],
+-                                         m_comment, "CORBATypedef" /* stereotype */);
+-            // @todo How do we convey the existingType ?
+-            skipStmt();
+-            continue;
++        if (m_source[m_srcIndex] != "{") {
++            kdError() << "importIDL: ignoring excess chars at "
++            << name << endl;
++            skipStmt("{");
+         }
+-        if (keyword == "const") {
+-            skipStmt();
+-            continue;
++        return true;
++    }
++    if (keyword == "struct" || keyword == "exception") {
++        const QString& name = advance();
++        UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
++                        name, m_scope[m_scopeIndex], m_comment);
++        m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
++        if (keyword == "struct")
++            m_klass->setStereotype("CORBAStruct");
++        else
++            m_klass->setStereotype("CORBAException");
++        if (advance() != "{") {
++            kdError() << "importIDL: expecting '{' at " << name << endl;
++            skipStmt("{");
+         }
+-        if (keyword == "custom") {
+-            continue;
++        return true;
++    }
++    if (keyword == "union") {
++        // TBD. <gulp>
++        skipStmt("}");
++        m_srcIndex++;  // advance to ';'
++        return true;
++    }
++    if (keyword == "enum") {
++        const QString& name = advance();
++        UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
++                        name, m_scope[m_scopeIndex], m_comment);
++        UMLEnum *enumType = static_cast<UMLEnum*>(ns);
++        m_srcIndex++;  // skip name
++        while (++m_srcIndex < srcLength && m_source[m_srcIndex] != "}") {
++            Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
++            if (advance() != ",")
++                break;
+         }
+-        if (keyword == "abstract") {
+-            m_isAbstract = true;
+-            continue;
+-        }
+-        if (keyword == "valuetype") {
+-            const QString& name = advance();
+-            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+-                            name, m_scope[m_scopeIndex], m_comment);
+-            m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+-            m_klass->setAbstract(m_isAbstract);
+-            m_isAbstract = false;
+-            if (advance() == ";")   // forward declaration
+-                continue;
+-            if (m_source[m_srcIndex] == ":") {
+-                if (advance() == "truncatable")
+-                    m_srcIndex++;
+-                while (m_srcIndex < srcLength && m_source[m_srcIndex] != "{") {
+-                    const QString& baseName = m_source[m_srcIndex];
+-                    Import_Utils::createGeneralization(m_klass, baseName);
+-                    if (advance() != ",")
+-                        break;
+-                    m_srcIndex++;
+-                }
+-            }
+-            if (m_source[m_srcIndex] != "{") {
+-                kdError() << "importIDL: ignoring excess chars at "
+-                << name << endl;
+-                skipStmt("{");
+-            }
+-            m_comment = QString::null;
+-            continue;
+-        }
+-        if (keyword == "public") {
+-            continue;
+-        }
+-        if (keyword == "private") {
+-            m_currentAccess = Uml::Visibility::Private;
+-            continue;
+-        }
+-        if (keyword == "readonly") {
+-            m_isReadonly = true;
+-            continue;
+-        }
+-        if (keyword == "attribute") {
+-            m_isAttribute = true;
+-            continue;
+-        }
+-        if (keyword == "oneway") {
+-            m_isOneway = true;
+-            continue;
+-        }
+-        if (keyword == "}") {
+-            if (m_scopeIndex)
+-                m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
+-            else
+-                kdError() << "importIDL: too many }" << endl;
+-            m_srcIndex++;  // skip ';'
+-            continue;
+-        }
+-        if (keyword == ";")
+-            continue;
+-        // At this point, we expect `keyword' to be a type name
+-        // (of a member of struct or valuetype, or return type
+-        // of an operation.) Up next is the name of the attribute
+-        // or operation.
+-        if (! keyword.contains( QRegExp("^\\w") )) {
+-            kdError() << "importIDL: ignoring " << keyword << endl;
+-            skipStmt();
+-            continue;
+-        }
+-        QString typeName = joinTypename();
+-        QString name = advance();
+-        if (name.contains( QRegExp("\\W") )) {
+-            kdError() << "importIDL: expecting name in " << name << endl;
+-            skipStmt();
+-            continue;
+-        }
+-        // At this point we most definitely need a class.
+-        if (m_klass == NULL) {
+-            kdError() << "importIDL: no class set for " << name << endl;
+-            continue;
+-        }
+-        QString nextToken = advance();
+-        if (nextToken == "(") {
+-            // operation
+-            UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+-            m_srcIndex++;
+-            while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+-                const QString &direction = m_source[m_srcIndex++];
+-                QString typeName = joinTypename();
+-                const QString &parName = advance();
+-                UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName);
+-                Uml::Parameter_Direction dir;
+-                if (Model_Utils::stringToDirection(direction, dir))
+-                    att->setParmKind(dir);
+-                else
+-                    kdError() << "importIDL: expecting parameter direction at "
+-                    << direction << endl;
++        skipStmt();
++        return true;
++    }
++    if (keyword == "typedef") {
++        const QString& existingType = advance();
++        const QString& newType = advance();
++        Import_Utils::createUMLObject(Uml::ot_Class, newType, m_scope[m_scopeIndex],
++                                     m_comment, "CORBATypedef" /* stereotype */);
++        // @todo How do we convey the existingType ?
++        skipStmt();
++        return true;
++    }
++    if (keyword == "const") {
++        skipStmt();
++        return true;
++    }
++    if (keyword == "custom") {
++        return true;
++    }
++    if (keyword == "abstract") {
++        m_isAbstract = true;
++        return true;
++    }
++    if (keyword == "valuetype") {
++        const QString& name = advance();
++        UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
++                        name, m_scope[m_scopeIndex], m_comment);
++        m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
++        m_klass->setAbstract(m_isAbstract);
++        m_isAbstract = false;
++        if (advance() == ";")   // forward declaration
++            return true;
++        if (m_source[m_srcIndex] == ":") {
++            if (advance() == "truncatable")
++                m_srcIndex++;
++            while (m_srcIndex < srcLength && m_source[m_srcIndex] != "{") {
++                const QString& baseName = m_source[m_srcIndex];
++                Import_Utils::createGeneralization(m_klass, baseName);
+                 if (advance() != ",")
+                     break;
+                 m_srcIndex++;
+             }
+-            Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, typeName,
+-                                      false, false, false, false, m_comment);
+-            if (m_isOneway) {
+-                op->setStereotype("oneway");
+-                m_isOneway = false;
+-            }
+-            skipStmt();  // skip possible "raises" clause
+-            m_comment = QString::null;
+-            continue;
+         }
+-        // At this point we know it's some kind of attribute declaration.
+-        while (1) {
+-            while (nextToken != "," && nextToken != ";") {
+-                name += nextToken;  // add possible array dimensions to `name'
+-                nextToken = advance();
+-            }
+-            UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name, typeName, m_comment);
+-            UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+-            if (m_isReadonly) {
+-                attr->setStereotype("readonly");
+-                m_isReadonly = false;
+-            }
+-            if (nextToken != ",")
++        if (m_source[m_srcIndex] != "{") {
++            kdError() << "importIDL: ignoring excess chars at "
++            << name << endl;
++            skipStmt("{");
++        }
++        return true;
++    }
++    if (keyword == "public") {
++        return true;
++    }
++    if (keyword == "private") {
++        m_currentAccess = Uml::Visibility::Private;
++        return true;
++    }
++    if (keyword == "readonly") {
++        m_isReadonly = true;
++        return true;
++    }
++    if (keyword == "attribute") {
++        m_isAttribute = true;
++        return true;
++    }
++    if (keyword == "oneway") {
++        m_isOneway = true;
++        return true;
++    }
++    if (keyword == "}") {
++        if (m_scopeIndex)
++            m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
++        else
++            kdError() << "importIDL: too many }" << endl;
++        m_srcIndex++;  // skip ';'
++        return true;
++    }
++    if (keyword == ";")
++        return true;
++    // At this point, we expect `keyword' to be a type name
++    // (of a member of struct or valuetype, or return type
++    // of an operation.) Up next is the name of the attribute
++    // or operation.
++    if (! keyword.contains( QRegExp("^\\w") )) {
++        kdError() << "importIDL: ignoring " << keyword << endl;
++        return false;
++    }
++    QString typeName = joinTypename();
++    QString name = advance();
++    if (name.contains( QRegExp("\\W") )) {
++        kdError() << "importIDL: expecting name in " << name << endl;
++        return false;
++    }
++    // At this point we most definitely need a class.
++    if (m_klass == NULL) {
++        kdError() << "importIDL: no class set for " << name << endl;
++        return false;
++    }
++    QString nextToken = advance();
++    if (nextToken == "(") {
++        // operation
++        UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
++        m_srcIndex++;
++        while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
++            const QString &direction = m_source[m_srcIndex++];
++            QString typeName = joinTypename();
++            const QString &parName = advance();
++            UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName);
++            Uml::Parameter_Direction dir;
++            if (Model_Utils::stringToDirection(direction, dir))
++                att->setParmKind(dir);
++            else
++                kdError() << "importIDL: expecting parameter direction at "
++                << direction << endl;
++            if (advance() != ",")
+                 break;
+-            name = advance();
++            m_srcIndex++;
++        }
++        Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, typeName,
++                                  false, false, false, false, m_comment);
++        if (m_isOneway) {
++            op->setStereotype("oneway");
++            m_isOneway = false;
++        }
++        skipStmt();  // skip possible "raises" clause
++        return true;
++    }
++    // At this point we know it's some kind of attribute declaration.
++    while (1) {
++        while (nextToken != "," && nextToken != ";") {
++            name += nextToken;  // add possible array dimensions to `name'
+             nextToken = advance();
+         }
+-        m_currentAccess = Uml::Visibility::Public;
+-        if (m_source[m_srcIndex] != ";") {
+-            kdError() << "importIDL: ignoring trailing items at " << name << endl;
+-            skipStmt();
++        UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name, typeName, m_comment);
++        UMLAttribute *attr = static_cast<UMLAttribute*>(o);
++        if (m_isReadonly) {
++            attr->setStereotype("readonly");
++            m_isReadonly = false;
+         }
+-        m_comment = QString::null;
++        if (nextToken != ",")
++            break;
++        name = advance();
++        nextToken = advance();
+     }
+-    pclose(fp);
++    return true;
+ }
+ 
+-
+--- umbrello/umbrello/umldoc.cpp	(revision 490305)
++++ umbrello/umbrello/umldoc.cpp	(revision 497528)
+@@ -44,19 +44,14 @@
+ #endif
+ 
+ // app includes
+-#include "actor.h"
+ #include "associationwidget.h"
+ #include "association.h"
+ #include "package.h"
+-#include "component.h"
+ #include "codegenerator.h"
+-#include "node.h"
+-#include "artifact.h"
+ #include "datatype.h"
+ #include "enum.h"
+ #include "entity.h"
+ #include "docwindow.h"
+-#include "objectwidget.h"
+ #include "operation.h"
+ #include "attribute.h"
+ #include "template.h"
+@@ -64,13 +59,13 @@
+ #include "entityattribute.h"
+ #include "stereotype.h"
+ #include "classifierlistitem.h"
++#include "object_factory.h"
+ #include "model_utils.h"
+ #include "widget_utils.h"
+ #include "uml.h"
+ #include "umllistview.h"
+ #include "umllistviewitem.h"
+ #include "umlview.h"
+-#include "usecase.h"
+ #include "clipboard/idchangelog.h"
+ #include "dialogs/classpropdlg.h"
+ #include "inputdialog.h"
+@@ -109,7 +104,6 @@
+     m_bTypesAreResolved = false;
+     m_pAutoSaveTimer = 0;
+     m_nViewID = Uml::id_None;
+-    m_highestIDforForeignFile = 0;
+     m_pTabPopupMenu = 0;
+     UMLApp * pApp = UMLApp::app();
+     connect(this, SIGNAL(sigDiagramCreated(Uml::IDType)), pApp, SLOT(slotUpdateViews()));
+@@ -258,8 +252,7 @@
+     }
+ 
+     // remove all code generators
+-    QDictIterator<CodeGenerator> it( m_codeGeneratorDictionary );
+-    for( ; it.current(); ++it )
++    for (CodeGeneratorListIt it(m_codeGenerators); it.current(); ++it)
+         removeCodeGenerator(it.current());
+ 
+     m_currentcodegenerator = 0;
+@@ -704,14 +697,10 @@
+ {
+     if(!gen)
+         return false;
+-
+-    QString tag = gen->getLanguage(); // this should be unique
+-
+-    if(m_codeGeneratorDictionary.find(tag))
+-        return false; // return false, we already have some object with this tag in the list
++    if (m_codeGenerators.find(gen) >= 0)
++        return false; // return false, we already have the object in the list
+     else
+-        m_codeGeneratorDictionary.insert(tag, gen);
+-
++        m_codeGenerators.append(gen);
+     return true;
+ }
+ 
+@@ -731,11 +720,11 @@
+  * Remove a CodeGenerator object
+  */
+ bool UMLDoc::removeCodeGenerator ( CodeGenerator * remove_object ) {
+-    QString lang = remove_object->getLanguage();
+-    if(!(lang.isEmpty()) && m_codeGeneratorDictionary.find(lang))
++    QString lang = Model_Utils::progLangToString( remove_object->getLanguage() );
++    if(!(lang.isEmpty()) && m_codeGenerators.find(remove_object) >= 0)
+     {
+         m_codeGenerationXMIParamMap->erase(lang);
+-        m_codeGeneratorDictionary.remove(lang);
++        m_codeGenerators.remove(remove_object);
+         delete remove_object;
+     } else
+         return false;
+@@ -743,8 +732,12 @@
+     return true;
+ }
+ 
+-CodeGenerator * UMLDoc::findCodeGeneratorByLanguage (const QString &lang) {
+-    return m_codeGeneratorDictionary.find(lang);
++CodeGenerator * UMLDoc::findCodeGeneratorByLanguage (Uml::Programming_Language lang) {
++    CodeGenerator *cg = NULL;
++    for (CodeGeneratorListIt it(m_codeGenerators); (cg = it.current()) != NULL; ++it)
++        if (cg->getLanguage() == lang)
++            break;
++    return cg;
+ }
+ 
+ UMLView * UMLDoc::findView(Uml::IDType id) {
+@@ -804,52 +797,12 @@
+     return dynamic_cast<UMLClassifier*>(obj);
+ }
+ 
+-QString UMLDoc::uniqObjectName(const Object_Type type, QString prefix,
+-                               UMLPackage *parentPkg /* = NULL */) {
+-    QString currentName = prefix;
+-    if (currentName.isEmpty()) {
+-        if(type == ot_Class)
+-            currentName = i18n("new_class");
+-        else if(type == ot_Actor)
+-            currentName = i18n("new_actor");
+-        else if(type == ot_UseCase)
+-            currentName = i18n("new_usecase");
+-        else if(type == ot_Package)
+-            currentName = i18n("new_package");
+-        else if(type == ot_Component)
+-            currentName = i18n("new_component");
+-        else if(type == ot_Node)
+-            currentName = i18n("new_node");
+-        else if(type == ot_Artifact)
+-            currentName = i18n("new_artifact");
+-        else if(type == ot_Interface)
+-            currentName = i18n("new_interface");
+-        else if(type == ot_Datatype)
+-            currentName = i18n("new_datatype");
+-        else if(type == ot_Enum)
+-            currentName = i18n("new_enum");
+-        else if(type == ot_Entity)
+-            currentName = i18n("new_entity");
+-        else if(type == ot_Association)
+-            currentName = i18n("new_association");
+-        else {
+-            currentName = i18n("new_object");
+-            kdWarning() << "unknown object type in umldoc::uniqObjectName()" << endl;
+-        }
+-    }
+-    QString name = currentName;
+-    for (int number = 1; !isUnique(name, parentPkg); number++)  {
+-        name = currentName + "_" + QString::number(number);
+-    }
+-    return name;
+-}
+-
+ /**
+   *   Adds a UMLObject thats already created but doesn't change
+   *   any ids or signal.  Used by the list view.  Use
+   *   AddUMLObjectPaste if pasting.
+   */
+-bool UMLDoc::addUMLObject(UMLObject* object) {
++bool UMLDoc::addUMLObject(UMLObject* object, bool prepend) {
+     Object_Type ot = object->getBaseType();
+     if (ot == ot_Attribute || ot == ot_Operation || ot == ot_EnumLiteral
+             || ot == ot_EntityAttribute || ot == ot_Template || ot == ot_Stereotype) {
+@@ -869,13 +822,10 @@
+                   << " because it's already there." << endl;
+         return false;
+     }
+-    m_objectList.append( object );
+-    // CHECK: Can we remove this m_highestIDforForeignFile voodoo ///
+-    Uml::IDType id = object->getID();
+-    int nId = INTERNALIZE_ID(id);
+-    if (nId > m_highestIDforForeignFile)
+-        m_highestIDforForeignFile = nId;
+-    // end CHECK ////////////////////////////////////////////////////
++    if (prepend)
++        m_objectList.prepend(object);
++    else
++        m_objectList.append(object);
+     return true;
+ }
+ 
+@@ -948,125 +898,6 @@
+     return true;
+ }
+ 
+-UMLObject* UMLDoc::createUMLObject(Object_Type type, const QString &n,
+-                                   UMLPackage *parentPkg /* = NULL */,
+-                                   bool prepend /* = false */) {
+-    bool ok = false;
+-    QString name;
+-    if( !n.isEmpty() && isUnique(n, parentPkg) )
+-    {
+-        name = n;
+-    }
+-    else
+-    {
+-        name = uniqObjectName(type, n, parentPkg);
+-        bool bValidNameEntered = false;
+-        do {
+-            name = KInputDialog::getText(i18n("Name"), i18n("Enter name:"), name, &ok, (QWidget*)UMLApp::app());
+-            if (!ok) {
+-                return 0;
+-            }
+-            if (name.length() == 0) {
+-                KMessageBox::error(0, i18n("That is an invalid name."),
+-                                   i18n("Invalid Name"));
+-                continue;
+-            }
+-            if (getCurrentCodeGenerator() != NULL &&
+-                    getCurrentCodeGenerator()->isReservedKeyword(name)) {
+-                KMessageBox::error(0, i18n("This is a reserved keyword for the language of the configured code generator."),
+-                                   i18n("Reserved Keyword"));
+-                continue;
+-            }
+-            if (! isUnique(name, parentPkg)) {
+-                KMessageBox::error(0, i18n("That name is already being used."),
+-                                   i18n("Not a Unique Name"));
+-                continue;
+-            }
+-            bValidNameEntered = true;
+-        } while (bValidNameEntered == false);
+-    }
+-    UMLObject *o = NULL;
+-    if(type == ot_Actor) {
+-        o = new UMLActor(name);
+-    } else if(type == ot_UseCase) {
+-        o = new UMLUseCase(name);
+-    } else if(type == ot_Class ) {
+-        o = new UMLClassifier(name);
+-    } else if(type == ot_Package) {
+-        o = new UMLPackage(name);
+-    } else if(type == ot_Component) {
+-        o = new UMLComponent(name);
+-    } else if(type == ot_Node) {
+-        o = new UMLNode(name);
+-    } else if(type == ot_Artifact) {
+-        o = new UMLArtifact(name);
+-    } else if(type == ot_Interface) {
+-        UMLClassifier *c = new UMLClassifier(name);
+-        c->setInterface();
+-        o = c;
+-    } else if(type == ot_Datatype) {
+-        o = new UMLDatatype(name);
+-    } else if(type == ot_Enum) {
+-        o = new UMLEnum(name);
+-    } else if(type == ot_Entity) {
+-        o = new UMLEntity(name);
+-    } else {
+-        kdWarning() << "CreateUMLObject(int) error unknown type: " << type << endl;
+-        return (UMLObject*)0L;
+-    }
+-    o->setUMLPackage(parentPkg);
+-    if (parentPkg)
+-        parentPkg->addObject(o);
+-    else if (prepend)
+-        m_objectList.prepend(o);
+-    else
+-        m_objectList.append(o);
+-    emit sigObjectCreated(o);
+-    setModified(true);
+-    return o;
+-}
+-
+-UMLObject* UMLDoc::createChildObject(UMLObject* umlobject, Object_Type type) {
+-    UMLObject* returnObject = NULL;
+-    switch (type) {
+-    case ot_Attribute: {
+-            UMLClassifier *c = dynamic_cast<UMLClassifier*>(umlobject);
+-            if (c && !c->isInterface())
+-                returnObject = c->createAttribute();
+-            break;
+-        }
+-    case ot_Operation: {
+-            UMLClassifier *c = dynamic_cast<UMLClassifier*>(umlobject);
+-            if (c)
+-                returnObject = c->createOperation();
+-            break;
+-        }
+-    case ot_Template: {
+-            UMLClassifier *c = dynamic_cast<UMLClassifier*>(umlobject);
+-            if (c)
+-                returnObject = c->createTemplate();
+-            break;
+-        }
+-    case ot_EnumLiteral: {
+-            UMLEnum* umlenum = dynamic_cast<UMLEnum*>(umlobject);
+-            if (umlenum) {
+-                returnObject = umlenum->createEnumLiteral();
+-            }
+-            break;
+-        }
+-    case ot_EntityAttribute: {
+-            UMLEntity* umlentity = dynamic_cast<UMLEntity*>(umlobject);
+-            if (umlentity) {
+-                returnObject = umlentity->createEntityAttribute();
+-            }
+-            break;
+-        }
+-    default:
+-        kdDebug() << "ERROR UMLDoc::createChildObject type:" << type << endl;
+-    }
+-    return returnObject;
+-}
+-
+ UMLStereotype* UMLDoc::findStereotype(const QString &name) {
+     for (UMLStereotype *s = m_stereoList.first(); s; s = m_stereoList.next() ) {
+         if (s->getName() == name)
+@@ -1453,34 +1284,6 @@
+     setModified(true);
+ }
+ 
+-bool UMLDoc::showProperties(UMLObject* object, int page, bool assoc) {
+-    UMLApp::app()->getDocWindow()->updateDocumentation( false );
+-    ClassPropDlg* dialogue = new ClassPropDlg((QWidget*)UMLApp::app(), object, page, assoc);
+-
+-    bool modified = false;
+-    if ( dialogue->exec() ) {
+-        UMLApp::app()->getDocWindow()->showDocumentation(object, true);
+-        setModified(true);
+-        modified = true;
+-    }
+-    dialogue->close(true);//wipe from memory
+-    return modified;
+-}
+-
+-bool UMLDoc::showProperties(ObjectWidget *o) {
+-    UMLApp::app()->getDocWindow() -> updateDocumentation( false );
+-    ClassPropDlg *dlg = new ClassPropDlg((QWidget*)UMLApp::app(), o);
+-
+-    bool modified = false;
+-    if(dlg->exec()) {
+-        UMLApp::app()->getDocWindow() -> showDocumentation( o, true );
+-        setModified(true);
+-        modified = true;
+-    }
+-    dlg -> close(true);//wipe from memory
+-    return modified;
+-}
+-
+ void UMLDoc::signalUMLObjectCreated(UMLObject * o) {
+     emit sigObjectCreated(o);
+     if (!m_bLoading)
+@@ -1688,8 +1491,8 @@
+ 
+     // save code generators
+     QDomElement codeGenElement = doc.createElement( "codegeneration" );
+-    QDictIterator<CodeGenerator> it( m_codeGeneratorDictionary );
+-    for( ; it.current(); ++it )
++    
++    for (CodeGeneratorListIt it(m_codeGenerators); it.current(); ++it)
+         it.current()->saveToXMI ( doc, codeGenElement );
+     extensions.appendChild( codeGenElement );
+ 
+@@ -1827,7 +1630,7 @@
+             pView->hide();
+             addView(pView);
+         } else {
+-            UMLObject *pObject = makeNewUMLObject(type);
++            UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
+             if (pObject) {
+                 if (! pObject->loadFromXMI(element)) {
+                     kdError() << "UMLDoc::loadFolderFile(" << filename
+@@ -1891,7 +1694,6 @@
+     }
+ 
+     m_nViewID = Uml::id_None;
+-    m_highestIDforForeignFile = 0;
+     for (node = node.firstChild(); !node.isNull(); node = node.nextSibling()) {
+         if (node.isComment())
+             continue;
+@@ -1991,19 +1793,6 @@
+ #endif
+     resolveTypes();
+ 
+-    if (m_nViewID == Uml::id_None) {
+-        m_uniqueID = m_highestIDforForeignFile;
+-        // We must do this because there is no <docsettings> to
+-        // tell us the highest ID when loading foreign XMI files.
+-        kdDebug() << "UMLDoc::loadFromXMI: Setting m_uniqueID to "
+-        << m_uniqueID << " because no <docsettings> encountered"
+-        << endl;
+-        // Let's make it the next round number.
+-        int roundUpFactor = (m_uniqueID < 1000 ? 100 :
+-                             m_uniqueID < 10000 ? 1000 : 10000);
+-        m_uniqueID = roundUpFactor * ((m_uniqueID - 1) / roundUpFactor + 1);
+-    }
+-
+     emit sigWriteToStatusBar( i18n("Setting up the document...") );
+     kapp->processEvents();  // give UI events a chance
+     m_currentView = NULL;
+@@ -2132,7 +1921,7 @@
+             }
+             continue;
+         }
+-        UMLObject *pObject = makeNewUMLObject(type);
++        UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
+         if( !pObject ) {
+             kdWarning() << "Unknown type of umlobject to create: " << type << endl;
+             // We want a best effort, therefore this is handled as a
+@@ -2147,6 +1936,8 @@
+         if (tagEq(type, "Association") ||
+                 tagEq(type, "AssociationClass") ||
+                 tagEq(type, "Generalization") ||
++                tagEq(type, "Realization") ||
++                tagEq(type, "Abstraction") ||
+                 tagEq(type, "Dependency")) {
+             if ( !status ) {
+                 // Some interim umbrello versions saved empty UML:Associations,
+@@ -2228,64 +2019,6 @@
+     }
+ }
+ 
+-UMLObject* UMLDoc::makeNewClassifierObject(QString type, UMLClassifier *parent) {
+-    if (parent == NULL)
+-        return NULL;
+-    UMLObject* pObject = NULL;
+-    if (tagEq(type, "Operation")) {
+-        pObject = new UMLOperation(parent);
+-    } else if (tagEq(type, "Attribute")) {
+-        if (parent->getBaseType() != Uml::ot_Class)
+-            return NULL;
+-        UMLClassifier *pClass = static_cast<UMLClassifier*>(parent);
+-        pObject = new UMLAttribute(pClass);
+-    } else if (tagEq(type, "Template")) {
+-        pObject = new UMLTemplate(parent);
+-    }
+-    return pObject;
+-}
+-
+-UMLObject* UMLDoc::makeNewUMLObject(const QString &type) {
+-    UMLObject* pObject = 0;
+-    if (tagEq(type, "UseCase")) {
+-        pObject = new UMLUseCase();
+-    } else if (tagEq(type, "Actor")) {
+-        pObject = new UMLActor();
+-    } else if (tagEq(type, "Class")) {
+-        pObject = new UMLClassifier();
+-    } else if (tagEq(type, "Package")) {
+-        pObject = new UMLPackage();
+-    } else if (tagEq(type, "Component")) {
+-        pObject = new UMLComponent();
+-    } else if (tagEq(type, "Node")) {
+-        pObject = new UMLNode();
+-    } else if (tagEq(type, "Artifact")) {
+-        pObject = new UMLArtifact();
+-    } else if (tagEq(type, "Interface")) {
+-        UMLClassifier *c = new UMLClassifier();
+-        c->setInterface();
+-        pObject = c;
+-    } else if (tagEq(type, "DataType") || tagEq(type, "Primitive")
+-               || tagEq(type, "Datatype")) {   // for bkwd compat.
+-        pObject = new UMLDatatype();
+-    } else if (tagEq(type, "Enumeration") ||
+-               tagEq(type, "Enum")) {   // for bkwd compat.
+-        pObject = new UMLEnum();
+-    } else if (tagEq(type, "Entity")) {
+-        pObject = new UMLEntity();
+-    } else if (tagEq(type, "Stereotype")) {
+-        pObject = new UMLStereotype();
+-    } else if (tagEq(type, "Association") ||
+-               tagEq(type, "AssociationClass")) {
+-        pObject = new UMLAssociation();
+-    } else if (tagEq(type, "Generalization")) {
+-        pObject = new UMLAssociation(Uml::at_Generalization);
+-    } else if (tagEq(type, "Dependency")) {
+-        pObject = new UMLAssociation(Uml::at_Dependency);
+-    }
+-    return pObject;
+-}
+-
+ bool UMLDoc::loadDiagramsFromXMI( QDomNode & node ) {
+     emit sigWriteToStatusBar( i18n("Loading diagrams...") );
+     emit sigResetStatusbarProgress();
+@@ -2342,34 +2075,6 @@
+     UMLApp::app()->setDiagramMenuItemsState(false);
+ }
+ 
+-QStringList UMLDoc::getModelTypes()
+-{
+-    QStringList types;
+-    //insert "standard" (frequently used) types --FIXME, make this language dependant.
+-    types.append("void");
+-    types.append("int");
+-    types.append("long");
+-    types.append("bool");
+-    types.append("string");
+-    types.append("double");
+-    types.append("float");
+-    types.append("date");
+-
+-    // adding for perl The 3 base type (SV,AV,HV)
+-    types.append("$");
+-    types.append("@");
+-    types.append("%");
+-
+-    //now add the Classes and Interfaces (both are Concepts)
+-    UMLClassifierList namesList( getConcepts() );
+-    UMLClassifier* pConcept = 0;
+-    for(pConcept=namesList.first(); pConcept!=0 ;pConcept=namesList.next())
+-    {
+-        types.append( pConcept->getName() );
+-    }
+-    return types;
+-}
+-
+ UMLClassifierList UMLDoc::getConcepts(bool includeNested /* =true */) {
+     UMLClassifierList conceptList;
+     for (UMLObjectListIt oit(m_objectList); oit.current(); ++oit) {
+@@ -2472,22 +2177,6 @@
+     painter.end();
+ }
+ 
+-bool UMLDoc::showProperties(UMLWidget * o) {
+-    // will already be selected so make sure docWindow updates the doc
+-    // back it the widget
+-    UMLApp::app()->getDocWindow() -> updateDocumentation( false );
+-    ClassPropDlg *dlg = new ClassPropDlg((QWidget*)UMLApp::app(), o);
+-
+-    bool modified = false;
+-    if(dlg->exec()) {
+-        UMLApp::app()->getDocWindow() -> showDocumentation( o -> getUMLObject() , true );
+-        setModified(true);
+-        modified = true;
+-    }
+-    dlg -> close(true);//wipe from memory
+-    return modified;
+-}
+-
+ void UMLDoc::setModified(bool modified /*=true*/, bool addToUndo /*=true*/) {
+     if(!m_bLoading) {
+         m_modified = modified;
+@@ -2798,13 +2487,16 @@
+ }
+ 
+ void UMLDoc::addDefaultDatatypes() {
+-    UMLApp::app()->getGenerator()->createDefaultDatatypes();
++    QStringList entries = UMLApp::app()->getGenerator()->defaultDatatypes();
++    QStringList::Iterator end(entries.end());
++    for (QStringList::Iterator it = entries.begin(); it != end; ++it)
++        createDatatype(*it);
+ }
+ 
+ void UMLDoc::createDatatype(const QString &name)  {
+     UMLObject* umlobject = findUMLObject(name, ot_Datatype);
+     if (!umlobject) {
+-        createUMLObject(ot_Datatype, name);
++        Object_Factory::createUMLObject(ot_Datatype, name);
+     }
+     UMLApp::app()->getListView()->closeDatatypesFolder();
+ }
+--- umbrello/umbrello/attribute.cpp	(revision 490305)
++++ umbrello/umbrello/attribute.cpp	(revision 497528)
+@@ -24,8 +24,8 @@
+ #include "umldoc.h"
+ #include "uml.h"
+ #include "dialogs/umlattributedialog.h"
++#include "object_factory.h"
+ 
+-
+ UMLAttribute::UMLAttribute( const UMLObject *parent, QString Name, Uml::IDType id,
+                             Uml::Visibility s, QString type, QString iv )
+         : UMLClassifierListItem(parent, Name, id) {
+@@ -38,9 +38,9 @@
+         m_pSecondary = pDoc->findUMLObject(type);
+         if (m_pSecondary == NULL) {
+             if (type.contains( QRegExp("[\\*\\&]") ))
+-                m_pSecondary = pDoc->createUMLObject(Uml::ot_Datatype, type);
++                m_pSecondary = Object_Factory::createUMLObject(Uml::ot_Datatype, type);
+             else
+-                m_pSecondary = pDoc->createUMLObject(Uml::ot_Class, type);
++                m_pSecondary = Object_Factory::createUMLObject(Uml::ot_Class, type);
+         }
+     }
+ }
+--- umbrello/umbrello/clipboard/umldrag.cpp	(revision 490305)
++++ umbrello/umbrello/clipboard/umldrag.cpp	(revision 497528)
+@@ -25,6 +25,8 @@
+ #include "../umllistview.h"
+ #include "../umllistviewitem.h"
+ #include "../associationwidget.h"
++#include "../object_factory.h"
++#include "../model_utils.h"
+ 
+ #define nfmt 4
+ class UMLDragPrivate {
+@@ -342,7 +344,7 @@
+             element = objectElement.toElement();
+             continue;
+         }
+-        pObject = UMLDoc::makeNewUMLObject(type);
++        pObject = Object_Factory::makeObjectFromXMI(type);
+ 
+         if( !pObject ) {
+             kdWarning() << "UMLDrag::decodeClip1: Given wrong type of umlobject to create: "
+@@ -369,7 +371,7 @@
+                 return false;
+             }
+             Uml::Object_Type type = pObject->getBaseType();
+-            QString newName = doc->uniqObjectName(type, pObject->getName());
++            QString newName = Model_Utils::uniqObjectName(type, pObject->getName());
+             pObject->setName(newName);
+             /****************************************************************/
+ 
+@@ -473,7 +475,7 @@
+         pObject = 0;
+         QString type = element.tagName();
+         if (type != "UML:Association") {
+-            pObject = UMLDoc::makeNewUMLObject(type);
++            pObject = Object_Factory::makeObjectFromXMI(type);
+ 
+             if( !pObject ) {
+                 kdWarning() << "Given wrong type of umlobject to create:" << type << endl;
+@@ -691,7 +693,7 @@
+         //FIXME associations don't load
+         if (type == "UML:Association")
+             continue;
+-        pObject = UMLDoc::makeNewUMLObject(type);
++        pObject = Object_Factory::makeObjectFromXMI(type);
+ 
+         if ( !pObject ) {
+             kdWarning() << "Given wrong type of umlobject to create: " << type << endl;
+@@ -794,12 +796,9 @@
+     if ( element.isNull() ) {
+         return false;//return ok as it means there is no umlobjects
+     }
+-    UMLObject* pObject = 0;
+     while ( !element.isNull() ) {
+-        pObject = 0;
+         QString type = element.tagName();
+-        pObject = UMLDoc::makeNewClassifierObject(type, newParent);
+-
++        UMLClassifierListItem *pObject = newParent->makeChildObject(type);
+         if( !pObject ) {
+             kdWarning() << "Given wrong type of umlobject to create:" << type << endl;
+             return false;
+--- umbrello/umbrello/adaimport.cpp	(revision 490305)
++++ umbrello/umbrello/adaimport.cpp	(revision 497528)
+@@ -14,9 +14,6 @@
+ 
+ #include <stdio.h>
+ // qt/kde includes
+-#include <qfile.h>
+-#include <qtextstream.h>
+-#include <qstringlist.h>
+ #include <qregexp.h>
+ #include <kdebug.h>
+ // app includes
+@@ -30,11 +27,16 @@
+ #include "attribute.h"
+ 
+ AdaImport::AdaImport() : NativeImportBase("--") {
++   initVars();
+ }
+ 
+ AdaImport::~AdaImport() {
+ }
+ 
++void AdaImport::initVars() {
++    m_inGenericFormalPart = false;
++}
++
+ bool AdaImport::preprocess(QString&) {
+     return false;
+ }
+@@ -72,439 +74,368 @@
+         m_source.append(lexeme);
+ }
+ 
+-void AdaImport::parseFile(QString filename) {
+-    if (filename.contains('/')) {
+-        QString path = filename;
+-        path.remove( QRegExp("/[^/]+$") );
+-        kdDebug() << "IDLImport::parseFile: adding path " << path << endl;
+-        Import_Utils::addIncludePath(path);
+-    }
+-    if (! QFile::exists(filename)) {
+-        if (filename.startsWith("/")) {
+-            kdError() << "AdaImport::parseFile(" << filename
+-                      << "): cannot find file" << endl;
+-            return;
++bool AdaImport::parseStmt() {
++    const uint srcLength = m_source.count();
++    const QString& keyword = m_source[m_srcIndex];
++    //kdDebug() << '"' << keyword << '"' << endl;
++    if (keyword == "with") {
++        if (m_inGenericFormalPart) {
++            // mapping of generic formal subprograms or packages is not yet implemented
++            return false;
+         }
+-        bool found = false;
+-        QStringList includePaths = Import_Utils::includePathList();
+-        for (QStringList::Iterator pathIt = includePaths.begin();
+-                                   pathIt != includePaths.end(); ++pathIt) {
+-            QString path = (*pathIt);
+-            if (! path.endsWith("/")) {
+-                path.append("/");
++        while (++m_srcIndex < srcLength && m_source[m_srcIndex] != ";") {
++            QStringList components = QStringList::split(".", m_source[m_srcIndex].lower());
++            const QString& prefix = components.first();
++            if (prefix == "system" || prefix == "ada" || prefix == "gnat" ||
++                prefix == "interfaces" || prefix == "text_io" ||
++                prefix == "unchecked_conversion" ||
++                prefix == "unchecked_deallocation") {
++                if (advance() != ",")
++                    break;
++                continue;
+             }
+-            if (QFile::exists(path + filename)) {
+-                filename.prepend(path);
+-                found = true;
+-                break;
++            QString base = prefix;
++            uint i = 0;
++            while (1) {
++                if (! m_parsedFiles.contains(base)) {
++                    m_parsedFiles.append(base);
++                    QString filename = base + ".ads";
++                    // Save current m_source and m_srcIndex.
++                    QStringList source(m_source);
++                    uint srcIndex = m_srcIndex;
++                    m_source.clear();
++                    parseFile(filename);
++                    // Restore m_source and m_srcIndex.
++                    m_source = source;
++                    m_srcIndex = srcIndex;
++                    // Also reset m_currentAccess.
++                    // CHECK: need to reset more stuff?
++                    m_currentAccess = Uml::Visibility::Public;
++                }
++                if (++i >= components.count())
++                    break;
++                base += '-' + components[i];
+             }
++            if (advance() != ",")
++                break;
+         }
+-        if (! found) {
+-            kdError() << "AdaImport::parseFile(" << filename
+-                      << "): cannot find file" << endl;
+-            return;
+-        }
++        return true;
+     }
+-    QFile file(filename);
+-    if (! file.open(IO_ReadOnly)) {
+-        kdError() << "AdaImport::parseFile(" << filename
+-                  << "): cannot open file" << endl;
+-        return;
++    if (keyword == "generic") {
++        m_inGenericFormalPart = true;
++        return true;
+     }
+-    // Scan the input file into the QStringList m_source.
+-    m_srcIndex = 0;
+-    QTextStream stream(&file);
+-    while (! stream.atEnd()) {
+-        QString line = stream.readLine();
+-        scan(line);
+-    }
+-    file.close();
+-    // Parse the QStringList m_source.
+-    m_klass = NULL;
+-    m_currentAccess = Uml::Visibility::Public;
+-    m_isAbstract = false;
+-    const uint srcLength = m_source.count();
+-    bool inGenericFormalPart = false;
+-    for (m_srcIndex = 0; m_srcIndex < srcLength; m_srcIndex++) {
+-        const QString& keyword = m_source[m_srcIndex];
+-        kdDebug() << '"' << keyword << '"' << endl;
+-        if (keyword.startsWith("--")) {
+-            m_comment += keyword.mid(2) + '\n';
+-            continue;
+-        }
+-        if (keyword == "with") {
+-            if (inGenericFormalPart) {
+-                // mapping of generic formal subprograms or packages is not yet implemented
++    if (keyword == "package") {
++        const QString& name = advance();
++        UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
++                        name, m_scope[m_scopeIndex], m_comment);
++        if (advance() == "is") {
++            if (m_source[m_srcIndex + 1] == "new") {
++                // generic package instantiation: TBD
+                 skipStmt();
+-                continue;
++            } else {
++                m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+             }
+-            while (++m_srcIndex < srcLength && m_source[m_srcIndex] != ";") {
+-                QStringList components = QStringList::split(".", m_source[m_srcIndex].lower());
+-                const QString& prefix = components.first();
+-                if (prefix == "system" || prefix == "ada" || prefix == "gnat" ||
+-                    prefix == "interfaces" || prefix == "text_io" ||
+-                    prefix == "unchecked_conversion" ||
+-                    prefix == "unchecked_deallocation") {
+-                    if (advance() != ",")
+-                        break;
+-                    continue;
+-                }
+-                QString base = prefix;
+-                uint i = 0;
+-                while (1) {
+-                    if (! m_parsedFiles.contains(base)) {
+-                        m_parsedFiles.append(base);
+-                        QString filename = base + ".ads";
+-                        // Save current m_source and m_srcIndex.
+-                        QStringList source(m_source);
+-                        uint srcIndex = m_srcIndex;
+-                        m_source.clear();
+-                        parseFile(filename);
+-                        // Restore m_source and m_srcIndex.
+-                        m_source = source;
+-                        m_srcIndex = srcIndex;
+-                        // Also reset m_currentAccess.
+-                        // CHECK: need to reset more stuff?
+-                        m_currentAccess = Uml::Visibility::Public;
+-                    }
+-                    if (++i >= components.count())
+-                        break;
+-                    base += '-' + components[i];
+-                }
++        } else if (m_source[m_srcIndex] != "renames") {
++            kdError() << "AdaImport::parseFile: unexpected: " << m_source[m_srcIndex] << endl;
++            skipStmt("is");
++        }
++        if (m_inGenericFormalPart) {
++            // handling of generic formal parameters: TBD
++            m_inGenericFormalPart = false;
++        }
++        return true;
++    }
++    if (keyword == "type") {
++        const QString& name = advance();
++        if (advance() == "(") {
++            kdDebug() << "AdaImport::parseFile(" << name << "): "
++                << "discriminant handling is not yet implemented" << endl;
++            skipStmt(")");
++        }
++        if (m_source[m_srcIndex] == ";") {
++            // forward declaration
++            // To Be Done
++            return true;
++        }
++        if (m_source[m_srcIndex] != "is") {
++            kdError() << "AdaImport::parseFile: expecting \"is\"" << endl;
++            return false;
++        }
++        if (advance() == "(") {
++            // enum type
++            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
++                            name, m_scope[m_scopeIndex], m_comment);
++            UMLEnum *enumType = static_cast<UMLEnum*>(ns);
++            while (++m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
++                Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
+                 if (advance() != ",")
+                     break;
+             }
+-            continue;
++            skipStmt();
++            return true;
+         }
+-        if (keyword == "generic") {
+-            inGenericFormalPart = true;
+-            continue;
++        bool isTaggedType = false;
++        if (m_source[m_srcIndex] == "abstract") {
++            m_isAbstract = true;
++            m_srcIndex++;
+         }
+-        if (keyword == "package") {
+-            const QString& name = advance();
+-            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
++        if (m_source[m_srcIndex] == "tagged") {
++            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+                             name, m_scope[m_scopeIndex], m_comment);
+-            if (advance() == "is") {
+-                if (m_source[m_srcIndex + 1] == "new") {
+-                    // generic package instantiation: TBD
+-                    skipStmt();
+-                } else {
+-                    m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+-                }
+-            } else if (m_source[m_srcIndex] != "renames") {
+-                kdError() << "AdaImport::parseFile: unexpected: " << m_source[m_srcIndex] << endl;
+-                skipStmt("is");
+-            }
+-            if (inGenericFormalPart) {
+-                // handling of generic formal parameters: TBD
+-                inGenericFormalPart = false;
+-            }
++            ns->setAbstract(m_isAbstract);
++            m_isAbstract = false;
+             m_comment = QString::null;
+-            continue;
++            m_srcIndex++;
++            isTaggedType = true;
+         }
+-        if (keyword == "type") {
+-            const QString& name = advance();
+-            if (advance() == "(") {
+-                kdDebug() << "AdaImport::parseFile(" << name << "): "
+-                    << "discriminant handling is not yet implemented" << endl;
+-                skipStmt(")");
+-            }
+-            if (m_source[m_srcIndex] == ";") {
+-                // forward declaration
+-                // To Be Done
+-                continue;
+-            }
+-            if (m_source[m_srcIndex] != "is") {
+-                kdError() << "AdaImport::parseFile: expecting \"is\"" << endl;
+-                skipStmt();
+-                continue;
+-            }
+-            if (advance() == "(") {
+-                // enum type
+-                UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+-                                name, m_scope[m_scopeIndex], m_comment);
+-                UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+-                while (++m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+-                    Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
+-                    if (advance() != ",")
+-                        break;
+-                }
+-                skipStmt();
+-                m_comment = QString::null;
+-                continue;
+-            }
+-            bool isTaggedType = false;
+-            if (m_source[m_srcIndex] == "abstract") {
+-                m_isAbstract = true;
+-                m_srcIndex++;
+-            }
+-            if (m_source[m_srcIndex] == "tagged") {
++        if (m_source[m_srcIndex] == "limited") {
++            m_srcIndex++;  // we can't (yet?) represent that
++        }
++        if (m_source[m_srcIndex] == "private" ||
++            (m_source[m_srcIndex] == "null" &&
++             m_source[m_srcIndex+1] == "record")) {
++            skipStmt();
++            return true;
++        }
++        if (m_source[m_srcIndex] == "record") {
++            // If it's a tagged record then the class was already created
++            // above (see processing for "tagged".) Doesn't matter;
++            // in that case Import_Utils::createUMLObject() just returns
++            // the existing class instead of creating a new one.
++            UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
++                            name, m_scope[m_scopeIndex], m_comment);
++            if (! isTaggedType)
++                ns->setStereotype("record");
++            m_klass = static_cast<UMLClassifier*>(ns);
++            return true;
++        }
++        if (m_source[m_srcIndex] == "new") {
++            QString base = advance();
++            UMLClassifier *parent = NULL;
++            if (advance() == "with") {
+                 UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+-                                name, m_scope[m_scopeIndex], m_comment);
+-                ns->setAbstract(m_isAbstract);
+-                m_isAbstract = false;
++                                base, NULL);
++                parent = static_cast<UMLClassifier*>(ns);
++                ns = Import_Utils::createUMLObject(Uml::ot_Class, name,
++                                       m_scope[m_scopeIndex], m_comment);
+                 m_comment = QString::null;
+-                m_srcIndex++;
+-                isTaggedType = true;
+-            }
+-            if (m_source[m_srcIndex] == "limited") {
+-                m_srcIndex++;  // we can't (yet?) represent that
+-            }
+-            if (m_source[m_srcIndex] == "private" ||
+-                (m_source[m_srcIndex] == "null" &&
+-                 m_source[m_srcIndex+1] == "record")) {
+-                skipStmt();
+-                continue;
+-            }
+-            if (m_source[m_srcIndex] == "record") {
+-                // If it's a tagged record then the class was already created
+-                // above (see processing for "tagged".) Doesn't matter;
+-                // in that case Import_Utils::createUMLObject() just returns
+-                // the existing class instead of creating a new one.
+-                UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+-                                name, m_scope[m_scopeIndex], m_comment);
+-                if (! isTaggedType)
+-                    ns->setStereotype("record");
+-                m_klass = static_cast<UMLClassifier*>(ns);
+-                m_comment = QString::null;
+-                continue;
+-            }
+-            if (m_source[m_srcIndex] == "new") {
+-                QString base = advance();
+-                UMLClassifier *parent = NULL;
+-                if (advance() == "with") {
+-                    UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+-                                    base, NULL);
+-                    parent = static_cast<UMLClassifier*>(ns);
+-                    ns = Import_Utils::createUMLObject(Uml::ot_Class, name,
+-                                           m_scope[m_scopeIndex], m_comment);
+-                    m_comment = QString::null;
+-                    QString nextLexeme = advance();
+-                    if (nextLexeme == "null" || nextLexeme == "record") {
+-                        UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
+-                        Import_Utils::createGeneralization(klass, parent);
+-                        if (nextLexeme == "record") {
+-                            // Set the m_klass for attributes.
+-                            m_klass = klass;
+-                            continue;
+-                        }
++                QString nextLexeme = advance();
++                if (nextLexeme == "null" || nextLexeme == "record") {
++                    UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
++                    Import_Utils::createGeneralization(klass, parent);
++                    if (nextLexeme == "record") {
++                        // Set the m_klass for attributes.
++                        m_klass = klass;
++                        return true;
+                     }
+                 }
+             }
+-            // Datatypes: TO BE DONE
+-            skipStmt();
+-            m_comment = QString::null;
+-            continue;
+         }
+-        if (keyword == "private") {
+-            m_currentAccess = Uml::Visibility::Private;
+-            continue;
+-        }
+-        if (keyword == "end") {
+-            if (m_klass) {
+-                if (advance() != "record") {
+-                    kdError() << "end: expecting \"record\" at "
++        // Datatypes: TO BE DONE
++        return false;
++    }
++    if (keyword == "private") {
++        m_currentAccess = Uml::Visibility::Private;
++        return true;
++    }
++    if (keyword == "end") {
++        if (m_klass) {
++            if (advance() != "record") {
++                kdError() << "end: expecting \"record\" at "
++                          << m_source[m_srcIndex] << endl;
++            }
++            m_klass = NULL;
++        } else if (m_scopeIndex) {
++            if (advance() != ";") {
++                const QString& scopeName = m_scope[m_scopeIndex]->getName();
++                if (scopeName != m_source[m_srcIndex])
++                    kdError() << "end: expecting " << scopeName << ", found "
+                               << m_source[m_srcIndex] << endl;
+-                }
+-                m_klass = NULL;
+-            } else if (m_scopeIndex) {
+-                if (advance() != ";") {
+-                    const QString& scopeName = m_scope[m_scopeIndex]->getName();
+-                    if (scopeName != m_source[m_srcIndex])
+-                        kdError() << "end: expecting " << scopeName << ", found "
+-                                  << m_source[m_srcIndex] << endl;
+-                }
+-                m_scopeIndex--;
+-                m_currentAccess = Uml::Visibility::Public;   // @todo make a stack for this
+-            } else {
+-                kdError() << "importAda: too many \"end\"" << endl;
+             }
++            m_scopeIndex--;
++            m_currentAccess = Uml::Visibility::Public;   // @todo make a stack for this
++        } else {
++            kdError() << "importAda: too many \"end\"" << endl;
++        }
++        skipStmt();
++        return true;
++    }
++    if (keyword == "function" || keyword == "procedure") {
++        const QString& name = advance();
++        QString returnType;
++        if (advance() != "(") {
++            // Unlike an Ada package, a UML package does not support
++            // subprograms.
++            // In order to map those, we would need to create a UML
++            // class with stereotype <<utility>> for the Ada package.
++            kdDebug() << "ignoring parameterless " << keyword << " " << name << endl;
+             skipStmt();
+-            continue;
++            return true;
+         }
+-        if (keyword == "function" || keyword == "procedure") {
+-            const QString& name = advance();
+-            QString returnType;
+-            if (advance() != "(") {
+-                // Unlike an Ada package, a UML package does not support
+-                // subprograms.
+-                // In order to map those, we would need to create a UML
+-                // class with stereotype <<utility>> for the Ada package.
+-                kdDebug() << "ignoring parameterless " << keyword << " " << name << endl;
++        UMLClassifier *klass = NULL;
++        UMLOperation *op = NULL;
++        const uint MAX_PARNAMES = 16;
++        while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
++            QString parName[MAX_PARNAMES];
++            uint parNameCount = 0;
++            do {
++                if (parNameCount >= MAX_PARNAMES) {
++                    kdError() << "MAX_PARNAMES is exceeded at " << name << endl;
++                    break;
++                }
++                parName[parNameCount++] = advance();
++            } while (advance() == ",");
++            if (m_source[m_srcIndex] != ":") {
++                kdError() << "importAda: expecting ':'" << endl;
+                 skipStmt();
+-                continue;
++                break;
+             }
+-            UMLClassifier *klass = NULL;
+-            UMLOperation *op = NULL;
+-            const uint MAX_PARNAMES = 16;
+-            while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+-                QString parName[MAX_PARNAMES];
+-                uint parNameCount = 0;
+-                do {
+-                    if (parNameCount >= MAX_PARNAMES) {
+-                        kdError() << "MAX_PARNAMES is exceeded at " << name << endl;
+-                        break;
+-                    }
+-                    parName[parNameCount++] = advance();
+-                } while (advance() == ",");
+-                if (m_source[m_srcIndex] != ":") {
+-                    kdError() << "importAda: expecting ':'" << endl;
++            const QString &direction = advance();
++            QString typeName;
++            Uml::Parameter_Direction dir = Uml::pd_In;
++            if (direction == "access") {
++                // Oops, we have to improvise here because there
++                // is no such thing as "access" in UML.
++                // So we use the next best thing, "inout".
++                // Better ideas, anyone?
++                dir = Uml::pd_InOut;
++                typeName = advance();
++            } else if (direction == "in") {
++                if (m_source[m_srcIndex + 1] == "out") {
++                    dir = Uml::pd_InOut;
++                    m_srcIndex++;
++                }
++                typeName = advance();
++            } else if (direction == "out") {
++                dir = Uml::pd_Out;
++                typeName = advance();
++            } else {
++                typeName = direction;  // In Ada, the default direction is "in"
++            }
++            if (op == NULL) {
++                // In Ada, the first parameter indicates the class.
++                UMLDoc *umldoc = UMLApp::app()->getDocument();
++                UMLObject *type = umldoc->findUMLObject(typeName, Uml::ot_Class, m_scope[m_scopeIndex]);
++                if (type == NULL) {
++                    kdError() << "importAda: cannot find UML object for " << typeName << endl;
+                     skipStmt();
+                     break;
+-                }
+-                const QString &direction = advance();
+-                QString typeName;
+-                Uml::Parameter_Direction dir = Uml::pd_In;
+-                if (direction == "access") {
+-                    // Oops, we have to improvise here because there
+-                    // is no such thing as "access" in UML.
+-                    // So we use the next best thing, "inout".
+-                    // Better ideas, anyone?
+-                    dir = Uml::pd_InOut;
+-                    typeName = advance();
+-                } else if (direction == "in") {
+-                    if (m_source[m_srcIndex + 1] == "out") {
+-                        dir = Uml::pd_InOut;
++                    /*** better:
++                    if (advance() == ";") {
+                         m_srcIndex++;
+-                    }
+-                    typeName = advance();
+-                } else if (direction == "out") {
+-                    dir = Uml::pd_Out;
+-                    typeName = advance();
+-                } else {
+-                    typeName = direction;  // In Ada, the default direction is "in"
+-                }
+-                if (op == NULL) {
+-                    // In Ada, the first parameter indicates the class.
+-                    UMLDoc *umldoc = UMLApp::app()->getDocument();
+-                    UMLObject *type = umldoc->findUMLObject(typeName, Uml::ot_Class, m_scope[m_scopeIndex]);
+-                    if (type == NULL) {
+-                        kdError() << "importAda: cannot find UML object for " << typeName << endl;
+-                        skipStmt();
++                        continue;
++                    } else {
+                         break;
+-                        /*** better:
+-                        if (advance() == ";") {
+-                            m_srcIndex++;
+-                            continue;
+-                        } else {
+-                            break;
+-                        }
+-                         ****/
+                     }
+-                    Uml::Object_Type t = type->getBaseType();
+-                    if (t != Uml::ot_Interface &&
+-                        (t != Uml::ot_Class || type->getStereotype() == "record")) {
+-                        // Not an instance bound method - we cannot represent it.
+-                        skipStmt(")");
+-                        break;
+-                    }
+-                    klass = static_cast<UMLClassifier*>(type);
+-                    op = Import_Utils::makeOperation(klass, name);
+-                    // The controlling parameter is suppressed.
+-                    parNameCount--;
+-                    if (parNameCount) {
+-                        for (uint i = 0; i < parNameCount; i++)
+-                            parName[i] = parName[i + 1];
+-                    }
++                     ****/
+                 }
+-                for (uint i = 0; i < parNameCount; i++) {
+-                    UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName[i]);
+-                    att->setParmKind(dir);
+-                }
+-                if (advance() != ";")
++                Uml::Object_Type t = type->getBaseType();
++                if (t != Uml::ot_Interface &&
++                    (t != Uml::ot_Class || type->getStereotype() == "record")) {
++                    // Not an instance bound method - we cannot represent it.
++                    skipStmt(")");
+                     break;
+-            }
+-            if (keyword == "function") {
+-                if (advance() != "return") {
+-                    if (klass)
+-                        kdError() << "importAda: expecting \"return\" at function "
+-                            << name << endl;
+-                    skipStmt();
+-                    continue;
+                 }
+-                returnType = advance();
++                klass = static_cast<UMLClassifier*>(type);
++                op = Import_Utils::makeOperation(klass, name);
++                // The controlling parameter is suppressed.
++                parNameCount--;
++                if (parNameCount) {
++                    for (uint i = 0; i < parNameCount; i++)
++                        parName[i] = parName[i + 1];
++                }
+             }
+-            bool isAbstract = false;
+-            if (advance() == "is" && advance() == "abstract")
+-                isAbstract = true;
+-            if (klass != NULL && op != NULL)
+-                Import_Utils::insertMethod(klass, op, m_currentAccess, returnType,
+-                                           false, isAbstract, false, false, m_comment);
+-            m_comment = QString::null;
+-            skipStmt();
+-            continue;
+-        }
+-        if (keyword == "subtype") {    // FIXMEnow: potentially important but not yet implemented
+-            m_comment = QString::null;
+-            skipStmt();
+-            continue;
+-        }
+-        if (keyword == "task" || keyword == "protected") {
+-            // Can task and protected objects/types be mapped to UML?
+-            bool isType = false;
+-            QString name = advance();
+-            if (name == "type") {
+-                isType = true;
+-                name = advance();
++            for (uint i = 0; i < parNameCount; i++) {
++                UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName[i]);
++                att->setParmKind(dir);
+             }
+-            QString next = advance();
+-            if (next == "(") {
+-                skipStmt(")");  // skip discriminant
+-                next = advance();
+-            }
+-            if (next == "is")
+-                skipStmt("end");
+-            skipStmt();
+-            m_comment = QString::null;
+-            continue;
++            if (advance() != ";")
++                break;
+         }
+-        if (keyword == "for") {    // rep spec (yuck)
+-            QString typeName = advance();
+-            QString next = advance();
+-            if (next == "'") {
+-                advance();  // skip qualifier
+-                next = advance();
++        if (keyword == "function") {
++            if (advance() != "return") {
++                if (klass)
++                    kdError() << "importAda: expecting \"return\" at function "
++                        << name << endl;
++                return false;
+             }
+-            if (next == "use") {
+-                if (advance() == "record")
+-                    skipStmt("end");
+-            } else {
+-                kdError() << "importAda: expecting \"use\" at rep spec of "
+-                          << typeName << endl;
+-            }
+-            m_comment = QString::null;
+-            skipStmt();
+-            continue;
++            returnType = advance();
+         }
+-        // At this point we're only interested in attribute declarations.
+-        if (m_klass == NULL || keyword == "null") {
+-            skipStmt();
+-            m_comment = QString::null;
+-            continue;
++        bool isAbstract = false;
++        if (advance() == "is" && advance() == "abstract")
++            isAbstract = true;
++        if (klass != NULL && op != NULL)
++            Import_Utils::insertMethod(klass, op, m_currentAccess, returnType,
++                                       false, isAbstract, false, false, m_comment);
++        return true;
++    }
++    if (keyword == "subtype") {    // FIXMEnow: potentially important but not yet implemented
++        skipStmt();
++        return true;
++    }
++    if (keyword == "task" || keyword == "protected") {
++        // Can task and protected objects/types be mapped to UML?
++        bool isType = false;
++        QString name = advance();
++        if (name == "type") {
++            isType = true;
++            name = advance();
+         }
+-        const QString& name = keyword;
+-        if (advance() != ":") {
+-            kdError() << "adaImport: expecting \":\" at " << name << " "
+-                      << m_source[m_srcIndex] << endl;
+-            skipStmt();
+-            continue;
++        QString next = advance();
++        if (next == "(") {
++            skipStmt(")");  // skip discriminant
++            next = advance();
+         }
++        if (next == "is")
++            skipStmt("end");
++        skipStmt();
++        return true;
++    }
++    if (keyword == "for") {    // rep spec (yuck)
+         QString typeName = advance();
+-        QString initialValue;
+-        if (advance() == ":=") {
+-            QString expr = advance();
+-            QString token;
+-            while ((token = advance()) != ";") {
+-                expr.append(" " + token);
+-            }
++        QString next = advance();
++        if (next == "'") {
++            advance();  // skip qualifier
++            next = advance();
+         }
+-        UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+-                                                     typeName, m_comment);
+-        UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+-        attr->setInitialValue(initialValue);
+-        m_comment = QString::null;
++        if (next == "use") {
++            if (advance() == "record")
++                skipStmt("end");
++        } else {
++            kdError() << "importAda: expecting \"use\" at rep spec of "
++                      << typeName << endl;
++        }
+         skipStmt();
++        return true;
+     }
++    // At this point we're only interested in attribute declarations.
++    if (m_klass == NULL || keyword == "null") {
++        skipStmt();
++        return true;
++    }
++    const QString& name = keyword;
++    if (advance() != ":") {
++        kdError() << "adaImport: expecting \":\" at " << name << " "
++                  << m_source[m_srcIndex] << endl;
++        skipStmt();
++        return true;
++    }
++    QString typeName = advance();
++    QString initialValue;
++    if (advance() == ":=") {
++        QString expr = advance();
++        QString token;
++        while ((token = advance()) != ";") {
++            expr.append(" " + token);
++        }
++    }
++    UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
++                                                 typeName, m_comment);
++    UMLAttribute *attr = static_cast<UMLAttribute*>(o);
++    attr->setInitialValue(initialValue);
++    skipStmt();
++    return true;
+ }
+ 
+ 
+--- umbrello/umbrello/codegenerators/aswriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/aswriter.h	(revision 497528)
+@@ -29,7 +29,7 @@
+     Q_OBJECT
+ public:
+ 
+-    ASWriter( UMLDoc* parent, const char* name = 0 );
++    ASWriter();
+     virtual ~ASWriter();
+ 
+     /**
+@@ -39,16 +39,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "ASWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "ActionScript"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/idlwriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/idlwriter.h	(revision 497528)
+@@ -32,7 +32,7 @@
+ class IDLWriter : public SimpleCodeGenerator {
+ public:
+ 
+-    IDLWriter (UMLDoc * parent, const char* name = 0);
++    IDLWriter ();
+     virtual ~IDLWriter ();
+ 
+     /**
+@@ -42,18 +42,11 @@
+     virtual void writeClass (UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "IDLWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "IDL"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+-    void createDefaultDatatypes();
++    QStringList defaultDatatypes();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/php5writer.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/php5writer.h	(revision 497528)
+@@ -32,7 +32,7 @@
+     Q_OBJECT
+ public:
+ 
+-    Php5Writer( UMLDoc * parent, const char* name = 0 );
++    Php5Writer();
+     virtual ~Php5Writer();
+ 
+     /**
+@@ -42,16 +42,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "PhpWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "PHP"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/pythonwriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/pythonwriter.h	(revision 497528)
+@@ -30,7 +30,7 @@
+     Q_OBJECT
+ public:
+ 
+-    PythonWriter( UMLDoc * parent, const char* name = 0 );
++    PythonWriter();
+     virtual ~PythonWriter();
+ 
+     /**
+@@ -40,16 +40,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "PythonWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "Python"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/rubycodegenerator.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/rubycodegenerator.cpp	(revision 497528)
+@@ -29,15 +29,13 @@
+ // Constructors/Destructors
+ //
+ 
+-RubyCodeGenerator::RubyCodeGenerator ( UMLDoc * parentDoc , const char * name, QDomElement & elem )
+-        : CodeGenerator ( parentDoc , name)
++RubyCodeGenerator::RubyCodeGenerator (QDomElement & elem )
+ {
+     initFields();
+     loadFromXMI(elem);
+ }
+ 
+-RubyCodeGenerator::RubyCodeGenerator ( UMLDoc * parentDoc, const char * name )
+-        : CodeGenerator ( parentDoc , name)
++RubyCodeGenerator::RubyCodeGenerator ()
+ {
+     initFields();
+ }
+@@ -52,8 +50,8 @@
+ //
+ 
+ // return our language
+-QString RubyCodeGenerator::getLanguage() {
+-    return "Ruby";
++Uml::Programming_Language RubyCodeGenerator::getLanguage() {
++    return Uml::pl_Ruby;
+ }
+ 
+ // In the Java version, we make the ANT build file also available.
+@@ -169,9 +167,6 @@
+     initFromParentDocument();
+ }
+ 
+-void RubyCodeGenerator::createDefaultDatatypes() {
+-}
+-
+ const QStringList RubyCodeGenerator::reservedKeywords() const {
+ 
+     static QStringList keywords;
+--- umbrello/umbrello/codegenerators/rubywriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/rubywriter.h	(revision 497528)
+@@ -33,7 +33,7 @@
+     Q_OBJECT
+ public:
+ 
+-    RubyWriter( UMLDoc * parent, const char* name = 0 );
++    RubyWriter();
+     virtual ~RubyWriter();
+ 
+     /**
+@@ -43,16 +43,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "RubyWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "Ruby"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/cppwriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/cppwriter.h	(revision 497528)
+@@ -40,7 +40,7 @@
+     /**
+      * Constructor, initialises a couple of variables
+      */
+-    CppWriter(UMLDoc* parent = 0, const char* name = 0);
++    CppWriter();
+ 
+     /**
+      * Destructor, empty
+@@ -54,21 +54,14 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "CppWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "C++"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * Add C++ primitives as datatypes
+      */
+-    void createDefaultDatatypes();
++    QStringList defaultDatatypes();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/codegen_utils.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/codegen_utils.cpp	(revision 497528)
+@@ -16,16 +16,20 @@
+ 
+ namespace Codegen_Utils {
+ 
+-void createCppDatatypes() {
+-    UMLDoc *umldoc = UMLApp::app()->getDocument();
+-    umldoc->createDatatype("int");
+-    umldoc->createDatatype("char");
+-    umldoc->createDatatype("bool");
+-    umldoc->createDatatype("float");
+-    umldoc->createDatatype("double");
+-    umldoc->createDatatype("long");
+-    umldoc->createDatatype("short");
+-    umldoc->createDatatype("string");
++QStringList cppDatatypes() {
++    QStringList l;
++    l.append("int");
++    l.append("char");
++    l.append("bool");
++    l.append("float");
++    l.append("double");
++    l.append("short");
++    l.append("long");
++    l.append("unsigned int");
++    l.append("unsigned short");
++    l.append("unsigned long");
++    l.append("string");
++    return l;
+ }
+ 
+ const QStringList reservedCppKeywords() {
+--- umbrello/umbrello/codegenerators/codegenfactory.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/codegenfactory.cpp	(revision 497528)
+@@ -51,119 +51,69 @@
+ CodeGeneratorFactory::~CodeGeneratorFactory() {
+ }
+ 
+-QStringList CodeGeneratorFactory::languagesAvailable() {
+-    kdDebug()<<"Querying languages available"<<endl;
+-
+-    QStringList l;
+-    l.append("ActionScript");
+-    l.append("Ada");
+-    l.append("Cpp");
+-    //  l.append("C#");
+-    l.append("IDL");
+-    l.append("Java");
+-    l.append("JavaScript");
+-    l.append("Perl");
+-    l.append("PHP");
+-    l.append("PHP5");
+-    l.append("Python");
+-    l.append("Ruby");
+-    l.append("SQL");
+-    l.append("Tcl");
+-    l.append("XMLSchema");
+-    return l;
+-}
+-
+-QString CodeGeneratorFactory::generatorName(const QString &l) {
+-    kdDebug()<<"Looking up generator for language "<<l<<endl;
+-    if (l=="Java")
+-        return "JavaCodeGenerator";
+-    if (l=="Cpp")
+-        return "CppCodeGenerator";
+-    if (l == "Ada")
+-        return "AdaWriter";
+-    if (l == "ActionScript")
+-        return "ASWriter";
+-    /*
+-        if (l=="C#")
+-                return "C#Writer";
+-    */
+-    if (l=="IDL")
+-        return "IDLWriter";
+-    if (l == "JavaScript")
+-        return "JSWriter";
+-    if (l == "PHP")
+-        return "PHPWriter";
+-    if (l == "PHP5")
+-        return "PHP5Writer";
+-    if (l == "Perl")
+-        return "PerlWriter";
+-    if (l == "Python")
+-        return "PythonWriter";
+-    if (l == "Ruby")
+-        return "RubyWriter";
+-    if (l == "SQL")
+-        return "SQLWriter";
+-    if (l == "Tcl")
+-        return "TclWriter";
+-    if (l == "XMLSchema")
+-        return "XMLSchemaWriter";
+-    //else...
+-    kdDebug()<<"CodeGeneratorFactory::Error: no generator for language "<<l<<endl;
+-    return "";
+-}
+-
+-CodeGenerator* CodeGeneratorFactory::createObject(UMLDoc* doc, const char* name)  {
++CodeGenerator* CodeGeneratorFactory::createObject(Uml::Programming_Language pl)  {
+     CodeGenerator* obj = 0;
+-    QString cname(name);
+-
+-    if (doc) {
+-        Settings::OptionState optionState = UMLApp::app()->getOptionState();
+-        if (cname == "AdaWriter") {
+-            obj = new AdaWriter(doc, name);
+-        } else if(cname == "ASWriter") {
+-            obj = new ASWriter( doc, name );
+-        } else if(cname == "CppCodeGenerator") {
++    Settings::OptionState optionState = UMLApp::app()->getOptionState();
++    switch (pl) {
++        case Uml::pl_Ada:
++            obj = new AdaWriter();
++            break;
++        case Uml::pl_ActionScript:
++            obj = new ASWriter();
++            break;
++        case Uml::pl_Cpp:
+             if (optionState.generalState.newcodegen)
+-                obj = new CPPCodeGenerator(doc, name);
++                obj = new CPPCodeGenerator();
+             else
+-                obj = new CppWriter(doc, name);
+-            //          } else if(cname == "C#Writer") {
+-            //                  obj = new CsWriter( doc, name );
+-        } else if(cname == "IDLWriter") {
+-            obj = new IDLWriter( doc, name );
+-        } else if(cname =="JavaCodeGenerator") {
++                obj = new CppWriter();
++            break;
++        // case Uml::pl_Csharp:
++        //     obj = new CsWriter();
++        //     break;
++        case Uml::pl_IDL:
++            obj = new IDLWriter();
++            break;
++        case Uml::pl_Java:
+             if (optionState.generalState.newcodegen)
+-                obj = new JavaCodeGenerator(doc, name);
++                obj = new JavaCodeGenerator();
+             else
+-                obj = new JavaWriter(doc, name);
+-        } else if(cname == "JSWriter") {
+-            obj = new JSWriter( doc, name );
+-        } else if (cname == "PHPWriter") {
+-            obj = new PhpWriter( doc, name);
+-        } else if (cname == "PHP5Writer") {
+-            obj = new Php5Writer( doc, name);
+-        } else if (cname == "PerlWriter") {
+-            obj = new PerlWriter( doc, name);
+-        } else if (cname == "PythonWriter") {
+-            obj = new PythonWriter( doc, name);
+-        } else if (cname == "RubyWriter") {
++                obj = new JavaWriter();
++            break;
++        case Uml::pl_JavaScript:
++            obj = new JSWriter();
++            break;
++        case Uml::pl_PHP:
++            obj = new PhpWriter();
++            break;
++        case Uml::pl_PHP5:
++            obj = new Php5Writer();
++            break;
++        case Uml::pl_Perl:
++            obj = new PerlWriter();
++            break;
++        case Uml::pl_Python:
++            obj = new PythonWriter();
++            break;
++        case Uml::pl_Ruby:
+             if (optionState.generalState.newcodegen)
+-                obj = new RubyCodeGenerator(doc, name);
++                obj = new RubyCodeGenerator();
+             else
+-                obj = new RubyWriter(doc, name);
+-        } else if (cname == "SQLWriter") {
+-            obj = new SQLWriter( doc, name);
+-        } else if (cname == "TclWriter") {
+-            obj = new TclWriter( doc, name);
+-        } else if (cname == "XMLSchemaWriter") {
+-            obj = new XMLSchemaWriter( doc, name);
+-        } else {
+-            kdWarning() << "cannot create object of type " << name <<
+-            ". Type unknown" << endl;
+-        }
+-
+-    } else {
+-        kdWarning() << "cannot create parent UML document" << endl;
++                obj = new RubyWriter();
++            break;
++        case Uml::pl_SQL:
++            obj = new SQLWriter();
++            break;
++        case Uml::pl_Tcl:
++            obj = new TclWriter();
++            break;
++        case Uml::pl_XMLSchema:
++            obj = new XMLSchemaWriter();
++            break;
++        default:
++            kdWarning() << "cannot create object of type " << pl
++                        << ". Type unknown" << endl;
++            break;
+     }
++
+     return obj;
+ }
+--- umbrello/umbrello/codegenerators/sqlwriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/sqlwriter.cpp	(revision 497528)
+@@ -29,15 +29,13 @@
+ #include "../association.h"
+ #include "../attribute.h"
+ 
+-SQLWriter::SQLWriter( UMLDoc *parent, const char *name )
+-        :SimpleCodeGenerator( parent, name) {
++SQLWriter::SQLWriter() {
+ }
+ 
+ SQLWriter::~SQLWriter() {}
+ 
+ void SQLWriter::writeClass(UMLClassifier *c) {
+ 
+-
+     if(!c) {
+         kdDebug()<<"Cannot write class of NULL concept!" << endl;
+         return;
+@@ -194,22 +192,10 @@
+     return;
+ }
+ 
+-QString SQLWriter::getLanguage() {
+-    return "SQL";
++Uml::Programming_Language SQLWriter::getLanguage() {
++    return Uml::pl_SQL;
+ }
+ 
+-/**
+- * checks whether type is "SQLWriter"
+- *
+- * @param type
+- */
+-bool SQLWriter::isType (QString & type)
+-{
+-    if(type == "SQLWriter")
+-        return true;
+-    return false;
+-}
+-
+ const QStringList SQLWriter::reservedKeywords() const {
+ 
+     static QStringList keywords;
+--- umbrello/umbrello/codegenerators/idlwriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/idlwriter.cpp	(revision 497528)
+@@ -28,8 +28,7 @@
+ #include "../operation.h"
+ #include "../umlnamespace.h"
+ 
+-IDLWriter::IDLWriter(UMLDoc *parent, const char *name)
+-        : SimpleCodeGenerator(parent, name, false) {
++IDLWriter::IDLWriter() : SimpleCodeGenerator(false) {
+ }
+ 
+ IDLWriter::~IDLWriter() {}
+@@ -55,22 +54,10 @@
+ /**
+  * returns "IDL"
+  */
+-QString IDLWriter::getLanguage() {
+-    return "IDL";
++Uml::Programming_Language IDLWriter::getLanguage() {
++    return Uml::pl_IDL;
+ }
+ 
+-/**
+- * checks whether type is "IDLWriter"
+- *
+- * @param type
+- */
+-bool IDLWriter::isType (QString & type)
+-{
+-    if(type == "IDLWriter")
+-        return true;
+-    return false;
+-}
+-
+ void IDLWriter::computeAssocTypeAndRole
+ (UMLAssociation *a, UMLClassifier *c, QString& typeName, QString& roleName)
+ {
+@@ -431,17 +418,20 @@
+     idl << ");" << m_endl << m_endl;
+ }
+ 
+-void IDLWriter::createDefaultDatatypes() {
+-    m_doc->createDatatype("boolean");
+-    m_doc->createDatatype("char");
+-    m_doc->createDatatype("octet");
+-    m_doc->createDatatype("short");
+-    m_doc->createDatatype("unsigned short");
+-    m_doc->createDatatype("long");
+-    m_doc->createDatatype("unsigned long");
+-    m_doc->createDatatype("float");
+-    m_doc->createDatatype("double");
+-    m_doc->createDatatype("string");
++QStringList IDLWriter::defaultDatatypes() {
++    QStringList l;
++    l.append("boolean");
++    l.append("char");
++    l.append("octet");
++    l.append("short");
++    l.append("unsigned short");
++    l.append("long");
++    l.append("unsigned long");
++    l.append("float");
++    l.append("double");
++    l.append("string");
++    l.append("any");
++    return l;
+ }
+ 
+ const QStringList IDLWriter::reservedKeywords() const {
+--- umbrello/umbrello/codegenerators/php5writer.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/php5writer.cpp	(revision 497528)
+@@ -2988,8 +2988,7 @@
+         0
+     };
+ 
+-Php5Writer::Php5Writer( UMLDoc *parent, const char *name )
+-        :SimpleCodeGenerator( parent, name) {
++Php5Writer::Php5Writer() {
+ }
+ 
+ Php5Writer::~Php5Writer() {}
+@@ -3357,22 +3356,10 @@
+ /**
+  * returns "PHP"
+  */
+-QString Php5Writer::getLanguage() {
+-    return "PHP";
++Uml::Programming_Language Php5Writer::getLanguage() {
++    return Uml::pl_PHP;
+ }
+ 
+-/**
+- * checks whether type is "PhpWriter"
+- *
+- * @param type
+- */
+-bool Php5Writer::isType (QString & type)
+-{
+-    if(type == "PhpWriter")
+-        return true;
+-    return false;
+-}
+-
+ const QStringList Php5Writer::reservedKeywords() const {
+ 
+     static QStringList keywords;
+--- umbrello/umbrello/codegenerators/jswriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/jswriter.h	(revision 497528)
+@@ -29,7 +29,7 @@
+     Q_OBJECT
+ public:
+ 
+-    JSWriter( UMLDoc * parent, const char* name = 0 );
++    JSWriter();
+     virtual ~JSWriter();
+ 
+     /**
+@@ -39,16 +39,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "JSWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "JavaScript"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/cppwriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/cppwriter.cpp	(revision 497528)
+@@ -39,8 +39,7 @@
+ // 3-14-2003: this code developed from the javawriter with parts of the
+ // original cppwriter by Luis De la Parra Blum
+ 
+-CppWriter::CppWriter( UMLDoc *parent, const char *name )
+-        : SimpleCodeGenerator(parent, name)
++CppWriter::CppWriter()
+ {
+ 
+     // set some general parameters for how to generate code in this class
+@@ -86,17 +85,10 @@
+ 
+ CppWriter::~CppWriter() { }
+ 
+-QString CppWriter::getLanguage() {
+-    return "C++";
++Uml::Programming_Language CppWriter::getLanguage() {
++    return Uml::pl_Cpp;
+ }
+ 
+-bool CppWriter::isType (QString & type)
+-{
+-    if (type == "CppWriter")
+-        return true;
+-    return false;
+-}
+-
+ void CppWriter::writeClass(UMLClassifier *c)
+ {
+ 
+@@ -1196,6 +1188,9 @@
+         }
+         str += " )";
+ 
++        if (op->getConst())
++            str += " const";
++
+         // method body : only gets IF its not in a header
+         if (isHeaderMethod && !INLINE_OPERATION_METHODS)
+             str +=";"; // terminate now
+@@ -1287,8 +1282,8 @@
+     return fieldName;
+ }
+ 
+-void CppWriter::createDefaultDatatypes() {
+-    Codegen_Utils::createCppDatatypes();
++QStringList CppWriter::defaultDatatypes() {
++    return Codegen_Utils::cppDatatypes();
+ }
+ 
+ const QStringList CppWriter::reservedKeywords() const {
+--- umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp	(revision 497528)
+@@ -93,11 +93,15 @@
+ 
+     // if a property has a friend stereotype, the operation should
+     // not be a class name
+-    QString startText;
++    QString startText = returnType + " ";
++
+     if (!o->getStereotype().isEmpty() && o->getStereotype(false) == "friend")
+-        startText = returnType + " " + methodName + " ("+paramStr+") {";
+-    else
+-        startText = returnType + " " + className + "::" + methodName + " ("+paramStr+") {";
++        startText += className + "::";
++    startText += methodName + " ("+paramStr+")";
++    if (o->getConst())
++        startText += " const";
++    startText += " {";
++
+     setStartMethodText(startText);
+ 
+     // Only write this out if its a child of an interface OR is abstract.
+--- umbrello/umbrello/codegenerators/cppcodegenerator.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/cppcodegenerator.cpp	(revision 497528)
+@@ -35,10 +35,7 @@
+ // Constructors/Destructors
+ //
+ 
+-CPPCodeGenerator::CPPCodeGenerator ( UMLDoc * parentDoc , const char * name)
+-        : CodeGenerator( parentDoc, name ) {
+-
+-    //m_parentDoc = parentDoc; // this should be done by the call to the parent constructor?
++CPPCodeGenerator::CPPCodeGenerator () {
+     initAttributes();
+ }
+ 
+@@ -57,25 +54,13 @@
+ //
+ 
+ /**
+- * returns "Cpp"
++ * returns "C++"
+  */
+-QString CPPCodeGenerator::getLanguage() {
+-    return "Cpp";
++Uml::Programming_Language CPPCodeGenerator::getLanguage() {
++    return Uml::pl_Cpp;
+ }
+ 
+ /**
+- * checks whether type is "CPPCodeGenerator"
+- *
+- * @param type
+- */
+-bool CPPCodeGenerator::isType (QString & type)
+-{
+-    if(type == "CPPCodeGenerator")
+-        return true;
+-    return false;
+-}
+-
+-/**
+  * Set the value of m_createMakefile
+  * @param new_var the new value of m_createMakefile
+  */
+@@ -197,9 +182,8 @@
+ 
+ // special method needed so that we write out the header code documents
+ void CPPCodeGenerator::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
+-    QString langType = getLanguage();
+     QDomElement docElement = doc.createElement( "codegenerator" );
+-    docElement.setAttribute("language",langType);
++    docElement.setAttribute("language", "C++");
+ 
+     CodeDocumentList * docList = getCodeDocumentList();
+     for (CodeDocument * codeDoc = docList->first(); codeDoc; codeDoc= docList->next())
+@@ -384,8 +368,8 @@
+     initFromParentDocument();
+ }
+ 
+-void CPPCodeGenerator::createDefaultDatatypes() {
+-    Codegen_Utils::createCppDatatypes();
++QStringList CPPCodeGenerator::defaultDatatypes() {
++    return Codegen_Utils::cppDatatypes();
+ }
+ 
+ const QStringList CPPCodeGenerator::reservedKeywords() const {
+--- umbrello/umbrello/codegenerators/phpwriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/phpwriter.cpp	(revision 497528)
+@@ -2983,8 +2983,7 @@
+         0
+     };
+ 
+-PhpWriter::PhpWriter( UMLDoc *parent, const char *name )
+-        :SimpleCodeGenerator( parent, name) {
++PhpWriter::PhpWriter() {
+ }
+ 
+ PhpWriter::~PhpWriter() {}
+@@ -3314,22 +3313,10 @@
+ /**
+  * returns "PHP"
+  */
+-QString PhpWriter::getLanguage() {
+-    return "PHP";
++Uml::Programming_Language PhpWriter::getLanguage() {
++    return Uml::pl_PHP;
+ }
+ 
+-/**
+- * checks whether type is "PhpWriter"
+- *
+- * @param type
+- */
+-bool PhpWriter::isType (QString & type)
+-{
+-    if(type == "PhpWriter")
+-        return true;
+-    return false;
+-}
+-
+ const QStringList PhpWriter::reservedKeywords() const {
+ 
+     static QStringList keywords;
+--- umbrello/umbrello/codegenerators/tclwriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/tclwriter.h	(revision 497528)
+@@ -42,7 +42,7 @@
+     /**
+      * Constructor, initialises a couple of variables
+      */
+-    TclWriter(UMLDoc * parent = 0, const char *name = 0);
++    TclWriter();
+ 
+     /**
+      * Destructor, empty
+@@ -56,18 +56,11 @@
+     virtual void    writeClass(UMLClassifier * c);
+ 
+     /**
+-     * checks whether type is "TclWriter"
+-     *
+-     * @param type
++     * returns "Tcl"
+      */
+-    virtual bool    isType(QString & type);
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+-     * returns "C++"
+-     */
+-    virtual QString getLanguage();
+-
+-    /**
+      * get list of reserved keywords
+      */
+     virtual const QStringList reservedKeywords() const;
+--- umbrello/umbrello/codegenerators/codegen_utils.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/codegen_utils.h	(revision 497528)
+@@ -16,9 +16,9 @@
+ namespace Codegen_Utils {
+ 
+ /**
+- * Add C++ primitives as datatypes
++ * Return list of C++ datatypes
+  */
+-void createCppDatatypes();
++QStringList cppDatatypes();
+ 
+ /**
+  * Get list of C++ reserved keywords
+--- umbrello/umbrello/codegenerators/simplecodegenerator.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/simplecodegenerator.h	(revision 497528)
+@@ -46,8 +46,7 @@
+     /**
+      * Empty Constructor
+      */
+-    SimpleCodeGenerator (UMLDoc * doc, const char * name = 0,
+-                         bool createDirHierarchyForPackages = true);
++    SimpleCodeGenerator (bool createDirHierarchyForPackages = true);
+ 
+     /**
+      * Empty Destructor
+@@ -57,9 +56,6 @@
+     // Public attribute accessor methods
+     //
+ 
+-    virtual bool isType (QString & type) = 0;
+-    virtual QString getLanguage() = 0;
+-
+     void writeCodeToFile ( UMLClassifierList & concepts);
+     void writeCodeToFile ( );
+ 
+--- umbrello/umbrello/codegenerators/codegenfactory.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/codegenfactory.h	(revision 497528)
+@@ -10,12 +10,9 @@
+ #ifndef CODEGENFACTORY_H
+ #define CODEGENFACTORY_H
+ 
+-#include <qstring.h>
+-#include <qstringlist.h>
+-#include <qobject.h>
++#include "../umlnamespace.h"
+ 
+ class CodeGenerator;
+-class UMLDoc;
+ 
+ /**
+  * CodeGeneratorFactory lists gives access to the available code generators, their names 
+@@ -30,18 +27,7 @@
+     CodeGeneratorFactory();
+     virtual ~CodeGeneratorFactory();
+ 
+-    /**
+-     * Returns a QStringList containing the languages offered by this library
+-     */
+-    QStringList languagesAvailable();
+-
+-    /**
+-     * Returns the name of the generator which implements language l
+-     */
+-    QString generatorName(const QString &l);
+-
+-    //FIXMEnow        virtual QObject* createObject(QObject* parent, const char* name);
+-    CodeGenerator* createObject(UMLDoc* parent, const char* name);
++    CodeGenerator* createObject(Uml::Programming_Language pl);
+ };
+ 
+ #endif //CODEGENFACTORY_H
+--- umbrello/umbrello/codegenerators/sqlwriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/sqlwriter.h	(revision 497528)
+@@ -31,7 +31,7 @@
+     Q_OBJECT
+ public:
+ 
+-    SQLWriter( UMLDoc * parent, const char* name = 0 );
++    SQLWriter();
+     virtual ~SQLWriter();
+ 
+     /**
+@@ -41,16 +41,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "SQLWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "SQL"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/perlwriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/perlwriter.h	(revision 497528)
+@@ -34,7 +34,7 @@
+     Q_OBJECT
+ public:
+ 
+-    PerlWriter( UMLDoc *doc, const char* name = 0 );
++    PerlWriter();
+     virtual ~PerlWriter();
+ 
+     /**
+@@ -44,23 +44,16 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "PerlWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "Perl"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+      */
+     virtual const QStringList reservedKeywords() const;
+ 
+-    void createDefaultDatatypes();
++    QStringList defaultDatatypes();
+ 
+ private:
+ 
+--- umbrello/umbrello/codegenerators/jswriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/jswriter.cpp	(revision 497528)
+@@ -25,8 +25,7 @@
+ #include <qregexp.h>
+ #include <qtextstream.h>
+ 
+-JSWriter::JSWriter( UMLDoc *parent, const char *name )
+-        :SimpleCodeGenerator( parent, name) {
++JSWriter::JSWriter() {
+ }
+ 
+ JSWriter::~JSWriter() {}
+@@ -245,22 +244,10 @@
+ /**
+  * returns "JavaScript"
+  */
+-QString JSWriter::getLanguage() {
+-    return "JavaScript";
++Uml::Programming_Language JSWriter::getLanguage() {
++    return Uml::pl_JavaScript;
+ }
+ 
+-/**
+- * checks whether type is "JSWriter"
+- *
+- * @param type
+- */
+-bool JSWriter::isType (QString & type)
+-{
+-    if(type == "JSWriter")
+-        return true;
+-    return false;
+-}
+-
+ const QStringList JSWriter::reservedKeywords() const {
+ 
+     static QStringList keywords;
+--- umbrello/umbrello/codegenerators/javawriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/javawriter.cpp	(revision 497528)
+@@ -32,23 +32,16 @@
+ #include "../attribute.h"
+ #include "../association.h"
+ 
+-JavaWriter::JavaWriter( UMLDoc *parent, const char *name ) : SimpleCodeGenerator(parent, name) {
++JavaWriter::JavaWriter() {
+     startline = m_endl + m_indentation;
+ }
+ 
+ JavaWriter::~JavaWriter() {}
+ 
+-QString JavaWriter::getLanguage() {
+-    return "Java";
++Uml::Programming_Language JavaWriter::getLanguage() {
++    return Uml::pl_Java;
+ }
+ 
+-bool JavaWriter::isType (QString & type)
+-{
+-    if (type == "JavaCodeGenerator")
+-        return true;
+-    return false;
+-}
+-
+ void JavaWriter::writeClass(UMLClassifier *c)
+ {
+ 
+--- umbrello/umbrello/codegenerators/xmlschemawriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/xmlschemawriter.cpp	(revision 497528)
+@@ -27,8 +27,7 @@
+ #include "../umlnamespace.h"
+ 
+ // Constructor
+-XMLSchemaWriter::XMLSchemaWriter( UMLDoc *doc, const char *name )
+-        : SimpleCodeGenerator ( doc, name )
++XMLSchemaWriter::XMLSchemaWriter()
+ {
+ 
+     packageNamespaceTag = "tns";
+@@ -44,22 +43,10 @@
+ /**
+  * returns "XMLSchema"
+  */
+-QString XMLSchemaWriter::getLanguage() {
+-    return "XMLSchema";
++Uml::Programming_Language XMLSchemaWriter::getLanguage() {
++    return Uml::pl_XMLSchema;
+ }
+ 
+-/**
+- * checks whether type is "XMLSchemaWriter"
+- *
+- * @param type
+- */
+-bool XMLSchemaWriter::isType (QString & type)
+-{
+-    if(type == "XMLSchemaWriter")
+-        return true;
+-    return false;
+-}
+-
+ // main method for invoking..
+ void XMLSchemaWriter::writeClass(UMLClassifier *c)
+ {
+--- umbrello/umbrello/codegenerators/tclwriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/tclwriter.cpp	(revision 497528)
+@@ -77,8 +77,7 @@
+                                  0
+                              };
+ 
+-TclWriter::TclWriter(UMLDoc * parent, const char *name)
+-        : SimpleCodeGenerator(parent, name)
++TclWriter::TclWriter()
+ {
+ }
+ 
+@@ -86,20 +85,12 @@
+ {
+ }
+ 
+-QString
++Uml::Programming_Language
+ TclWriter::getLanguage()
+ {
+-    return "Tcl";
++    return Uml::pl_Tcl;
+ }
+ 
+-bool
+-TclWriter::isType(QString & type)
+-{
+-    if (type == "TclWriter")
+-        return true;
+-    return false;
+-}
+-
+ void
+ TclWriter::writeClass(UMLClassifier * c)
+ {
+--- umbrello/umbrello/codegenerators/adawriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/adawriter.cpp	(revision 497528)
+@@ -37,8 +37,7 @@
+ 
+ const QString AdaWriter::defaultPackageSuffix = "_Holder";
+ 
+-AdaWriter::AdaWriter(UMLDoc *parent, const char *name)
+-        : SimpleCodeGenerator(parent, name) {
++AdaWriter::AdaWriter() {
+ }
+ 
+ AdaWriter::~AdaWriter() {}
+@@ -46,23 +45,11 @@
+ /**
+  * returns "Ada"
+  */
+-QString AdaWriter::getLanguage() {
+-    return "Ada";
++Uml::Programming_Language AdaWriter::getLanguage() {
++    return Uml::pl_Ada;
+ }
+ 
+-/**
+- * checks whether type is "AdaWriter"
+- *
+- * @param type
+- */
+-bool AdaWriter::isType (QString & type)
+-{
+-    if(type == "AdaWriter")
+-        return true;
+-    return false;
+-}
+ 
+-
+ bool AdaWriter::isOOClass(UMLClassifier *c) {
+     Uml::Object_Type ot = c->getBaseType();
+     if (ot == Uml::ot_Interface)
+@@ -528,17 +515,19 @@
+     // for generating meaningful implementations.
+ }
+ 
+-void AdaWriter::createDefaultDatatypes() {
+-    m_doc->createDatatype("Boolean");
+-    m_doc->createDatatype("Character");
+-    m_doc->createDatatype("Positive");
+-    m_doc->createDatatype("Natural");
+-    m_doc->createDatatype("Integer");
+-    m_doc->createDatatype("Short_Integer");
+-    m_doc->createDatatype("Long_Integer");
+-    m_doc->createDatatype("Float");
+-    m_doc->createDatatype("Long_Float");
+-    m_doc->createDatatype("String");
++QStringList AdaWriter::defaultDatatypes() {
++    QStringList l;
++    l.append("Boolean");
++    l.append("Character");
++    l.append("Positive");
++    l.append("Natural");
++    l.append("Integer");
++    l.append("Short_Integer");
++    l.append("Long_Integer");
++    l.append("Float");
++    l.append("Long_Float");
++    l.append("String");
++    return l;
+ }
+ 
+ /**
+--- umbrello/umbrello/codegenerators/javacodegenerator.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/javacodegenerator.h	(revision 497528)
+@@ -45,8 +45,8 @@
+     /**
+      * Empty Constructor
+      */
+-    JavaCodeGenerator ( UMLDoc * doc , const char * name, QDomElement & element);
+-    JavaCodeGenerator ( UMLDoc * doc , const char * name);
++    JavaCodeGenerator ();
++    JavaCodeGenerator (QDomElement & element);
+ 
+     /**
+      * Empty Destructor
+@@ -126,12 +126,12 @@
+     CodeComment * newCodeComment ( CodeDocument * doc) ;
+ 
+     // return "Java"
+-    QString getLanguage();
++    Uml::Programming_Language getLanguage();
+ 
+     /**
+      * Adds Java's primitives as datatypes
+      */
+-    virtual void createDefaultDatatypes();
++    virtual QStringList defaultDatatypes();
+ 
+     /**
+      * IF the type is "string" we need to declare it as
+--- umbrello/umbrello/codegenerators/cppcodegenerator.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/cppcodegenerator.h	(revision 497528)
+@@ -44,7 +44,7 @@
+     /**
+      * Basic Constructor
+      */
+-    CPPCodeGenerator ( UMLDoc * doc , const char * name);
++    CPPCodeGenerator ();
+ 
+     /**
+      * Empty Destructor
+@@ -98,16 +98,9 @@
+     bool removeHeaderCodeDocument ( CPPHeaderCodeDocument * remove_object );
+ 
+     /**
+-     * checks whether type is "CPPCodeGenerator"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "Cpp"
+      */
+-    QString getLanguage();
++    Uml::Programming_Language getLanguage();
+ 
+     // generate 2 different types of classifier code documents.
+     CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier);
+@@ -132,7 +125,7 @@
+     /**
+      * Add C++ primitives as datatypes
+      */
+-    void createDefaultDatatypes();
++    QStringList defaultDatatypes();
+ 
+     /**
+      * Save the XMI representation of this object
+--- umbrello/umbrello/codegenerators/phpwriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/phpwriter.h	(revision 497528)
+@@ -30,7 +30,7 @@
+     Q_OBJECT
+ public:
+ 
+-    PhpWriter( UMLDoc * parent, const char* name = 0 );
++    PhpWriter();
+     virtual ~PhpWriter();
+ 
+     /**
+@@ -40,16 +40,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "PhpWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "PHP"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/simplecodegenerator.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/simplecodegenerator.cpp	(revision 497528)
+@@ -42,11 +42,10 @@
+ // Constructors/Destructors
+ //
+ 
+-SimpleCodeGenerator::SimpleCodeGenerator (UMLDoc * parentDoc , const char * name,
+-        bool createDirHierarchyForPackages /* =true */)
+-        : CodeGenerator( parentDoc, name )
++SimpleCodeGenerator::SimpleCodeGenerator (bool createDirHierarchyForPackages /* =true */)
+ {
+     m_indentLevel = 0;
++    UMLDoc * parentDoc = UMLApp::app()->getDocument();
+     parentDoc->disconnect(this); // disconnect from UMLDoc.. we arent planning to be synced at all
+     m_createDirHierarchyForPackages = createDirHierarchyForPackages;
+     initFields(parentDoc);
+--- umbrello/umbrello/codegenerators/perlwriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/perlwriter.cpp	(revision 497528)
+@@ -27,8 +27,7 @@
+ #include <qdatetime.h>
+ #include <qtextstream.h>
+ 
+-PerlWriter::PerlWriter( UMLDoc * doc, const char *name )
+-        : SimpleCodeGenerator ( doc, name )
++PerlWriter::PerlWriter()
+ {
+ }
+ 
+@@ -166,22 +165,10 @@
+ /**
+  * returns "Perl"
+  */
+-QString PerlWriter::getLanguage() {
+-    return "Perl";
++Uml::Programming_Language PerlWriter::getLanguage() {
++    return Uml::pl_Perl;
+ }
+ 
+-/**
+- * checks whether type is "PerlWriter"
+- *
+- * @param type
+- */
+-bool PerlWriter::isType (QString & type)
+-{
+-    if(type == "PerlWriter")
+-        return true;
+-    return false;
+-}
+-
+ ////////////////////////////////////////////////////////////////////////////////////
+ //  Helper Methods
+ 
+@@ -359,10 +346,12 @@
+     return;
+ }
+ 
+-void PerlWriter::createDefaultDatatypes() {
+-    m_doc->createDatatype("$");
+-    m_doc->createDatatype("@");
+-    m_doc->createDatatype("%");
++QStringList PerlWriter::defaultDatatypes() {
++    QStringList l;
++    l.append("$");
++    l.append("@");
++    l.append("%");
++    return l;
+ }
+ 
+ const QStringList PerlWriter::reservedKeywords() const {
+--- umbrello/umbrello/codegenerators/aswriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/aswriter.cpp	(revision 497528)
+@@ -24,8 +24,7 @@
+ #include <qregexp.h>
+ #include <qtextstream.h>
+ 
+-ASWriter::ASWriter( UMLDoc *parent, const char *name )
+-        :SimpleCodeGenerator( parent, name) {
++ASWriter::ASWriter() {
+ }
+ 
+ ASWriter::~ASWriter() {}
+@@ -289,22 +288,10 @@
+ /**
+  * returns "ActionScript"
+  */
+-QString ASWriter::getLanguage() {
+-    return "ActionScript";
++Uml::Programming_Language ASWriter::getLanguage() {
++    return Uml::pl_ActionScript;
+ }
+ 
+-/**
+- * checks whether type is "ASWriter"
+- *
+- * @param type
+- */
+-bool ASWriter::isType (QString & type)
+-{
+-    if(type == "ASWriter")
+-        return true;
+-    return false;
+-}
+-
+ const QStringList ASWriter::reservedKeywords() const {
+ 
+     static QStringList keywords;
+--- umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp	(revision 497528)
+@@ -149,6 +149,8 @@
+     // virtual functions
+     start = (inlinePolicy ? " {" : ";");
+     end = (inlinePolicy ? "}" : "");
++    if (pOp->getConst())
++        prototype += " const";
+     if (interface || pOp->getAbstract()) {
+        // constructor can't be virtual or abstract
+        if (!pOp->isLifeOperation()) {
+--- umbrello/umbrello/codegenerators/pythonwriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/pythonwriter.cpp	(revision 497528)
+@@ -34,8 +34,7 @@
+ #include "../operation.h"
+ #include "../umlnamespace.h"
+ 
+-PythonWriter::PythonWriter( UMLDoc *parent, const char *name )
+-  : SimpleCodeGenerator(parent, name), m_bNeedPass(true) {
++PythonWriter::PythonWriter() : m_bNeedPass(true) {
+ }
+ 
+ PythonWriter::~PythonWriter() {}
+@@ -257,22 +256,10 @@
+ /**
+  * returns "Python"
+  */
+-QString PythonWriter::getLanguage() {
+-    return "Python";
++Uml::Programming_Language PythonWriter::getLanguage() {
++    return Uml::pl_Python;
+ }
+ 
+-/**
+- * checks whether type is "PythonWriter"
+- *
+- * @param type
+- */
+-bool PythonWriter::isType (QString & type)
+-{
+-    if(type == "PythonWriter")
+-        return true;
+-    return false;
+-}
+-
+ const QStringList PythonWriter::reservedKeywords() const {
+ 
+     static QStringList keywords;
+--- umbrello/umbrello/codegenerators/rubywriter.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/rubywriter.cpp	(revision 497528)
+@@ -35,8 +35,7 @@
+ #include "../operation.h"
+ #include "../umlnamespace.h"
+ 
+-RubyWriter::RubyWriter( UMLDoc *parent, const char *name ) :
+-SimpleCodeGenerator( parent, name) {
++RubyWriter::RubyWriter() {
+ }
+ 
+ RubyWriter::~RubyWriter() {}
+@@ -388,22 +387,10 @@
+ /**
+  * returns "Ruby"
+  */
+-QString RubyWriter::getLanguage() {
+-    return "Ruby";
++Uml::Programming_Language RubyWriter::getLanguage() {
++    return Uml::pl_Ruby;
+ }
+ 
+-/**
+- * checks whether type is "RubyWriter"
+- *
+- * @param type
+- */
+-bool RubyWriter::isType (QString & type)
+-{
+-    if(type == "RubyWriter")
+-        return true;
+-    return false;
+-}
+-
+ const QStringList RubyWriter::reservedKeywords() const {
+ 
+     static QStringList keywords;
+--- umbrello/umbrello/codegenerators/javacodegenerator.cpp	(revision 490305)
++++ umbrello/umbrello/codegenerators/javacodegenerator.cpp	(revision 497528)
+@@ -31,15 +31,13 @@
+ // Constructors/Destructors
+ //
+ 
+-JavaCodeGenerator::JavaCodeGenerator ( UMLDoc * parentDoc , const char * name, QDomElement & elem )
+-        : CodeGenerator ( parentDoc , name)
++JavaCodeGenerator::JavaCodeGenerator (QDomElement & elem)
+ {
+     initFields();
+     loadFromXMI(elem);
+ }
+ 
+-JavaCodeGenerator::JavaCodeGenerator ( UMLDoc * parentDoc, const char * name )
+-        : CodeGenerator ( parentDoc , name)
++JavaCodeGenerator::JavaCodeGenerator ()
+ {
+     initFields();
+ }
+@@ -54,8 +52,8 @@
+ //
+ 
+ // return our language
+-QString JavaCodeGenerator::getLanguage() {
+-    return "Java";
++Uml::Programming_Language JavaCodeGenerator::getLanguage() {
++    return Uml::pl_Java;
+ }
+ 
+ /**
+@@ -192,15 +190,18 @@
+ 
+ }
+ 
+-void JavaCodeGenerator::createDefaultDatatypes() {
+-    m_document->createDatatype("int");
+-    m_document->createDatatype("char");
+-    m_document->createDatatype("boolean");
+-    m_document->createDatatype("float");
+-    m_document->createDatatype("double");
+-    m_document->createDatatype("byte");
+-    m_document->createDatatype("short");
+-    m_document->createDatatype("string");
++QStringList JavaCodeGenerator::defaultDatatypes() {
++    QStringList l;
++    l.append("int");
++    l.append("char");
++    l.append("boolean");
++    l.append("float");
++    l.append("double");
++    l.append("byte");
++    l.append("short");
++    l.append("long");
++    l.append("string");
++    return l;
+ }
+ 
+ const QStringList JavaCodeGenerator::reservedKeywords() const {
+--- umbrello/umbrello/codegenerators/javawriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/javawriter.h	(revision 497528)
+@@ -39,7 +39,7 @@
+     /**
+      * Constructor, initialises a couple of variables
+      */
+-    JavaWriter(UMLDoc* parent = 0, const char* name = 0);
++    JavaWriter();
+ 
+     /**
+      * Destructor, empty
+@@ -53,16 +53,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "JavaCodeGenerator"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "Java"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+ private:
+ 
+--- umbrello/umbrello/codegenerators/xmlschemawriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/xmlschemawriter.h	(revision 497528)
+@@ -46,7 +46,7 @@
+     /**
+      * Constructor, initialises a couple of variables
+      */
+-    XMLSchemaWriter(UMLDoc * doc, const char* name = 0);
++    XMLSchemaWriter();
+ 
+     /**
+      * Destructor, empty
+@@ -60,16 +60,9 @@
+     virtual void writeClass(UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "XMLSchemaWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "XMLSchema"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+     /**
+      * get list of reserved keywords
+--- umbrello/umbrello/codegenerators/adawriter.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/adawriter.h	(revision 497528)
+@@ -37,7 +37,7 @@
+     /**
+      * Basic Constructor
+      */
+-    AdaWriter (UMLDoc * parent = 0, const char* name = 0);
++    AdaWriter ();
+ 
+     /**
+      * Empty Destructor
+@@ -51,18 +51,11 @@
+     virtual void writeClass (UMLClassifier *c);
+ 
+     /**
+-     * checks whether type is "AdaWriter"
+-     *
+-     * @param type
+-     */
+-    virtual bool isType (QString & type);
+-
+-    /**
+      * returns "Ada"
+      */
+-    virtual QString getLanguage();
++    virtual Uml::Programming_Language getLanguage();
+ 
+-    void createDefaultDatatypes();
++    QStringList defaultDatatypes();
+ 
+     /**
+      * Check whether the given string is a reserved word for the
+--- umbrello/umbrello/codegenerators/rubycodegenerator.h	(revision 490305)
++++ umbrello/umbrello/codegenerators/rubycodegenerator.h	(revision 497528)
+@@ -42,8 +42,8 @@
+     /**
+      * Empty Constructor
+      */
+-    RubyCodeGenerator ( UMLDoc * doc , const char * name, QDomElement & element);
+-    RubyCodeGenerator ( UMLDoc * doc , const char * name);
++    RubyCodeGenerator ();
++    RubyCodeGenerator (QDomElement & element);
+ 
+     /**
+      * Empty Destructor
+@@ -110,14 +110,9 @@
+     CodeComment * newCodeComment ( CodeDocument * doc) ;
+ 
+     // return "Ruby"
+-    QString getLanguage();
++    Uml::Programming_Language getLanguage();
+ 
+     /**
+-     * Adds Ruby's primitives as datatypes
+-     */
+-    virtual void createDefaultDatatypes();
+-
+-    /**
+      * Convert a C++ type such as 'int' or 'QWidget' to 
+      * ruby types Integer and Qt::Widget
+      *
+--- umbrello/umbrello/classifierwidget.cpp	(revision 490305)
++++ umbrello/umbrello/classifierwidget.cpp	(revision 497528)
+@@ -26,6 +26,7 @@
+ #include "umldoc.h"
+ #include "uml.h"
+ #include "listpopupmenu.h"
++#include "model_utils.h"
+ 
+ ClassifierWidget::ClassifierWidget(UMLView * view, UMLClassifier *c)
+   : UMLWidget(view, c) {
+@@ -402,7 +403,7 @@
+         {
+             UMLDoc *doc = UMLApp::app()->getDocument();
+             Uml::Object_Type ot = ListPopupMenu::convert_MT_OT(mt);
+-            if (doc->createChildObject(m_pObject, ot))
++            if (Model_Utils::createChildObject(m_pObject, ot))
+                 doc->setModified();
+             updateComponentSize();
+             update();
+--- umbrello/umbrello/entityattribute.cpp	(revision 490305)
++++ umbrello/umbrello/entityattribute.cpp	(revision 497528)
+@@ -22,6 +22,7 @@
+ #include "umldoc.h"
+ #include "uml.h"
+ #include "dialogs/umlentityattributedialog.h"
++#include "object_factory.h"
+ 
+ UMLEntityAttribute::UMLEntityAttribute( const UMLObject *parent, QString Name, Uml::IDType id,
+                                         Uml::Visibility s, QString type, QString iv )
+@@ -39,7 +40,7 @@
+         UMLDoc* pDoc = UMLApp::app()->getDocument();
+         m_pSecondary = pDoc->findUMLObject(type);
+         if (m_pSecondary == NULL) {
+-            m_pSecondary = pDoc->createUMLObject(Uml::ot_EntityAttribute, type);
++            m_pSecondary = Object_Factory::createUMLObject(Uml::ot_EntityAttribute, type);
+         }
+     }
+ }
+--- umbrello/umbrello/dialogs/umlentityattributedialog.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/umlentityattributedialog.cpp	(revision 497528)
+@@ -37,6 +37,7 @@
+ #include "../umldoc.h"
+ #include "../uml.h"
+ #include "../dialog_utils.h"
++#include "../object_factory.h"
+ 
+ UMLEntityAttributeDialog::UMLEntityAttributeDialog( QWidget * pParent, UMLEntityAttribute * pEntityAttribute )
+         : KDialogBase( Plain, i18n("Entity Attribute Properties"), Help | Ok | Cancel , Ok, pParent, "_UMLENTITYATTRIBUTEDLG_", true, true) {
+@@ -230,7 +231,7 @@
+         // Else we don't know what it is so as a compromise create a class.
+         Uml::Object_Type ot = (typeName.contains('*') ? Uml::ot_Datatype
+                                : Uml::ot_Class);
+-        obj = pDoc->createUMLObject(ot, typeName);
++        obj = Object_Factory::createUMLObject(ot, typeName);
+         if (obj == NULL)
+             return false;
+         classifier = static_cast<UMLClassifier*>(obj);
+--- umbrello/umbrello/dialogs/codegenerationoptionspage.h	(revision 490305)
++++ umbrello/umbrello/dialogs/codegenerationoptionspage.h	(revision 497528)
+@@ -22,6 +22,7 @@
+ #include <qwidget.h>
+ #include "codegenerationoptionsbase.h"
+ #include "../codegenerator.h"
++#include "../umlnamespace.h"
+ 
+ /**
+  * @author Luis De la Parra
+@@ -35,7 +36,8 @@
+     Q_OBJECT
+ public:
+     CodeGenerationOptionsPage(CodeGenerator * gen,
+-                              QString activeLanguage, QWidget *parent=0, const char *name=0);
++                              Uml::Programming_Language activeLanguage,
++                              QWidget *parent=0, const char *name=0);
+     ~CodeGenerationOptionsPage();
+     void setDefaults();
+     QString getCodeGenerationLanguage();
+@@ -50,11 +52,11 @@
+ 
+     CodeGenerator * m_pCodeGenerator;
+     CodeGenerationPolicyPage * m_pCodePolicyPage;
+-    void init (CodeGenerator * gen, const QString &activeLanguage);
++    void init (CodeGenerator * gen, Uml::Programming_Language activeLanguage);
+     int overwriteToInteger(CodeGenerationPolicy::OverwritePolicy value);
+     int newLineToInteger(CodeGenerationPolicy::NewLineType value);
+     int indentTypeToInteger(CodeGenerationPolicy::IndentationType value);
+-    void setupActiveLanguageBox(QString activeLanguage);
++    void setupActiveLanguageBox(Uml::Programming_Language activeLanguage);
+ 
+ protected slots:
+     void activeLanguageChanged(int id);
+--- umbrello/umbrello/dialogs/codegenerationwizard.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/codegenerationwizard.cpp	(revision 497528)
+@@ -27,13 +27,12 @@
+ #include "codegenerationoptionspage.h"
+ #include "../classifier.h"
+ #include "../codegenerator.h"
+-#include "../generatorinfo.h"
+ #include "../uml.h"
+ #include "../umldoc.h"
+ 
+ CodeGenerationWizard::CodeGenerationWizard(UMLDoc *doc,
+         UMLClassifierList *classList,
+-        QString activeLanguage,
++        Uml::Programming_Language activeLanguage,
+         UMLApp *parent, const char *name)
+         :CodeGenerationWizardBase((QWidget*)parent,name) {
+     m_doc = doc;
+@@ -209,20 +208,6 @@
+ CodeGenerator* CodeGenerationWizard::generator() {
+     // FIX
+     /*
+-        GeneratorInfo* info;
+-        if( m_CodeGenerationOptionsPage->getCodeGenerationLanguage().isEmpty() ) {
+-                KMessageBox::sorry(this,i18n("There is no Active Language defined.\nPlease select\
+-                                             one of the installed languages to generate the code in."),
+-                                   i18n("No Language Selected"));
+-                return 0;
+-        }
+-        GeneratorDict ldict = UMLApp::app()->generatorDict();
+-        info = ldict.find( m_CodeGenerationOptionsPage->getCodeGenerationLanguage() );
+-        if(!info) {
+-                kdDebug()<<"error looking up library information (dictionary)"<<endl;
+-                return 0;
+-        }
+-
+         KLibLoader* loader = KLibLoader::self();
+         if(!loader) {
+                 kdDebug()<<"error getting KLibLoader!"<<endl;
+--- umbrello/umbrello/dialogs/codeeditor.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/codeeditor.cpp	(revision 497528)
+@@ -146,7 +146,7 @@
+                 }
+                 else if( (dynamic_cast<UMLClassifier*>(obj)) )
+                 {
+-                    if(m_parentDoc->getParentGenerator()->getDocument()->showProperties(obj))
++                    if (obj->showProperties())
+                         rebuildView(para);
+                 }
+                 else if( (role = dynamic_cast<UMLRole*>(obj)))
+--- umbrello/umbrello/dialogs/settingsdlg.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/settingsdlg.cpp	(revision 497528)
+@@ -29,7 +29,7 @@
+ #include "../dialog_utils.h"
+ 
+ SettingsDlg::SettingsDlg( QWidget * parent, Settings::OptionState *state,
+-                          QString activeLanguage, CodeGenerator * gen)
++                          Uml::Programming_Language activeLanguage, CodeGenerator * gen)
+         : KDialogBase( IconList, i18n("Umbrello Setup"),
+                Help | Default | Apply | Ok | Cancel, Ok, parent, 0, true, true ) {
+     m_bChangesApplied = false;
+@@ -252,7 +252,7 @@
+ 
+ }
+ 
+-void SettingsDlg::setupCodeGenPage(CodeGenerator *gen, const QString &activeLanguage) {
++void SettingsDlg::setupCodeGenPage(CodeGenerator *gen, Uml::Programming_Language activeLanguage) {
+     //setup code generation settings page
+     QVBox * page = addVBoxPage( i18n("Code Generation"), i18n("Code Generation Settings"), DesktopIcon( "source") );
+     m_pCodeGenPage = new CodeGenerationOptionsPage(gen, activeLanguage, page);
+--- umbrello/umbrello/dialogs/codegenerationoptionspage.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/codegenerationoptionspage.cpp	(revision 497528)
+@@ -20,7 +20,7 @@
+ // app includes
+ #include "codegenerationpolicypage.h"
+ #include "defaultcodegenpolicypage.h"
+-#include "../generatorinfo.h"
++#include "../model_utils.h"
+ #include "../uml.h"
+ 
+ //kde include
+@@ -34,7 +34,7 @@
+ #include <qbuttongroup.h>
+ 
+ CodeGenerationOptionsPage::CodeGenerationOptionsPage( CodeGenerator * gen,
+-        QString activeLanguage,
++        Uml::Programming_Language activeLanguage,
+         QWidget *parent,
+         const char *name )
+         :CodeGenerationOptionsBase(parent,name)
+@@ -45,8 +45,7 @@
+ CodeGenerationOptionsPage::~CodeGenerationOptionsPage() { }
+ 
+ void CodeGenerationOptionsPage::init( CodeGenerator * gen,
+-                                      const QString &activeLanguage
+-                                    )
++                                      Uml::Programming_Language activeLanguage)
+ {
+ 
+     m_pCodeGenerator = 0;
+@@ -93,40 +92,18 @@
+ 
+ }
+ 
+-void CodeGenerationOptionsPage::setupActiveLanguageBox(QString activeLanguage)
++void CodeGenerationOptionsPage::setupActiveLanguageBox(Uml::Programming_Language activeLanguage)
+ {
+-    GeneratorDict ldict = UMLApp::app()->generatorDict();
+-    //last but not least.. populate language list
+-    bool foundActive = false;
+-    GeneratorDictIt it(ldict);
+     int indexCounter = 0;
+-    for (it.toFirst(); it.current(); ++it) {
+-        m_SelectLanguageBox->insertItem(it.current()->language, indexCounter);
+-        if(activeLanguage == it.current()->language) {
+-            m_SelectLanguageBox->setCurrentItem(indexCounter);
+-            foundActive = true;
+-        }
++    while (indexCounter < Uml::pl_Reserved) {
++        QString language = Model_Utils::progLangToString((Uml::Programming_Language) indexCounter);
++        m_SelectLanguageBox->insertItem(language, indexCounter);
+         indexCounter++;
+     }
+-
+-    //if we could not find the active language, we try to fall back to C++
+-    if (!foundActive) {
+-        indexCounter = 0;
+-        for(it.toFirst(); it.current(); ++it) {
+-            if (it.current()->language == "Cpp") {
+-                m_SelectLanguageBox->setCurrentItem(indexCounter);
+-                activeLanguage = it.current()->language;
+-                break;
+-            }
+-        }
+-    }
+-
+-    //last try... if we dont have a activeLanguage and we have no Cpp installed we just
+-    //take the first language we find as "active"
+-    if( activeLanguage.isEmpty() ) {
+-        m_SelectLanguageBox->setCurrentItem(0);
+-    }
+-
++    if (activeLanguage != Uml::pl_Reserved)
++        m_SelectLanguageBox->setCurrentItem(activeLanguage);
++    else
++        m_SelectLanguageBox->setCurrentItem(Uml::pl_Cpp);
+ }
+ 
+ int CodeGenerationOptionsPage::indentTypeToInteger(CodeGenerationPolicy::IndentationType value) {
+--- umbrello/umbrello/dialogs/umlattributedialog.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/umlattributedialog.cpp	(revision 497528)
+@@ -38,6 +38,7 @@
+ #include "../umldoc.h"
+ #include "../uml.h"
+ #include "../dialog_utils.h"
++#include "../object_factory.h"
+ 
+ UMLAttributeDialog::UMLAttributeDialog( QWidget * pParent, UMLAttribute * pAttribute )
+         : KDialogBase( Plain, i18n("Attribute Properties"), Help | Ok | Cancel , Ok, pParent, "_UMLATTRIBUTEDLG_", true, true) {
+@@ -198,7 +199,7 @@
+         // Else we don't know what it is so as a compromise create a class.
+         Uml::Object_Type ot = (typeName.contains('*') ? Uml::ot_Datatype
+                                : Uml::ot_Class);
+-        obj = pDoc->createUMLObject(ot, typeName);
++        obj = Object_Factory::createUMLObject(ot, typeName);
+         if (obj == NULL)
+             return false;
+         classifier = static_cast<UMLClassifier*>(obj);
+--- umbrello/umbrello/dialogs/classifierlistpage.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/classifierlistpage.cpp	(revision 497528)
+@@ -18,6 +18,7 @@
+ #include "../template.h"
+ #include "../enumliteral.h"
+ #include "../entityattribute.h"
++#include "../model_utils.h"
+ #include <kbuttonbox.h>
+ #include <kdebug.h>
+ #include <klocale.h>
+@@ -410,7 +411,7 @@
+ void ClassifierListPage::slotNewListItem() {
+     saveCurrentItemDocumentation();
+     m_bSigWaiting = true;
+-    m_pDoc->createChildObject(m_pClassifier, m_itemType);
++    Model_Utils::createChildObject(m_pClassifier, m_itemType);
+ }
+ 
+ void ClassifierListPage::saveCurrentItemDocumentation() {
+--- umbrello/umbrello/dialogs/umloperationdialog.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/umloperationdialog.cpp	(revision 497528)
+@@ -86,11 +86,14 @@
+     genLayout -> addWidget(m_pStereoTypeCB, 1, 1);
+ 
+     m_pAbstractCB = new QCheckBox( i18n("&Abstract operation"), m_pGenGB );
+-    m_pAbstractCB -> setChecked( m_pOperation -> getAbstract() );
++    m_pAbstractCB -> setChecked( m_pOperation->getAbstract() );
++    genLayout -> addWidget( m_pAbstractCB, 2, 0 );
+     m_pStaticCB = new QCheckBox( i18n("Classifier &scope (\"static\")"), m_pGenGB );
+-    m_pStaticCB -> setChecked( m_pOperation -> getStatic() );
+-    genLayout -> addWidget( m_pAbstractCB, 2, 0 );
++    m_pStaticCB -> setChecked( m_pOperation->getStatic() );
+     genLayout -> addWidget( m_pStaticCB, 2, 1 );
++    m_pQueryCB = new QCheckBox( i18n("&Query (\"const\")"), m_pGenGB );
++    m_pQueryCB -> setChecked( m_pOperation->getConst() );
++    genLayout -> addWidget( m_pQueryCB, 2, 2 );
+ 
+     topLayout -> addWidget( m_pGenGB );
+ 
+@@ -485,6 +488,8 @@
+     else
+         m_pOperation->setTypeName(typeName);
+ 
++    m_pOperation->setStereotype( m_pStereoTypeCB->currentText() );
++
+     bool isAbstract = m_pAbstractCB->isChecked();
+     m_pOperation -> setAbstract( isAbstract );
+     if (isAbstract) {
+@@ -495,8 +500,8 @@
+          */
+         classifier->setAbstract(true);
+     }
+-    m_pOperation -> setStatic( m_pStaticCB -> isChecked() );
+-    m_pOperation -> setStereotype( m_pStereoTypeCB->currentText() );
++    m_pOperation->setStatic( m_pStaticCB->isChecked() );
++    m_pOperation->setConst( m_pQueryCB->isChecked() );
+ 
+     return true;
+ }
+--- umbrello/umbrello/dialogs/parmpropdlg.cpp	(revision 490305)
++++ umbrello/umbrello/dialogs/parmpropdlg.cpp	(revision 497528)
+@@ -29,6 +29,7 @@
+ #include "../template.h"
+ #include "../umldoc.h"
+ #include "../dialog_utils.h"
++#include "../object_factory.h"
+ 
+ ParmPropDlg::ParmPropDlg(QWidget * parent, UMLDoc * doc, UMLAttribute * a)
+         : KDialogBase(Plain, i18n("Parameter Properties"), Help | Ok | Cancel , Ok, parent, "_PARMPROPDLG_", true, true)
+@@ -209,7 +210,7 @@
+             // create a datatype or a class. For now, we create a class.
+             kdDebug() << "ParmPropDlg::slotOk: " << typeName << " not found."
+                 << " Creating a new class for the type." << endl;
+-            UMLObject *o = m_pUmldoc->createUMLObject(Uml::ot_Class, typeName);
++            UMLObject *o = Object_Factory::createUMLObject(Uml::ot_Class, typeName);
+             m_pAtt->setType(o);
+         }
+ 
+--- umbrello/umbrello/dialogs/umloperationdialog.h	(revision 490305)
++++ umbrello/umbrello/dialogs/umloperationdialog.h	(revision 497528)
+@@ -99,6 +99,7 @@
+     QLineEdit * m_pNameLE;
+     QCheckBox * m_pAbstractCB;
+     QCheckBox * m_pStaticCB;
++    QCheckBox * m_pQueryCB;
+     QPushButton* m_pDeleteButton;
+     QPushButton* m_pPropertiesButton;
+     KArrowButton* m_pUpButton;
+--- umbrello/umbrello/dialogs/codegenerationwizard.h	(revision 490305)
++++ umbrello/umbrello/dialogs/codegenerationwizard.h	(revision 497528)
+@@ -39,7 +39,7 @@
+     Q_OBJECT
+ public:
+     CodeGenerationWizard(UMLDoc *doc, UMLClassifierList *classList,
+-                         QString activeLanguage, UMLApp *parent,
++                         Uml::Programming_Language activeLanguage, UMLApp *parent,
+                          const char *name=0);
+     ~CodeGenerationWizard();
+ 
+--- umbrello/umbrello/dialogs/settingsdlg.h	(revision 490305)
++++ umbrello/umbrello/dialogs/settingsdlg.h	(revision 497528)
+@@ -50,7 +50,7 @@
+ 
+ public:
+     SettingsDlg( QWidget * parent, Settings::OptionState *state,
+-                 QString activeLanguage, CodeGenerator * gen);
++                 Uml::Programming_Language activeLanguage, CodeGenerator * gen);
+     ~SettingsDlg();
+ 
+     //public methods
+@@ -140,7 +140,7 @@
+     void setupUIPage();
+     void setupGeneralPage();
+     void setupClassPage();
+-    void setupCodeGenPage( CodeGenerator *gen, const QString &activeLanguage);
++    void setupCodeGenPage( CodeGenerator *gen, Uml::Programming_Language activeLanguage);
+     void setupCodeViewerPage(Settings::CodeViewerState options);
+     void applyPage( Settings::Page page );
+ 
+--- umbrello/umbrello/widgetbase.cpp	(revision 490305)
++++ umbrello/umbrello/widgetbase.cpp	(revision 497528)
+@@ -82,9 +82,9 @@
+ 
+ void WidgetBase::saveToXMI( QDomDocument & /*qDoc*/, QDomElement & qElement ) {
+     if (m_bUsesDiagramLineColour) {
+-        qElement.setAttribute( "linecolour", "none" );
++        qElement.setAttribute( "linecolor", "none" );
+     } else {
+-        qElement.setAttribute( "linecolour", m_LineColour.name() );
++        qElement.setAttribute( "linecolor", m_LineColour.name() );
+     }
+     if (m_bUsesDiagramLineWidth) {
+         qElement.setAttribute( "linewidth", "none" );
+@@ -94,20 +94,25 @@
+ }
+ 
+ bool WidgetBase::loadFromXMI( QDomElement & qElement ) {
+-    QString lineColour = qElement.attribute( "linecolour", "none" );
++    // first load from "linecolour" and then overwrite with the "linecolor"
++    // attribute if that one is present. The "linecolour" name was a "typo" in
++    // earlier versions of Umbrello
++    QString lineColor = qElement.attribute( "linecolour", "none" );
++    lineColor = qElement.attribute( "linecolor", lineColor );
++
+     QString lineWidth = qElement.attribute( "linewidth", "none" );
+-    if (lineColour != "none") {
+-        m_LineColour = QColor(lineColour);
++    if (lineColor != "none") {
++        setLineColor( QColor(lineColor) );
+         m_bUsesDiagramLineColour = false;
+     } else if (m_Type != Uml::wt_Box && m_pView != NULL) {
+-        m_LineColour = m_pView->getLineColor();
++        setLineColor( m_pView->getLineColor() );
+         m_bUsesDiagramLineColour = true;
+     }
+     if (lineWidth != "none") {
+-        m_LineWidth = lineWidth.toInt();
++        setLineWidth( lineWidth.toInt() );
+         m_bUsesDiagramLineWidth = false;
+     } else if ( m_pView ) {
+-        m_LineWidth = m_pView->getLineWidth();
++        setLineWidth( m_pView->getLineWidth() );
+         m_bUsesDiagramLineWidth = true;
+     }
+     return true;
+--- umbrello/umbrello/codegenerator.h	(revision 490305)
++++ umbrello/umbrello/codegenerator.h	(revision 497528)
+@@ -25,6 +25,8 @@
+ #include "codegenerationpolicy.h"
+ #include "umlclassifierlist.h"
+ #include "codedocumentlist.h"
++#include "codeviewerstate.h"
++#include "umlnamespace.h"
+ 
+ class UMLAttribute;
+ class UMLDoc;
+@@ -45,8 +47,6 @@
+ 
+ class KConfig;
+ 
+-#include "codeviewerstate.h"
+-
+ /**
+   * class CodeGenerator
+   * This class collects together all of the code documents which form this project,
+@@ -94,7 +94,7 @@
+      * @return      CodeGenerator
+      * @param       doc 
+      */
+-    CodeGenerator (UMLDoc * doc, const char *name);
++    CodeGenerator ();
+ 
+     /**
+      * Build a code generator and then initialize it from an XMI element.
+@@ -102,16 +102,13 @@
+      * @param       doc 
+      * @param       element an element from an XMI document 
+      */
+-    CodeGenerator (UMLDoc * doc, const char *name, QDomElement & element );
++    CodeGenerator (QDomElement & element );
+ 
+     /**
+      * Empty Destructor
+      */
+     virtual ~CodeGenerator ( );
+ 
+-    // Public attributes
+-    //
+-
+     // Public attribute accessor methods
+     //
+ 
+@@ -296,9 +293,9 @@
+     virtual CodeDocument * newCodeDocument ( );
+ 
+     /**
+-     * Return the unique language string that identifies this type of code generator
++     * Return the unique language enum that identifies this type of code generator
+      */
+-    virtual QString getLanguage() = 0;
++    virtual Uml::Programming_Language getLanguage() = 0;
+ 
+     /**
+      * Find a code document by the given classifier.
+@@ -310,9 +307,10 @@
+     CodeDocument * findCodeDocumentByClassifier (UMLClassifier * classifier );
+ 
+     /**
+-     * Create the default datatypes for your language (bool, int etc)
++     * Return the default datatypes for your language (bool, int etc)
++     * Default implementation returns empty list.
+      */
+-    virtual void createDefaultDatatypes();
++    virtual QStringList defaultDatatypes();
+ 
+     /** Get the editing dialog for this code document
+      */
+--- umbrello/umbrello/association.cpp	(revision 490305)
++++ umbrello/umbrello/association.cpp	(revision 497528)
+@@ -161,8 +161,7 @@
+ }
+ 
+ void UMLAssociation::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+-    if (m_AssocType == Uml::at_Generalization ||
+-            m_AssocType == Uml::at_Realization) {
++    if (m_AssocType == Uml::at_Generalization) {
+         QDomElement assocElement = UMLObject::save("UML:Generalization", qDoc);
+         assocElement.setAttribute( "discriminator", "" );
+         assocElement.setAttribute( "child", ID2STR(getObjectId(A)) );
+@@ -170,6 +169,13 @@
+         qElement.appendChild( assocElement );
+         return;
+     }
++    if (m_AssocType == Uml::at_Realization) {
++        QDomElement assocElement = UMLObject::save("UML:Abstraction", qDoc);
++        assocElement.setAttribute( "client", ID2STR(getObjectId(A)) );
++        assocElement.setAttribute( "supplier", ID2STR(getObjectId(B)) );
++        qElement.appendChild( assocElement );
++        return;
++    }
+     if (m_AssocType == Uml::at_Dependency) {
+         QDomElement assocElement = UMLObject::save("UML:Dependency", qDoc);
+         assocElement.setAttribute( "client", ID2STR(getObjectId(A)) );
+@@ -192,7 +198,8 @@
+     UMLDoc * doc = UMLApp::app()->getDocument();
+     UMLObject * obj[2] = { NULL, NULL };
+     if (m_AssocType == Uml::at_Generalization ||
+-            m_AssocType == Uml::at_Dependency) {
++        m_AssocType == Uml::at_Realization ||
++        m_AssocType == Uml::at_Dependency) {
+         for (unsigned r = Uml::A; r <= Uml::B; r++) {
+             const QString fetch = (m_AssocType == Uml::at_Generalization ?
+                                    r == Uml::A ? "child" : "parent"
+@@ -221,15 +228,9 @@
+                 QString tag = tempElement.tagName();
+                 if (Model_Utils::isCommonXMIAttribute(tag))
+                     continue;
+-                bool isGeneralization = (m_AssocType == Uml::at_Generalization &&
+-                                         (tagEq(tag, "child") || tagEq(tag, "parent") ||
+-                                          tagEq(tag, "subtype") || tagEq(tag, "supertype")));
+-                bool isDependency = (m_AssocType == Uml::at_Dependency &&
+-                                     (tagEq(tag, "client") || tagEq(tag, "supplier")));
+-                if (!isGeneralization && !isDependency) {
+-                    kdDebug() << "UMLAssociation::load: cannot load " << tag << endl;
+-                    continue;
+-                }
++                // Permitted tag names:
++                //  roleA: "child" "subtype" "client"
++                //  roleB: "parent" "supertype" "supplier"
+                 QString idStr = tempElement.attribute( "xmi.id", "" );
+                 if (idStr.isEmpty())
+                     idStr = tempElement.attribute( "xmi.idref", "" );
+@@ -242,8 +243,8 @@
+                 }
+                 if (idStr.isEmpty()) {
+                     kdError() << "UMLAssociation::load (type " << m_AssocType
+-                    << ", id " << ID2STR(getID()) << "): "
+-                    << "xmi id not given for " << tag << endl;
++                        << ", id " << ID2STR(getID()) << "): "
++                        << "xmi id not given for " << tag << endl;
+                     continue;
+                 }
+                 // Since we know for sure that we're dealing with a non
+@@ -256,15 +257,6 @@
+             }
+         }
+ 
+-        // setting the association type:
+-        //
+-        // In the old days, we could just record this on the association,
+-        // and be done with it. But thats not how the UML13.dtd does things.
+-        // As a result, we are checking roleA for information about the
+-        // parent association (!) which by this point in the parse, should
+-        // be set. However, the information that the roles are allowed to have
+-        // is not complete, so we need to finish the analysis here.
+-
+         // its a realization if either endpoint is an interface
+         if (m_AssocType == Uml::at_Generalization &&
+                 (obj[A] && obj[A]->getBaseType() == Uml::ot_Interface ||
+--- umbrello/umbrello/notewidget.cpp	(revision 490305)
++++ umbrello/umbrello/notewidget.cpp	(revision 497528)
+@@ -205,6 +205,7 @@
+ }
+ 
+ void NoteWidget::mouseReleaseEvent( QMouseEvent * me ) {
++    UMLWidget::mouseReleaseEvent( me );
+     if (m_bResizing) {
+         drawText();
+         UMLWidget::mouseReleaseEvent(me);
+--- umbrello/umbrello/activitywidget.cpp	(revision 490305)
++++ umbrello/umbrello/activitywidget.cpp	(revision 497528)
+@@ -27,8 +27,8 @@
+ ActivityWidget::ActivityWidget(UMLView * view, ActivityType activityType, Uml::IDType id )
+         : UMLWidget(view, id)
+ {
+-    m_ActivityType = activityType;
+     UMLWidget::setBaseType( Uml::wt_Activity );
++    setActivityType( activityType );
+     updateComponentSize();
+ }
+ 
+@@ -115,6 +115,7 @@
+ 
+ void ActivityWidget::setActivityType( ActivityType activityType ) {
+     m_ActivityType = activityType;
++    UMLWidget::m_bResizable = (m_ActivityType == Normal);
+ }
+ 
+ void ActivityWidget::slotMenuSelection(int sel) {
+@@ -195,7 +196,7 @@
+     m_Text = qElement.attribute( "activityname", "" );
+     m_Doc = qElement.attribute( "documentation", "" );
+     QString type = qElement.attribute( "activitytype", "1" );
+-    m_ActivityType = (ActivityType)type.toInt();
++    setActivityType( (ActivityType)type.toInt() );
+     return true;
+ }
+ 
+--- umbrello/umbrello/import_utils.cpp	(revision 490305)
++++ umbrello/umbrello/import_utils.cpp	(revision 497528)
+@@ -31,6 +31,7 @@
+ #include "attribute.h"
+ #include "template.h"
+ #include "association.h"
++#include "object_factory.h"
+ 
+ namespace Import_Utils {
+ 
+@@ -117,9 +118,10 @@
+         int isConst = name.contains(QRegExp("^const "));
+         name.remove(QRegExp("^const\\s+"));
+         QString typeName(name);
+-        int isPointer = typeName.contains('*');
+-        int isRef = typeName.contains('&');
+-        typeName.remove(QRegExp("[^\\w: ].*$"));
++        const int isAdorned = typeName.contains( QRegExp("[^\\w:\\. ]") );
++        const int isPointer = typeName.contains('*');
++        const int isRef = typeName.contains('&');
++        typeName.remove(QRegExp("[^\\w:\\. ].*$"));
+         UMLObject *origType = umldoc->findUMLObject(typeName, Uml::ot_UMLObject, parentPkg);
+         if (origType == NULL) {
+             // Still not found. Create the stripped down type.
+@@ -152,7 +154,7 @@
+                                         i18n("Namespace"), i18n("Class"));
+                     }
+                     Uml::Object_Type ot = (wantNamespace == KMessageBox::Yes ? Uml::ot_Package : Uml::ot_Class);
+-                    o = umldoc->createUMLObject(ot, scopeName, parentPkg);
++                    o = Object_Factory::createUMLObject(ot, scopeName, parentPkg);
+                     kapp->processEvents();
+                     parentPkg = static_cast<UMLPackage*>(o);
+                     UMLListView *listView = UMLApp::app()->getListView();
+@@ -163,13 +165,13 @@
+                 bPutAtGlobalScope = true;
+             }
+             Uml::Object_Type t = type;
+-            if (type == Uml::ot_UMLObject || isConst || isRef || isPointer)
++            if (type == Uml::ot_UMLObject || isAdorned)
+                 t = Uml::ot_Class;
+-            origType = umldoc->createUMLObject(t, typeName, parentPkg);
++            origType = Object_Factory::createUMLObject(t, typeName, parentPkg);
+             bNewUMLObjectWasCreated = true;
+             kapp->processEvents();
+         }
+-        if (isConst || isPointer || isRef) {
++        if (isConst || isAdorned) {
+             // Create the full given type (including adornments.)
+             if (isConst)
+                 name.prepend("const ");
+@@ -177,7 +179,7 @@
+                 parentPkg = NULL;
+                 bPutAtGlobalScope = false;
+             }
+-            o = umldoc->createUMLObject(Uml::ot_Datatype, name, parentPkg);
++            o = Object_Factory::createUMLObject(Uml::ot_Datatype, name, parentPkg);
+             kapp->processEvents();
+             UMLDatatype *dt = static_cast<UMLDatatype*>(o);
+             UMLClassifier *c = dynamic_cast<UMLClassifier*>(origType);
+@@ -187,10 +189,11 @@
+                 kdError() << "createUMLObject(" << name << "): "
+                 << "origType " << typeName << " is not a UMLClassifier"
+                 << endl;
+-            dt->setIsReference();
++            if (isRef || isPointer)
++                dt->setIsReference();
+             /*
+             if (isPointer) {
+-                UMLObject *pointerDecl = umldoc->createUMLObject(Uml::ot_Datatype, type);
++                UMLObject *pointerDecl = Object_Factory::createUMLObject(Uml::ot_Datatype, type);
+                 UMLDatatype *dt = static_cast<UMLDatatype*>(pointerDecl);
+                 dt->setOriginType(classifier);
+                 dt->setIsReference();
+--- umbrello/umbrello/package.cpp	(revision 490305)
++++ umbrello/umbrello/package.cpp	(revision 497528)
+@@ -23,6 +23,7 @@
+ #include "uml.h"
+ #include "umldoc.h"
+ #include "classifier.h"
++#include "object_factory.h"
+ #include "model_utils.h"
+ 
+ using namespace Uml;
+@@ -199,7 +200,7 @@
+                 return false;
+             continue;
+         }
+-        UMLObject *pObject = UMLDoc::makeNewUMLObject(type);
++        UMLObject *pObject = Object_Factory::makeObjectFromXMI(type);
+         if( !pObject ) {
+             kdWarning() << "UMLPackage::load: "
+             << "Unknown type of umlobject to create: "
+--- umbrello/umbrello/object_factory.h	(revision 0)
++++ umbrello/umbrello/object_factory.h	(revision 497528)
+@@ -0,0 +1,48 @@
++/***************************************************************************
++ *                                                                         *
++ *   This program is free software; you can redistribute it and/or modify  *
++ *   it under the terms of the GNU General Public License as published by  *
++ *   the Free Software Foundation; either version 2 of the License, or     *
++ *   (at your option) any later version.                                   *
++ *                                                                         *
++ *  copyright (C) 2006                                                     *
++ *  Umbrello UML Modeller Authors <uml-devel@ uml.sf.net>                  *
++ ***************************************************************************/
++
++#ifndef OBJECT_FACTORY__H
++#define OBJECT_FACTORY__H
++
++#include <qstring.h>
++#include "umlnamespace.h"
++
++class UMLObject;
++class UMLPackage;
++
++namespace Object_Factory {
++
++/**
++ * Creates a UMLObject of the given type.
++ *
++ * @param type      The type of @ref UMLObject to create.
++ * @param n         A name to give to the object (optional.)
++ *                  If not given then an input dialog prompts
++ *                  the user to supply a name.
++ * @param parentPkg The object's parent package (optional.)
++ * @param prepend   Set true if it is desired to prepend the new
++ *                  object to the list of objects.
++ *                  The default is to append.
++ */
++UMLObject* createUMLObject(Uml::Object_Type type,
++                           const QString &n = QString::null,
++                           UMLPackage *parentPkg = 0,
++                           bool prepend = false);
++
++/**
++ * Make a new UMLObject according to the given XMI tag.
++ * Used by loadFromXMI and clipboard paste.
++ */
++UMLObject* makeObjectFromXMI(const QString &xmiTag);
++
++}
++
++#endif
+--- umbrello/umbrello/objectwidget.cpp	(revision 490305)
++++ umbrello/umbrello/objectwidget.cpp	(revision 497528)
+@@ -27,6 +27,8 @@
+ #include "uml.h"
+ #include "umlobject.h"
+ #include "listpopupmenu.h"
++#include "docwindow.h"
++#include "dialogs/classpropdlg.h"
+ 
+ /**
+  * The number of pixels margin between the lowest message
+@@ -100,7 +102,7 @@
+             break;
+         }
+     case ListPopupMenu::mt_Properties:
+-        UMLApp::app()->getDocument() -> showProperties(this);
++        showProperties();
+         updateComponentSize();
+         moveEvent( 0 );
+         update();
+@@ -197,6 +199,19 @@
+     }
+ }
+ 
++bool ObjectWidget::showProperties() {
++    DocWindow *docwindow = UMLApp::app()->getDocWindow();
++    docwindow->updateDocumentation(false);
++    ClassPropDlg *dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this);
++    bool modified = false;
++    if (dlg->exec()) {
++        docwindow->showDocumentation(this, true);
++        UMLApp::app()->getDocument()->setModified(true);
++        modified = true;
++    }
++    dlg->close(true);//wipe from memory
++    return modified;
++}
+ 
+ void ObjectWidget::drawObject(QPainter & p, int offsetX, int offsetY) {
+ 
+--- umbrello/umbrello/adaimport.h	(revision 490305)
++++ umbrello/umbrello/adaimport.h	(revision 497528)
+@@ -24,10 +24,16 @@
+     AdaImport();
+     virtual ~AdaImport();
+ 
++protected:
+     /**
++     * Reimplement operation from NativeImportBase.
++     */
++    void initVars();
++
++    /**
+      * Implement abstract operation from NativeImportBase.
+      */
+-    void parseFile(QString file);
++    bool parseStmt();
+ 
+     /**
+      * Implement abstract operation from NativeImportBase.
+@@ -40,6 +46,7 @@
+      */
+     bool preprocess(QString& line);
+ 
++    bool m_inGenericFormalPart; ///< auxiliary variable
+ };
+ 
+ #endif
+--- umbrello/umbrello/classifier.h	(revision 490305)
++++ umbrello/umbrello/classifier.h	(revision 497528)
+@@ -432,6 +432,15 @@
+      */
+     bool hasAbstractOps ();
+ 
++    /**
++     * Create a new ClassifierListObject (attribute, operation, template)
++     * according to the given XMI tag.
++     * Returns NULL if the string given does not contain one of the tags
++     * <UML:Attribute>, <UML:Operation>, or <UML:TemplateParameter>.
++     * Used by the clipboard for paste operation.
++     */
++    UMLClassifierListItem* makeChildObject(QString xmiTag);
++
+ signals:
+     /** Signals that a new UMLOperation has been added to the classifer.
+      */
+--- umbrello/umbrello/objectwidget.h	(revision 490305)
++++ umbrello/umbrello/objectwidget.h	(revision 497528)
+@@ -143,6 +143,13 @@
+     void cleanup();
+ 
+     /**
++     * Show a properties dialog for an ObjectWidget.
++     *
++     * @return  True if we modified the object.
++     */
++    bool showProperties();
++
++    /**
+      * Returns whether to draw as an Actor or not.
+      *
+      * @return  True if widget is drawn as an actor.
+--- umbrello/umbrello/nativeimportbase.h	(revision 490305)
++++ umbrello/umbrello/nativeimportbase.h	(revision 497528)
+@@ -23,6 +23,21 @@
+ /**
+  * Intermediate base class for native Umbrello implementations of
+  * programming language import
++ *
++ * The default call sequence is as follows (RealizedLanguageImport
++ * is used as a placeholder name for the concrete language importer.)
++ *   NativeImportBase                      RealizedLanguageImport
++ * --> importFiles()
++ *       parseFile()
++ *         -----------------------------------> initVars()
++ *         scan()
++ *           preprocess() (may be reimplemented)
++ *           ---------------------------------> fillSource()
++ *         -----------------------------------> parseStmt()
++ * This sequence may be changed by overriding default implementations
++ * of virtual methods in NativeImportBase.
++ *
++ * @short Base class for native implementations of language import
+  * @author Oliver Kellogg <okellogg at users.sourceforge.net>
+  * Bugs and comments to uml-devel at lists.sf.net or http://bugs.kde.org
+  */
+@@ -40,20 +55,27 @@
+      */
+     void importFiles(QStringList files);
+ 
+-protected:
+     /**
+      * Import a single file.
+-     * To be provided by the programming language specific code import
+-     * implementation class.
++     * The default implementation should be feasible for languages that
++     * don't depend on an external preprocessor.
+      *
+      * @param file  The file to import.
+      */
+-    virtual void parseFile(QString file) = 0;
++    virtual void parseFile(QString filename);
+ 
++protected:
+     /**
++     * Initialize auxiliary variables.
++     * This is called by the default implementation of parseFile()
++     * after scanning (before parsing the QStringList m_source.)
++     * The default implementation is empty.
++     */
++    virtual void initVars();
++
++    /**
+      * Scan a single line.
+-     * The specific importer class is expected to call this for each line
+-     * read from the input file.
++     * parseFile() calls this for each line read from the input file.
+      * This in turn calls other methods such as preprocess() and fillSource().
+      *
+      * @param line  The line to scan.
+@@ -82,6 +104,16 @@
+     virtual void fillSource(QString word) = 0;
+ 
+     /**
++     * Parse the statement which starts at m_source[m_srcIndex]
++     * leaving m_srcIndex pointing to the end of the recogized
++     * statement.
++     * To be provided by the concrete importer.
++     *
++     * @return   True if the statement was recognized.
++     */
++    virtual bool parseStmt() = 0;
++
++    /**
+      * Advance m_srcIndex until m_source[m_srcIndex] contains the lexeme
+      * given by `until'.
+      */
+@@ -90,7 +122,7 @@
+     /**
+      * Advance m_srcIndex until m_source[m_srcIndex] contains a non-comment.
+      * Comments encountered during advancement are accumulated in `m_comment'.
+-     * if m_srcIndex hits the end of m_source then QString::null is returned.
++     * If m_srcIndex hits the end of m_source then QString::null is returned.
+      */
+     QString advance();
+ 
+--- umbrello/umbrello/umllistview.cpp	(revision 490305)
++++ umbrello/umbrello/umllistview.cpp	(revision 497528)
+@@ -485,7 +485,7 @@
+         umlType = object->getBaseType();
+ 
+         if ( typeIsCanvasWidget(lvt) ) {
+-            m_doc->showProperties(object, ClassPropDlg::page_gen);
++            object->showProperties(ClassPropDlg::page_gen);
+         } else if(umlType == Uml::ot_Attribute) {
+             // show the attribute dialogue
+             UMLAttribute* selectedAttribute = static_cast<UMLAttribute*>(object);
+@@ -1082,7 +1082,7 @@
+     //FIXME for entityattributes
+ 
+     if(object)
+-        m_doc -> showProperties(object, page);
++        object->showProperties(page);
+     item -> cancelRename( 0 );//double click can cause it to go into rename mode.
+ }
+ 
+@@ -2048,61 +2048,61 @@
+         break;
+ 
+     case Uml::lvt_Actor:
+-        name = m_doc->uniqObjectName( Uml::ot_Actor );
++        name = Model_Utils::uniqObjectName( Uml::ot_Actor );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject *)0 );
+         newItem -> setPixmap( 0, getPixmap( it_Actor ) );
+         break;
+ 
+     case Uml::lvt_Class:
+-        name = m_doc->uniqObjectName( Uml::ot_Class);
++        name = Model_Utils::uniqObjectName( Uml::ot_Class);
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject *)0 );
+         newItem -> setPixmap( 0, getPixmap( it_Class ) );
+         break;
+ 
+     case Uml::lvt_Package:
+-        name = m_doc->uniqObjectName( Uml::ot_Package );
++        name = Model_Utils::uniqObjectName( Uml::ot_Package );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject *)0 );
+         newItem->setPixmap( 0, getPixmap( it_Package ) );
+         break;
+ 
+     case Uml::lvt_Component:
+-        name = m_doc->uniqObjectName( Uml::ot_Component );
++        name = Model_Utils::uniqObjectName( Uml::ot_Component );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject *)0 );
+         newItem->setPixmap( 0, getPixmap( it_Component ) );
+         break;
+ 
+     case Uml::lvt_Node:
+-        name = m_doc->uniqObjectName( Uml::ot_Node );
++        name = Model_Utils::uniqObjectName( Uml::ot_Node );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject *)0 );
+         newItem->setPixmap( 0, getPixmap( it_Node ) );
+         break;
+ 
+     case Uml::lvt_Artifact:
+-        name = m_doc->uniqObjectName( Uml::ot_Artifact );
++        name = Model_Utils::uniqObjectName( Uml::ot_Artifact );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject *)0 );
+         newItem->setPixmap( 0, getPixmap( it_Artifact ) );
+         break;
+ 
+     case Uml::lvt_Interface:
+-        name = m_doc->uniqObjectName( Uml::ot_Interface );
++        name = Model_Utils::uniqObjectName( Uml::ot_Interface );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject*)0 );
+         newItem->setPixmap( 0, getPixmap( it_Interface ) );
+         break;
+ 
+     case Uml::lvt_Datatype:
+-        name = m_doc->uniqObjectName( Uml::ot_Datatype );
++        name = Model_Utils::uniqObjectName( Uml::ot_Datatype );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject*)0 );
+         newItem->setPixmap( 0, getPixmap( it_Datatype ) );
+         break;
+ 
+     case Uml::lvt_Enum:
+-        name = m_doc->uniqObjectName( Uml::ot_Enum );
++        name = Model_Utils::uniqObjectName( Uml::ot_Enum );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject*)0 );
+         newItem->setPixmap( 0, getPixmap( it_Enum ) );
+         break;
+ 
+     case Uml::lvt_Entity:
+-        name = m_doc->uniqObjectName( Uml::ot_Entity );
++        name = Model_Utils::uniqObjectName( Uml::ot_Entity );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject*)0 );
+         newItem->setPixmap( 0, getPixmap( it_Entity ) );
+         break;
+@@ -2132,7 +2132,7 @@
+             break;
+         }
+     case Uml::lvt_UseCase:
+-        name = m_doc->uniqObjectName( Uml::ot_UseCase );
++        name = Model_Utils::uniqObjectName( Uml::ot_UseCase );
+         newItem = new UMLListViewItem( parentItem, name, type, (UMLObject *)0 );
+         newItem -> setPixmap( 0, getPixmap( it_UseCase ) );
+         break;
+--- umbrello/umbrello/main.cpp	(revision 490305)
++++ umbrello/umbrello/main.cpp	(revision 497528)
+@@ -45,7 +45,7 @@
+ int main(int argc, char *argv[]) {
+     KAboutData aboutData( "umbrello", I18N_NOOP("Umbrello UML Modeller"),
+                           UMBRELLO_VERSION, description, KAboutData::License_GPL,
+-                          I18N_NOOP("(c) 2001 Paul Hensgen, (c) 2002-2005 Umbrello UML Modeller Authors"), 0,
++                          I18N_NOOP("(c) 2001 Paul Hensgen, (c) 2002-2006 Umbrello UML Modeller Authors"), 0,
+                           "http://uml.sf.net/");
+     aboutData.addAuthor("Paul Hensgen",0, "phensgen at users.sourceforge.net");
+     aboutData.addAuthor(I18N_NOOP("Umbrello UML Modeller Authors"), 0, "uml-devel at lists.sourceforge.net");
+--- umbrello/umbrello/forkjoinwidget.h	(revision 490305)
++++ umbrello/umbrello/forkjoinwidget.h	(revision 497528)
+@@ -79,7 +79,7 @@
+      * Although the ForkJoinWidget supports resizing, we suppress the
+      * resize corner because it is too large for this very slim widget.
+      */
+-    void drawSelected(QPainter * p, int offsetX, int offsetY, bool resizeable = true);
++    void drawSelected(QPainter * p, int offsetX, int offsetY);
+ 
+     /**
+     * Overrides the function from UMLWidget.
+--- umbrello/umbrello/operation.cpp	(revision 490305)
++++ umbrello/umbrello/operation.cpp	(revision 497528)
+@@ -35,14 +35,14 @@
+         setTypeName( rt );
+     m_Vis = s;
+     m_BaseType = Uml::ot_Operation;
+-    m_List.setAutoDelete(false);
++    m_bConst = false;
+ }
+ 
+ UMLOperation::UMLOperation(const UMLClassifier * parent)
+         : UMLClassifierListItem (parent)
+ {
+     m_BaseType = Uml::ot_Operation;
+-    m_List.setAutoDelete(false);
++    m_bConst = false;
+ }
+ 
+ UMLOperation::~UMLOperation() {
+@@ -271,6 +271,14 @@
+     return (isConstructorOperation() || isDestructorOperation());
+ }
+ 
++void UMLOperation::setConst(bool b) {
++    m_bConst = b;
++}
++
++bool UMLOperation::getConst() const {
++    return m_bConst;
++}
++
+ bool UMLOperation::showPropertiesDialogue(QWidget* parent) {
+     UMLOperationDialog dialogue(parent, this);
+     return dialogue.exec();
+@@ -278,6 +286,7 @@
+ 
+ void UMLOperation::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
+     QDomElement operationElement = UMLObject::save("UML:Operation", qDoc);
++    operationElement.setAttribute( "isQuery", m_bConst ? "true" : "false" );
+     QDomElement featureElement = qDoc.createElement( "UML:BehavioralFeature.parameter" );
+     if (m_pSecondary) {
+         QDomElement retElement = qDoc.createElement("UML:Parameter");
+@@ -287,7 +296,6 @@
+         retElement.setAttribute( "kind", "return" );
+         featureElement.appendChild( retElement );
+     } else {
+-        //operationElement.setAttribute( "type", m_SecondaryId );
+         kdDebug() << "UMLOperation::saveToXMI: m_SecondaryId is "
+         << m_SecondaryId << endl;
+     }
+@@ -331,6 +339,12 @@
+             }
+         }
+     }
++    QString isQuery = element.attribute( "isQuery", "" );
++    if (!isQuery.isEmpty()) {
++        // We need this extra test for isEmpty() because load() might have been
++        // called again by the processing for BehavioralFeature.parameter (see below)
++        m_bConst = (isQuery == "true");
++    }
+     QDomNode node = element.firstChild();
+     if (node.isComment())
+         node = node.nextSibling();
+--- umbrello/umbrello/classimport.cpp	(revision 0)
++++ umbrello/umbrello/classimport.cpp	(revision 497528)
+@@ -0,0 +1,37 @@
++/***************************************************************************
++ *                                                                         *
++ *   This program is free software; you can redistribute it and/or modify  *
++ *   it under the terms of the GNU General Public License as published by  *
++ *   the Free Software Foundation; either version 2 of the License, or     *
++ *   (at your option) any later version.                                   *
++ *                                                                         *
++ *  copyright (C) 2006                                                     *
++ *  Umbrello UML Modeller Authors <uml-devel@ uml.sf.net>                  *
++ ***************************************************************************/
++
++// own header
++#include "classimport.h"
++// qt/kde includes
++#include <qregexp.h>
++// app includes
++#include "idlimport.h"
++#include "pythonimport.h"
++#include "javaimport.h"
++#include "adaimport.h"
++#include "cppimport.h"
++
++ClassImport *ClassImport::createImporterByFileExt(QString filename) {
++    ClassImport *classImporter;
++    if (filename.endsWith(".idl"))
++        classImporter = new IDLImport();
++    else if (filename.endsWith(".py"))
++        classImporter = new PythonImport();
++    else if (filename.endsWith(".java"))
++        classImporter = new JavaImport();
++    else if (filename.contains( QRegExp("\\.ad[sba]$") ))
++        classImporter = new AdaImport();
++    else
++        classImporter = new CppImport();  // the default.
++    return classImporter;
++}
++
+--- umbrello/umbrello/entitywidget.cpp	(revision 490305)
++++ umbrello/umbrello/entitywidget.cpp	(revision 497528)
+@@ -22,6 +22,7 @@
+ #include "umldoc.h"
+ #include "uml.h"
+ #include "listpopupmenu.h"
++#include "model_utils.h"
+ 
+ #include <kdebug.h>
+ #include <qpainter.h>
+@@ -180,7 +181,7 @@
+ void EntityWidget::slotMenuSelection(int sel) {
+     switch(sel) {
+     case ListPopupMenu::mt_EntityAttribute:
+-        if ( UMLApp::app()->getDocument()->createChildObject(m_pObject, Uml::ot_EntityAttribute) )  {
++        if (Model_Utils::createChildObject(m_pObject, Uml::ot_EntityAttribute) )  {
+             UMLApp::app()->getDocument()->setModified();
+         }
+         break;
+--- umbrello/umbrello/umlview.cpp	(revision 490305)
++++ umbrello/umbrello/umlview.cpp	(revision 497528)
+@@ -88,9 +88,9 @@
+ #include "umlobjectlist.h"
+ #include "association.h"
+ #include "attribute.h"
+-
++#include "model_utils.h"
++#include "object_factory.h"
+ #include "umlwidget.h"
+-
+ #include "toolbarstatefactory.h"
+ 
+ 
+@@ -2847,58 +2847,58 @@
+ 
+     case ListPopupMenu::mt_UseCase:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject( ot_UseCase );
++        Object_Factory::createUMLObject( ot_UseCase );
+         break;
+ 
+     case ListPopupMenu::mt_Actor:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject( ot_Actor );
++        Object_Factory::createUMLObject( ot_Actor );
+         break;
+ 
+     case ListPopupMenu::mt_Class:
+     case ListPopupMenu::mt_Object:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject( ot_Class);
++        Object_Factory::createUMLObject( ot_Class);
+         break;
+ 
+     case ListPopupMenu::mt_Package:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject(ot_Package);
++        Object_Factory::createUMLObject(ot_Package);
+         break;
+ 
+     case ListPopupMenu::mt_Component:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject(ot_Component);
++        Object_Factory::createUMLObject(ot_Component);
+         break;
+ 
+     case ListPopupMenu::mt_Node:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject(ot_Node);
++        Object_Factory::createUMLObject(ot_Node);
+         break;
+ 
+     case ListPopupMenu::mt_Artifact:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject(ot_Artifact);
++        Object_Factory::createUMLObject(ot_Artifact);
+         break;
+ 
+     case ListPopupMenu::mt_Interface:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject(ot_Interface);
++        Object_Factory::createUMLObject(ot_Interface);
+         break;
+ 
+     case ListPopupMenu::mt_Enum:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject(ot_Enum);
++        Object_Factory::createUMLObject(ot_Enum);
+         break;
+ 
+     case ListPopupMenu::mt_Entity:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject(ot_Entity);
++        Object_Factory::createUMLObject(ot_Entity);
+         break;
+ 
+     case ListPopupMenu::mt_Datatype:
+         m_bCreateObject = true;
+-        m_pDoc->createUMLObject(ot_Datatype);
++        Object_Factory::createUMLObject(ot_Datatype);
+         break;
+ 
+     case ListPopupMenu::mt_Cut:
+--- umbrello/VERSION	(revision 490305)
++++ umbrello/VERSION	(revision 497528)
+@@ -1 +1 @@
+-1.5
++1.5.1
+--- umbrello/ChangeLog	(revision 490305)
++++ umbrello/ChangeLog	(revision 497528)
+@@ -1,7 +1,7 @@
+ Version 1.5.1
+ 
+ * Bugs fixed / wishes implemented (see http://bugs.kde.org)
+-109963 117791 117875 117990 118570
++109963 117791 117875 117990 118570 118719
+ 
+ Version 1.5
+ 
+--- scripts/licensecheck	(revision 490305)
++++ scripts/licensecheck	(revision 497528)
+@@ -2,7 +2,7 @@
+ #
+ # License checker for source files
+ 
+-# This should kept in sync with CVSROOT/loginfo.pl
++# This should kept in sync with kde-common/svn/hooks/post-commit.pl
+ sub checklicense($)
+ {
+    my ($text) = @_;
+@@ -18,22 +18,27 @@
+    $license = "";
+    $massave = "";
+ 
++   $gl = " (v2)" if ($text =~ /version 2 as published by the Free Software Foundation/);
+    $gl = " (v2+)" if ($text =~ /either version 2 of the License, or .at your option. any later version/);
+    $gl = " (v2.1)" if ($text =~ /version 2\.1 as published by the Free Software Foundation/);
++   $gl = " (v2.1+)" if ($text =~ /either version 2\.1 of the License, or .at your option. any later version/);
+    $qte = " (+Qt exception)" if ($text =~ /([Pp]ermission is given|[pP]ermission is also granted|[pP]ermission) to link (the code of )?this program with (any edition of )?(Qt|the Qt library)/);
+-   $massave = " (wrong address)" if ($text =~ /675 Mass Ave/i);
++   $massave = " (wrong address)" if ($text =~ /(?:675 Mass Ave|59 Temple Place|51 Franklin Steet|02139|02111-1307)/i); # "51 Franklin Street, 02110-1301" is the right FSF address
+ 
+    $license="GENERATED FILE" if ($text =~ /(All changes made in this file will be lost|DO NOT EDIT|DO NOT delete this file|[Gg]enerated by)/);
+-   $license="LGPL$gl$massave $license" if ($text =~ /This (program|library) is free software you can redistribute it and.?or modify it under the terms of the GNU (Library|Lesser) General Public License/);
+-   $license="GPL$gl$qte$massave $license" if ($text =~ /is free software you can redistribute it and.?or modify it under the terms of the GNU General Public License/);
++   $license="LGPL$gl$massave $license" if ($text =~ /is free software.? you can redistribute it and.?or modify it under the terms of the GNU (Library|Lesser) General Public License/);
++   $license="GPL$gl$qte$massave $license" if ($text =~ /is free software.? you can redistribute it and.?or modify it under the terms of the GNU General Public License/);
++   ### FIXME if the license matches the next regexp, it will probably match the following one too.
+    $license="QPL (part of Qt) $license" if ($text =~ /This file is part of the .*Qt GUI Toolkit. This file may be distributed under the terms of the Q Public License as defined/);
+    $license="QPL $license" if ($text =~ /may be distributed under the terms of the Q Public License as defined by Trolltech AS/);
+    $license="X11 (BSD like) $license" if($text =~ /Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files .the Software., to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and.?or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED AS IS/);
++   $license="BSD $license" if ($text =~ /THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE/);
+    $license="MPL 1.1 $license" if ($text =~ /subject to the Mozilla Public License Version 1.1/);
+    $license="no copyright $license" if ($text !~ /copyright/i);
+    $license="UNKNOWN" if(!length($license));
+ 
+    $license =~ s/ $//;
++
+    return "$license";
+ }
+ 
+--- scripts/README	(revision 490305)
++++ scripts/README	(revision 497528)
+@@ -1,35 +1,121 @@
+ 
+ Stuff in this directory:
+ 
++=== DEBUGGING SUPPORT
++
+ adddebug        Modifies the Makefile to add debug info (-g)
+ 
+-add_trace	Modifies a source file to add a trace as the first line
++add_trace.pl	Modifies a source file to add a trace as the first line
+ 		of every method, using kdDebug, and showing args values.
+ 
+-authors2xml	Extract author information from C++ files and print it out
+-		in DocBook format as a list
++kDebug2kdDebug.sh Script to convert old KDE debugging statements to their
++		modern equivalents.
+ 
++extend_dmalloc	Script to run gdb on return-addresses
++
++kdekillall	Kills the process "kdeinit: <process> with signal <signal>
++
++=== PROGRAMMING SUPPORT
++
+ cheatmake	Helper for saving time when recompiling, skipping files that
+ 		haven't changed in a meaningful way (e.g. if you only change
+ 		a comment...)
+ 
+-check_licenses	
++check_licenses	Old license checker for source files
++                (Use licensecheck instead)
+ 
+ licensecheck	Simple license checker for source files
+ 
++create_makefile Create the Makefile in a directory containing a Makefile.am
++                Saves time compared to re-running configure completely 
++
++create_makefiles The recursive version of it - needs create_makefile.
++
++fixheaders      Adds header files as it recognices make error output
++
++fixkdeincludes	Tries to reduce the number of includes in KDE source files
++
++fixuifiles	Fixes up Qt Designer .ui files (version, accels, generated names)
++		To use before any commit of a .ui file.
++
++fixfsfaddr.sed  Script for sed to fix old FSF addresses
++
++includemocs	Adds missing "#include foobar.moc" lines
++
++kdedoc		Open a kde help page in kfm/konqueror
++
++qtdoc		Open a qt help page in kfm/konqueror
++
++kde-spellcheck.pl A script to check source code for misspelings and optionally
++		correct them.
++
++=== MODERNIZATION SCRIPTS
++
++rc2kcfgxt.pl	Reads an existing KConfig rc file and creates a best-guess
++		version of a KConfigXT XML file.
++
++kdelnk2desktop.py Converts old-style .kdelnk files to their modern .desktop
++		equivalents.
++
++=== USEFUL DATA FOR EXTERNAL PROGRAMS
++
++kde-devel-emacs.el An emacs file that contains many helpful functions and keybindings
++		A must for anyone using [X]Emacs to develop KDE/Qt/C++ applications.
++
++kde-devel-gdb	A gdb macro definition file, to e.g. print QStrings from gdb.
++
++kde-devel-vim.vim A vim script that contains many helpful functions and keybindings
++		for vim-using KDE developers.
++
++kde.supp	Some valgrind suppressions handy for ignoring stuff we don't
++		care about when valgrinding kde applications
++
++completions/	Contains useful scripts to enhance the auto-complete feature of some shells.
++
++=== INFORMATION EXTRACTION
++
++alldcop.rb	Shows an pseudo-XML representation of the DCOP interfaces for
++		currently-running KDE applications.  Does not require
++		Korundum.
++
++authors2xml.pl	Extract author information from C++ files and print it out
++		in DocBook format as a list
++
+ makeobj		Script around make which basicly checks if it's in srcdir
+ 		or in builddir and changes to the right directory for
+ 		calling /usr/bin/make
+ 
+-colorcvs
++extractrc	Extract text tags from designer's UI files and XML GUI-RC files
+ 
+-create_makefile Create the Makefile in a directory containing a Makefile.am
+-                Saves time compared to re-running configure completely 
++extractattr	Same as extractrc, but for use by Scripty.
+ 
+-create_makefiles The recursive version of it - needs create_makefile.
++findmissingcrystal Looks at Crystal icons to find ones which are still
++		unchanged from kdeclassic.
+ 
++zonetab2pot.py  Reads timezone list as its first argument or from
++		/usr/share/zoneinfo/zone.tab, and converts it to a PO file
++		template.
++
++kdemangen.pl	Script to use the output from a KDE application's --author and
++		--help-all output to automatically generate a man page for the
++		application.
++
++png2mng.pl	Script to convert a series of numbered .png files into a .mng
++		animation.
++
++package_crystalsvg Script to package all svg files recursively from the current
++		directory.
++
++=== SOURCE CONTROL UTILITIES (CVS and Subversion)
++=== All CVS utilities have a corresponding svn version.
++
++colorcvs        Colorizes cvs commands.
++
+ create_cvsignore Create a .cvsignore file (using the contents of Makefile.am)
+ 
++cvs-clean	Recursively wipes out everything not registered in the CVS
++		server, starting from the current directory.
++
+ cvs2dist	Create a standalone source distribution tarball for an app
+ 		in a KDE CVS module.
+ 
+@@ -40,10 +126,11 @@
+ 
+ cvsblame	Bonsai-like cvs annotate 
+ 
+-cvschanged	Check for edited or merged files in a checked out CVS module,
+-		without connecting to the CVS server.
++cvscheck	Offline check for status of files in a checked-out module.
+ 
+-cvscheck	Offline check for status of files in a checked-out
++cvsgettags	List the available CVS tags for a given set of files, or
++		recursively for all files and directories.  No equivalent for
++		svn.
+ 
+ noncvslist	List all files in a checked out CVS module that are unknown to
+ 		to the CVS server.
+@@ -53,13 +140,6 @@
+ cxxmetric	Counts lines of code, comments and blank space in C and C++
+ 		source files.
+ 
+-fixheaders      Adds header files as it recognices make error output
+-
+-fixkdeincludes	Tries to reduce the number of includes in KDE source files
+-
+-fixuifiles	Fixes up Qt Designer .ui files (version, accels, generated names)
+-		To use before any commit of a .ui file.
+-
+ cvslastchange   launches "cvs diff -u" to display the last applied changes for a
+                 given file. HEAD branch only.
+ 
+@@ -75,57 +155,28 @@
+ 
+ cvsforwardport  Forwardport the last commit in a branch to HEAD
+ 
+-gendebug        Generate C++/Qt code for printing debug output.
+-
+ pruneemptydirs	Detects stale source dirs in a CVS tree
+ 
+-kde-build       Updates and recompiles a local CVS tree
++cvslastreferenced Goes through the whole history of a file to find all modifications
++                referencing a specific string.  It's useful if you want to know
++                when a function has been removed/modified/added to a file if a
++                recent cvs annotate doesn't reference it anymore. 
+ 
++=== KDE BUILD SCRIPTS
++
++kde-build       Updates and recompiles a local CVS or Subversion tree
++
+ build-progress.sh Displays the progress of kde-build, times needed to complete each
+ 		step. And sets the titlebar of the terminal to the directory that
+ 		make is processing 
+ 
+-extractrc	Extract text tags from designer's UI files and XML GUI-RC files
++kdesvn-build	Updates and recompiles a local Subversion tree.
+ 
++=== OTHERS
++
+ gettext.patch	Patch for gettext-0.10.35 to give xgettext the functionality to
+ 		extract scoped messages
+ 
+-includemocs	Adds missing "#include foobar.moc" lines
+-
+-kde-devel-emacs.el An emacs file that contains many helpful functions and keybindings
+-		A must for anyone using [X]Emacs to develop KDE/Qt/C++ applications.
+-
+-kde-devel-gdb	A gdb macro definition file, to e.g. print QStrings from gdb.
+-
+-extend_dmalloc	Script to run gdb on return-addresses
+-
+-kde-devel-vim.vim 
+-
+-kde.supp	Some valgrind suppressions handy for ignoring stuff we don't
+-		care about when valgrinding kde applications
+-
+-kdecompile	Python script for compiling and installing a KDE package
+-
+-kdedoc		Open a kde help page in kfm/konqueror
+-
+-qtdoc		Open a qt help page in kfm/konqueror
+-
+-kdekillall	Kills the process "kdeinit: <process> with signal <signal>
+-
+-kdelnk2desktop
+-
+-zone		Reads timezone list as its first argument or from
+-		/usr/share/zoneinfo/zone.tab, and converts it to a PO file
+-		 template
+-
+-rc2kcfgxt.pl	Reads an existing KConfig rc file and creates a best-guess
+-		version of a KConfigXT XML file.
+-
+-cvslastreferenced Goes through the whole history of a file to find all modifications
+-                referencing a specific string.  It's useful if you want to know
+-                when a function has been removed/modified/added to a file if a
+-                recent cvs annotate doesn't reference it anymore. 
+-
+ ----------------
+ Looking to add a script?
+ 
+--- kcachegrind/kcachegrind/tips	(revision 490305)
++++ kcachegrind/kcachegrind/tips	(revision 497528)
+@@ -1,10 +1,10 @@
+ <tip category="KCachegrind|Help">
+ <html>
+-<p>...that the <em>What's this...</em> help for every GUI widget
++<p>...that the <em>What's This?</em> help for every GUI widget
+ in KCachegrind contains detailed usage information for this widget?
+-It is highly recommend to read at least these help texts on first
+-use. Request <em>What's this...</em> help by pressing
+-Shift-F1 and clicking on the widget.</p>
++It is highly recommended to read at least these help texts on first
++use. Request <em>What's This?</em> help by pressing
++Shift+F1 and clicking on the widget.</p>
+ </html>
+ </tip>
+ 
+--- kcachegrind/kcachegrind/tabview.cpp	(revision 490305)
++++ kcachegrind/kcachegrind/tabview.cpp	(revision 497528)
+@@ -574,7 +574,7 @@
+ 		 "<li>The Assembler tab presents annotated assembler code "
+ 		 "if trace information on instruction level "
+ 		 "is available.</li></ul>"
+-		 "For more information, see the <em>What's this</em> "
++		 "For more information, see the <em>What's This?</em> "
+ 		 "help of the corresponding tab widget</p>");
+ }
+ 
+--- doc/kbabel/preferences.docbook	(revision 490305)
++++ doc/kbabel/preferences.docbook	(revision 497528)
+@@ -18,62 +18,96 @@
+ </chapterinfo>
+ 
+ <title>Preferences</title>
+-<sect1 id="preferences-kbabel">
+-<title>&kbabel; preferences</title>
+ 
+-<para> To show the Preferences dialog choose
+-<menuchoice><guimenu>Settings</guimenu> <guimenuitem>Configure
+-KBabel...</guimenuitem></menuchoice> from &kbabel;'s menu.  It uses a
+-structured configuration dialog which makes it very easy to find an
+-option without having to perform an extensive search for it.</para>
+ 
+-<para>The left side of the preferences dialog lists the categories of
+-customizable items and the right side shows the corresponding tab for
+-the selected category.  &kbabel; keeps changes if you move between
+-categories, so when you're finally happy click the
+-<guibutton>OK</guibutton> button.  At any time you can use quick
+-help&mdash;just click on the question mark on the title bar and,
+-after the cursor has changed to an arrow with a question mark,
+-click on a button, label, or preference entry to find out more
+-about it.</para>
++<sect1 id="preferences-overview">
++<title>Global and project settings</title>
+ 
+-<sect2 id="preferences-identity">
+-<title>Identity</title>
++<para>
++From KBabel 1.10 (KDE 3.4) on, KBabel has the concept of projects and therefore
++the settings have been split in two categories:
++the global settings and the project settings (also called project configuration).
++</para>
+ 
+-<para>This section allows you to set standard fields for every
+-translated <acronym>PO</acronym> file.  These are your name, email
+-address, full language name, email address for your translation team
+-mailing list.  There is also a timezone field to track your
+-<quote>last modified</quote> time for <acronym>PO</acronym> files.
+-You can specify it as character sequence like <acronym>EEST</acronym>
+-or offset from <acronym>GMT</acronym> time like +0200 (&ie; for
+-Romania).  This information is used when updating file headers.  You
+-can find the options that control what fields in the header should be
+-updated in the <link linkend="preferences-save">Save</link> section of
+-the Preferences dialog.</para>
++<important><para>
++&GNU; gettext uses a term called "project", which has nothing to do with
++KBabel's projects. &GNU; gettext means by project an application which is
++related to the <acronym>PO</acronym> file. For KBabel, a project is
++much bigger. It can mean a set of applications, like &kde;.
++</para></important>
+ 
+-<warning><para>Character sequences for timezones are not standardized.
+-So you should not use the string set here in time specification for
+-saving in <link linkend="preferences-save">Save</link> tab. You should
+-use <literal>%z</literal> instead.</para></warning>
++<para>
++KBabel has <emphasis>always</emphasis> a current project, even if it is the
++default project. KBabel has not mode without any project. A project is always
++for KBabel's editor and KBabel's catalog manager.
++</para>
+ 
+-<variablelist>
+-<varlistentry>
+-<term><guilabel>Number of singular/plural forms</guilabel></term>
+-<listitem>
+-<para> Use this for setting number of plural forms for your
+-language. For example, it is 2 for German (one for the singular and
+-one for the plural form).</para>
+ 
+-<note><para>This feature is currently implemented only for plural forms format  used in &kde;. It does not work with gettext plural forms.</para></note> 
+-</listitem>
+-</varlistentry>
+-</variablelist>
++<sect2 id="preferences-limitations">
++<title>Known limitations of the current implementation</title>
+ 
++<para>
++Unfortunately the current implementation of projects has a few known problems.
++</para>
++
++<para>
++An example is that in the global settings, there is no setting for the default user,
++his/her default language and other similar important global user data. It means that such
++data must be entered again each time that a new project is created.
++</para>
++
++<para>
++Another problem is the new project wizard. It does not ask enough information, especially
++it fails to ask for the team email address. So it is recommended to check the project
++settings after having run the wizard.
++</para>
++
++<tip><para>
++Currently you cannot copy projects from inside KBabel, so apparently you cannot easily share good settings.
++However you are free to copy the project outside KBabel and to load the copied project into KBabel.
++</para></tip>
++
+ </sect2>
+ 
++<sect2 id="preferences-non-kde-projects">
++<title>Using KBabel for non-&kde; projects</title>
++
++<para>
++While &kbabel;'s defaults are oriented toward working with and for &kde;, &kbabel; can be used
++to translate <acronym>PO</acronym> files of other projects. However mostly you will have to tweak the
++settings to the need of your project. This is especially true for &GNU; and
++&GNU;-like projects, which need quite different defaults than for &kde;.
++</para>
++
++<para>
++One problem is that &kbabel; is relatively agressive when saving <acronym>PO</acronym> files and
++replaces setting of the <acronym>PO</acronym> files by settings of the projects, if not told otherwise.
++This might look very strange to somebody not used to &kde;. However &kde; has 900+
++<acronym>POT</acronym> files to translate for the <acronym>GUI</acronym> messages only.
++So for such a task, much automatisation is wanted. Taking time to set a project
++is little compared to the time gained thereafter. Of course, as non-&kde; user, you
++might be less fortunate. You need to do more settings, as the defaults are not entirely suitable
++and you will not gain much by doing many translations, as &GNU; projects have typically
++only one <acronym>POT</acronym> file to translate.
++</para>
++
++</sect2>
++
++</sect1>
++
++<sect1 id="preferences-global">
++<title>&kbabel; global settings</title>
++
++<para>
++To show the Preferences dialog choose
++<menuchoice><guimenu>Settings</guimenu> <guimenuitem>Configure
++KBabel...</guimenuitem></menuchoice> from &kbabel;'s menu.  It uses a
++structured configuration dialog which makes it very easy to find an
++option without having to perform an extensive search for it.
++</para>
++
+ <sect2 id="preferences-editor">
+-<title>Editor</title>
++<title>Edit</title>
+ <para>
+ The editor preferences category is divided in 3 subwindows:
+ <guilabel>General</guilabel>, <guilabel>Appearance</guilabel>,
+@@ -84,6 +118,16 @@
+ <sect3 id="preferences-editor-general">
+ <title>General</title>
+ 
++<screenshot>
++<screeninfo>Dialog Edit General</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_edit_general.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Dialog Edit General</phrase></textobject>
++</mediaobject>
++</screenshot>
++
+ <para>This section contains a set of checkboxes.</para>
+ 
+ <para>The first checkbox in the upper side sets if the fuzzy status is
+@@ -101,12 +145,14 @@
+ <keycap>Tab</keycap> and it allows special handling of
+ <keycap>Enter</keycap>.</para>
+ 
+-<para>The lower checkboxes are very useful in assisting, not for the
++<para>
++The lower checkboxes are very useful in assisting, not for the
+ correctness of the translation, but if the translated string
+ is a suitable replacement for the original.  For
+ example, many messages represent menu items with keyboard accelerator
+ and C-like formatted strings whose structure must remain intact once
+-translated.</para>
++translated.
++</para>
+ 
+ <variablelist>
+   <varlistentry>
+@@ -126,7 +172,7 @@
+ accelerator characters is identical in both the original and the
+ translated string.  Note that accelerator marker is &amp; (but not in
+ every programming toolkit). See the <link
+-linkend="preferences-miscellaneous">Miscellaneous</link> section below
++linkend="preferences-project-miscellaneous">Miscellaneous</link> section below
+ to find how to change a keyboard accelerator.</para>
+     </listitem>
+   </varlistentry>
+@@ -168,7 +214,9 @@
+     If you are translating &kde; project, it uses a special kind of 
+     syntax for specifying plural forms of messages. This check automatically
+     counts the number of forms in <acronym>msgstr</acronym> and
+-    compares it with the number specified in <link linkend="preferences-identity"><guilabel>Identity</guilabel></link> tab. Incorrect number of plural forms can result in crash of an application.
++    compares it with the number specified in
++<link linkend="preferences-project-identity"><guilabel>Identity</guilabel></link>
++tab. Incorrect number of plural forms can result in crash of an application.
+     </para>
+     </listitem>
+   </varlistentry>
+@@ -200,6 +248,16 @@
+ <sect3 id="preferences-editor-appearance">
+ <title>Appearance</title>
+ 
++<screenshot>
++<screeninfo>Dialog Edit Appearance</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_edit_appearance.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Dialog Edit Appearance</phrase></textobject>
++</mediaobject>
++</screenshot>
++
+ <para>
+ These options let
+ you configure the appearance for the message editor. In upper part there
+@@ -290,7 +348,8 @@
+     <listitem><para>
+      Keyboard accelerators start with (&amp;) <quote>ampersand</quote>
+      character in &kde; but if you are translating for other projects there might be an different character marking the accelerator key.
+-     See <link linkend="preferences-miscellaneous">Miscellaneous</link> section below to find how to change keyboard accelerator.
++See <link linkend="preferences-project-miscellaneous">Miscellaneous</link>
++section below to find how to change keyboard accelerator.
+     </para></listitem>
+   </varlistentry>
+ </variablelist>
+@@ -306,9 +365,123 @@
+ 
+ </sect3>
+ 
+-<sect3 id="preferences-editor-fonts">
++</sect2>
++
++<sect2 id="preferences-search">
++<title>Search</title>
++
++<screenshot>
++<screeninfo>Dialog Search</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_search.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Dialog Search</phrase></textobject>
++</mediaobject>
++</screenshot>
++
++<para>
++The search section allows you to customize various settings
++for searching in previously translated strings.
++</para>
++
++<para>General settings are common for all search types.  If you check
++the <guibutton>Automatically start search</guibutton> option then the
++search is automatically started whenever you switch to another entry
++in the editor.  Currently, there are three possibilities you can choose
++from, but since &kbabel; can use dictionary plugins the available
++dictionaries depend on those installed.  Using
++<menuchoice><guimenuitem>Settings</guimenuitem> <guimenuitem>Configure
++Dictionary</guimenuitem> <guimenuitem>...</guimenuitem></menuchoice>
++you can configure every search plugin.</para>
++
++<para>The dictionary plugins installed by default are:</para>
++
++<variablelist>
++<varlistentry>
++<term>&kde; Database Search Engine</term>
++<listitem>
++<para>This new method is still in alpha stage of development
++     and is based on &kbabeldict; which accompanies &kbabel;.
++     See &kbabeldict; documentation for further info on
++     configuring the search engine.
++  </para></listitem>
++</varlistentry>
++
++<varlistentry>
++<term>PO Compendium</term>
++<listitem><para>The compendium is a normal <acronym>PO</acronym> file,
++    which should contain a list of standard translations from your translation
++    team. If you don't have one, you can also use a file that contains all
++    the translations from your team (&eg; the <filename>$lang.messages</filename>
++    file in the  &kde; Project, that can be found at
++    <ulink url="http://i18n.kde.org/po_overview/">i18n.kde.org</ulink>).
++  </para></listitem>
++</varlistentry>
++
++<varlistentry>
++<term>PO Auxiliary</term>
++<listitem><para>The auxiliary should help you find the
++    context of a translation by looking up the same message in a message
++    catalog of the same package but translated to another language. This way
++    you can have a look how this message is translated in another language.
++  </para></listitem>
++</varlistentry>
++</variablelist>
++
++<para>
++You can also start searching manually by choosing an
++entry in the popup menu that appears, either by clicking
++<menuchoice>
++<guimenu>Dictionaries</guimenu><guimenuitem>Search Text</guimenuitem>
++<guimenuitem>PO Compendium</guimenuitem></menuchoice>
++or by keeping the search button on the toolbar pressed down for a while.
++</para>
++
++</sect2>
++
++<sect2 id="preferences-diffmode">
++<title>Diff</title>
++
++<screenshot>
++<screeninfo>Dialog Diff</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_diff.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Dialog Diff</phrase></textobject>
++</mediaobject>
++</screenshot>
++
++<para>The <guilabel>Diff</guilabel> section holds settings how to
++display differences in msgids. </para>
++
++<para>Every difference can be displayed by two added parts and by characters removed from the text. For both you can specify the method of display and the color to be used. <guilabel>Highlighted</guilabel> means that the background of the corresponding characters will be shown in the selected color, while 
++<guilabel>Underlined</guilabel>(for added characters) or <guilabel>Stroked Out</guilabel>
++(for removed characters) will denote the changed parts by colored lines.
++</para>
++<para>
++Diff mode needs to find the original <acronym>msgid</acronym> to compare
++with. For this purpose, &kbabel; can use the <link linkend="database">translation database</link>
++if you turn in on by enabling <guilabel>Use messages from Translation Database</guilabel>.
++A second possibility is to use a tree of original PO files and specifying the root of
++the tree in <guilabel>Base folder for diff files</guilabel>.
++</para>
++</sect2>
++
++<sect2 id="preferences-fonts">
+ <title>Fonts</title>
+ 
++<screenshot>
++<screeninfo>Dialog Fonts</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_fonts.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Dialog Fonts</phrase></textobject>
++</mediaobject>
++</screenshot>
++
+ <para>
+ This is a standard &kde; font chooser dialog with a little addition. You can
+ select to view only fixed fonts by checking the
+@@ -317,11 +490,196 @@
+ font family, style, size and encoding. The bottom box shows a preview of the
+ current font for user convenience.
+ </para>
+-</sect3>
+ </sect2>
+ 
+-<sect2 id="preferences-save">
++</sect1>
++
++<sect1 id="preferences-project-wizard">
++<title>New Project Wizard</title>
++
++<sect2 id="preferences-project-wizard-basic">
++<title>Page 1</title>
++
++<screenshot>
++<screeninfo>Project Wizard Page 1</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_wizard_page1.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Project Wizard Page 1</phrase></textobject>
++</mediaobject>
++</screenshot>
++
++<para>
++The first page of the wizard ask about the basic data of the project.
++</para>
++
++<variablelist>
++<varlistentry>
++<term><guilabel>Project name</guilabel></term>
++<listitem><para>
++Enter here the name of the project, as it will be displayed in &kbabel;'s menu.
++</para></listitem>
++</varlistentry>
++<varlistentry>
++<term><guilabel>Configuration file name</guilabel></term>
++<listitem><para>
++Select here a file for holding your project settings.
++</para></listitem>
++</varlistentry>
++<varlistentry>
++<term><guilabel>Language</guilabel></term>
++<listitem><para>
++Select or enter here the language name used by this project.
++</para></listitem>
++</varlistentry>
++<varlistentry>
++<term><guilabel>Project type</guilabel></term>
++<listitem><para>
++Select here the type of your project.
++</para></listitem>
++</varlistentry>
++</variablelist>
++
++</sect2>
++
++<sect2 id="preferences-project-wizard-catman">
++<title>Page 2</title>
++
++<screenshot>
++<screeninfo>Project Wizard Page 2</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_wizard_page2.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Project Wizard Page 2</phrase></textobject>
++</mediaobject>
++</screenshot>
++
++<para>
++The second page of the wizard asks about settings related to the
++Catalog Manager.
++</para>
++
++<variablelist>
++<varlistentry>
++<term><guilabel>Base folder for PO files</guilabel></term>
++<listitem><para>
++Select the base folder where your PO files are.
++</para></listitem>
++</varlistentry>
++<varlistentry>
++<term><guilabel>Base folder for POT files</guilabel></term>
++<listitem><para>
++Select the base folder where your POT files are.
++</para></listitem>
++</varlistentry>
++</variablelist>
++
++<para>
++Type in or select the folders that contains all your <acronym>PO</acronym> and respectively
++<acronym>POT</acronym> files. The files and the folders in these folders will then be
++merged into one tree in &catalogmanager; window.
++</para>
++
++
++</sect2>
++
++<sect2>
++<title>Checking Project Stettings</title>
++
++<important><para>
++As written earlier in this chapter, unfortunately the wizard is very simple and
++therefore fails to ask for some important settings.
++</para></important>
++
++<para>
++Now that you have <quote>finished</quote> your new project, you should verify the main settings in
++<menuchoice><guimenu>Project</guimenu> <guimenuitem>Configure...</guimenuitem></menuchoice>.
++Especially select the <guilabel>Identity</guilabel> page and fix the team email address in
++<guilabel>Language mailing list</guilabel>.
++(The default one created by the wizard from the language setting is only useful if you are part of a &GNU; project.)
++</para>
++
++<para>
++If the project settings are not for KDE, it is recommended that you check the
++<guilabel>Save</guilabel> page and checks the settings there.
++</para>
++
++</sect2>
++
++</sect1>
++
++<sect1 id="preferences-project-settings">
++<title>Project Settings</title>
++
++<para> To show the project setting dialog choose
++<menuchoice><guimenu>Project</guimenu> <guimenuitem>Configure...</guimenuitem></menuchoice>
++from &kbabel;'s or &catalogmanager;'s menu.  It uses a
++structured configuration dialog which makes it very easy to find an
++option without having to perform an extensive search for it.</para>
++
++<para>The left side of the preferences dialog lists the categories of
++customizable items and the right side shows the corresponding tab for
++the selected category.  &kbabel; keeps changes if you move between
++categories, so when you're finally happy click the
++<guibutton>OK</guibutton> button.  At any time you can use quick
++help&mdash;just click on the question mark on the title bar and,
++after the cursor has changed to an arrow with a question mark,
++click on a button, label, or preference entry to find out more
++about it.</para>
++
++<note><para>
++Pages for settings for &kbabel; (the editor) and for &catalogmanager;
++are in the list.
++</para></note>
++
++<sect2 id="preferences-project-identity">
++<title>Identity</title>
++
++<para>These settings are for &kbabel;.</para>
++
++<para>This section allows you to set standard fields for every
++translated <acronym>PO</acronym> file.  These are your name, email
++address, full language name, email address for your translation team
++mailing list.  There is also a timezone field to track your
++<quote>last modified</quote> time for <acronym>PO</acronym> files.
++You can specify it as character sequence like <acronym>EEST</acronym>
++or offset from <acronym>GMT</acronym> time like +0200 (&ie; for
++Romania).  This information is used when updating file headers.  You
++can find the options that control what fields in the header should be
++updated in the <link linkend="preferences-project-save">Save</link> section of
++the Preferences dialog.</para>
++
++<warning><para>Character sequences for timezones are not standardized.
++So you should not use the string set here in time specification for
++saving in <link linkend="preferences-project-save">Save</link> tab. You should
++use <literal>%z</literal> instead.</para></warning>
++
++<variablelist>
++<varlistentry>
++<term><guilabel>Number of singular/plural forms</guilabel></term>
++<listitem>
++<para> Use this for setting number of plural forms for your
++language. For example, it is 2 for German (one for the singular and
++one for the plural form).</para>
++
++<note><para>This feature is currently implemented only for plural forms format  used in &kde;. It does not work with &GNU; gettext plural forms.</para></note> 
++</listitem>
++</varlistentry>
++</variablelist>
++
++</sect2>
++
++<sect2 id="preferences-project-save">
+ <title>Save</title>
++
++<para>These settings are for &kbabel;.</para>
++
++<para><remark>
++TODO This seems to document only the "General" tab but not the "Header" and "Copyright" ones
++</remark></para>
++
+ <para>
+ This section allows you to edit the options for <acronym>PO</acronym> file saving. The first 
+ group of checkboxes controls general behavior for actions
+@@ -349,12 +707,12 @@
+ Check this to automatically check syntax of file with
+ <userinput><command>msgfmt</command> --statistics</userinput> when
+ saving a file. You will only get a message if an error occurred. You
+-should keep this validation enabled unless you know what you're doing.
++should keep this validation enabled unless you know what you are doing.
+     </para></listitem>
+   </varlistentry>
+ </variablelist>
+ 
+-<para>If you don't want to touch some fields in a <acronym>PO</acronym>
++<para>If you do not want to touch some fields in a <acronym>PO</acronym>
+ file header or want to force updating of specific fields, there are five
+ checkboxes which control this: revision date, <acronym>PO</acronym> file
+ language, text encoding, last translator name, charset. If a field
+@@ -366,9 +724,15 @@
+ want to have the header updated.</para>
+ 
+ <para>For date and time of the header field
+-<emphasis>PO-Revision-Date</emphasis> you can choose one from bellow
+-formats:</para>
++<emphasis>PO-Revision-Date</emphasis> you can choose one of the
++formats: <guilabel>Default</guilabel>, <guilabel>Local</guilabel>, <guilabel>Custom</guilabel>.</para>
+ 
++<important><para>
++You should keep the default setting of <guilabel>Default</guilabel>. The two other settings
++make that the generated <acronym>PO</acronym> file is not a standard &GNU; gettext <acronym>PO</acronym> file
++anymore, so this should be avoided.
++</para></important>
++
+ <itemizedlist>
+   <listitem><para>
+     <guilabel>Default</guilabel> is the format normally used in <acronym>PO</acronym> files.
+@@ -496,20 +860,32 @@
+   </para></listitem>
+ </itemizedlist>
+ 
++<note><para>
++The option to select the date format for the <acronym>PO</acronym> file is considered to be deprecated,
++and will probably be removed in a future version of KBabel.
++</para></note>
++
+ <para>The lower group covers encoding options for <acronym>PO</acronym>
+ files when saving. If you work on the &kde; project you should be aware
+-that at least <filename>desktop.po</filename> file
+-<emphasis>must</emphasis> be UTF-8 encoded. The drop-down list lets you select
+-message encoding. You must at least have your language code and UTF-8 encoding set.
+-If, for some reason, you don't want to accidentally change the current PO
++that at least <acronym>PO</acronym> files <emphasis>must</emphasis> be UTF-8 encoded in &kde;.
++Alternatively you can select the encoding corresponding to your locale.
++If, for some reason, you do not want to accidentally change the current PO
+ file encoding, turn on <guibutton>Keep the encoding of the
+ file</guibutton>.</para>
+ 
++<caution><para>
++For reason of informtation interchange, &GNU; gettext limits the encodings allowed for a
++<acronym>PO</acronym> file. &kbabel; does not know of this restriction, so the encoding
++correspondig to your locale might not be suitable. (UTF-8 is always supported by &GNU; gettext.)
++</para></caution>
++
+ </sect2>
+ 
+-<sect2 id="preferences-spellcheck">
++<sect2 id="preferences-project-spellcheck">
+ <title>Spell Check</title>
+ 
++<para>These settings are for &kbabel;.</para>
++
+ <para>Here you can set your spell checking preferences.  This is of 
+ interest if you have a dictionary file for the language you are 
+ translating to. Below are the items to consider setting:</para>
+@@ -543,13 +919,24 @@
+   </varlistentry>
+   <varlistentry>
+     <term><guilabel>Encoding</guilabel></term>
+-    <listitem><para>
++    <listitem>
++<para>
+     Here you choose the encoding for your text.  This option is passed
+     to the spellchecker, and is used as the encoding for your words
+     dictionary.
+     See the <ulink url="help:/kspell">kspell</ulink> documentation for
+     more details.
+-    </para></listitem>
++</para>
++<note><para>
++The encoding selected here is not linked to encodings of the
++<acronym>PO</acronym> files. Depending on the spellchecker
++(especially in the case of  <command>ispell</command>),
++you might not have much choice for the encoding.
++(For example, a few Western European languages can only work
++with <command>ispell</command> when using ISO-8859-1.)
++</para></note>
++    </listitem>
++
+   </varlistentry>
+   <varlistentry>
+     <term><guilabel>Client</guilabel></term>
+@@ -570,104 +957,190 @@
+     <listitem><para>    
+     Here you can set location of the file for ignored words. Click
+     on the folder icon to the right of the edit box.  The default is
+-    <filename>$(HOME)/.kde/share/apps/kbabel/spellignores</filename>,
+-    where <filename>$(HOME)</filename> is your home folder.
++    <filename>$<envar>HOME</envar>/.kde/share/apps/kbabel/spellignores</filename>,
++    where <filename>$<envar>HOME</envar></filename> is your home folder.
+     </para></listitem>
+   </varlistentry>
+ </variablelist>
+ </sect2>
+ 
+-<sect2 id="preferences-search">
+-<title>Search</title>
++<sect2 id="preferences-project-source">
++<title>Source reference</title>
++
++<para>These settings are for &kbabel;.</para>
++
++<screenshot>
++<screeninfo>Project Settings, source reference</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_proj_source.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Project Settings, source reference</phrase></textobject>
++</mediaobject>
++</screenshot>
++
+ <para>
+-The search section allows you to customize various settings
+-for searching in previously translated strings.
++This dialog is for setting how KBabel should construct the full path from each source references,
++which are in the comments of each entry of a <acronym>PO</acronym> file.
+ </para>
+ 
+-<sect3 id="preferences-search-general">
+-<title>General</title>
++<sect3>
++<title>Dialog elements</title>
+ 
+-<para>General settings are common for all search types.  If you check
+-the <guibutton>Automatically start search</guibutton> option then the
+-search is automatically started whenever you switch to another entry
+-in the editor.  Currently, there are three possibilities you can choose
+-from, but since &kbabel; can use dictionary plugins the available
+-dictionaries depend on those installed.  Using
+-<menuchoice><guimenuitem>Settings</guimenuitem> <guimenuitem>Configure
+-Dictionary</guimenuitem> <guimenuitem>...</guimenuitem></menuchoice>
+-you can configure every search plugin.</para>
++<para>
++In the edit line <guilabel>Base folder for source code</guilabel>, you can set a
++base folder where the source code of your project is. This defines the value of the variable
++<userinput>@CODEROOT@</userinput>, which is described below.
++</para>
+ 
+-<para>The dictionary plugins installed by default are:</para>
++<para>
++In the group <guilabel>Path Patterns</guilabel>, you can define patterns or rules
++to construct the paths with the help of a few variables:
++<userinput>@CODEROOT@</userinput>, <userinput>@PACKAGEDIR@</userinput>,
++<userinput>@PACKAGE@</userinput>, <userinput>@COMMENTPATH@</userinput>,
++<userinput>@POFILEDIR@</userinput>, which are defined below.
++</para>
+ 
+-<variablelist>
+-<varlistentry>
+-<term>&kde; Database Search Engine</term>
+-<listitem>
+-<para>This new method is still in alpha stage of development
+-     and is based on &kbabeldict; which accompanies &kbabel;.
+-     See &kbabeldict; documentation for further info on
+-     configuring the search engine.
+-  </para></listitem>
+-</varlistentry>
++<note><para>
++The variable <userinput>@PODIRFILE@</userinput> was introduced in &kbabel; version 1.11.1 (for &kde; 3.5.1).
++</para></note>
+ 
+-<varlistentry>
+-<term>PO Compendium</term>
+-<listitem><para>The compendium is a normal <acronym>PO</acronym> file,
+-    which should contain a list of standard translations from your translation
+-    team. If you don't have one, you can also use a file that contains all
+-    the translations from your team (&eg; the <filename>$lang.messages</filename>
+-    file in the  &kde; Project, that can be found at
+-    <ulink url="http://i18n.kde.org/po_overview/">i18n.kde.org</ulink>).
+-  </para></listitem>
+-</varlistentry>
++<para>
++With the button <guibutton>Add</guibutton>, you can add the line from the text box
++to the list of used path patterns. With the button <guibutton>Remove</guibutton>,
++you can remove the selected pattern from the list. With the buttons
++<guibutton>Up</guibutton> and <guibutton>Down</guibutton>, you can change the priority of
++the path patterns.
++</para>
+ 
+-<varlistentry>
+-<term>PO Auxiliary</term>
+-<listitem><para>The auxiliary should help you find the
+-    context of a translation by looking up the same message in a message
+-    catalog of the same package but translated to another language. This way
+-    you can have a look how this message is translated in another language.
+-  </para></listitem>
+-</varlistentry>
+-</variablelist>
++</sect3>
+ 
++<sect3>
++<title>The variables</title>
++
++<itemizedlist>
++<listitem><para>
++<userinput>@CODEROOT@</userinput>: The base folder of the source code.
++</para></listitem>
++<listitem><para>
++<userinput>@PACKAGEDIR@</userinput>: The folder of the package (i.e. <acronym>PO</acronym> file).
++</para></listitem>
++<listitem><para>
++<userinput>@PACKAGE@</userinput>: The package name (i.e. <acronym>PO</acronym> file name without extension).
++</para></listitem>
++<listitem><para>
++<userinput>@POFILEDIR@</userinput>: The folder of the <acronym>PO</acronym> file.
++</para></listitem>
++<listitem><para>
++<userinput>@COMMENTPATH@</userinput>: The relative path given as source reference in the comment of an entry of the <acronym>PO</acronym> file.
++</para></listitem>
++</itemizedlist>
++
++<important><para>
++The variables <userinput>@PACKAGEDIR@</userinput> and <userinput>@POFILEDIR@</userinput> have similar
++meaning but not the same result. The variable <userinput>@POFILEDIR@</userinput>
++will always hold the folder of <acronym>PO</acronym> file,
++<userinput>@PACKAGEDIR@</userinput> might not. If the <acronym>PO</acronym> file was loaded
++by the help of the &catalogmanager; then <userinput>@PACKAGEDIR@</userinput> has only the part of
++the path, based on the <acronym>PO</acronym> base path defined for the &catalogmanager;
++<link linkend="preferences-project-folders">(see below)</link>.
++</para></important>
++
++<note><para>
++The variables <userinput>@CODEROOT@</userinput> and <userinput>@POFILEDIR@</userinput> can only be used at
++the beginning of a pattern to be useful. The variable <userinput>@COMMENTPATH@</userinput> can only be used at the
++end of a pattern and is nearly mandatory.
++The variables <userinput>@PACKAGEDIR@</userinput> and <userinput>@POFILEDIR@</userinput>
++should not be used in the same pattern. The variables <userinput>@CODEROOT@</userinput> and <userinput>@POFILEDIR@</userinput> should not be used in the same pattern either.
++</para></note>
++
++</sect3>
++
++<sect3>
++<title>The default path patterns</title>
++
+ <para>
+-You can also start searching manually by choosing an
+-entry in the popup menu that appears, either by clicking
+-<menuchoice>
+-<guimenu>Dictionaries</guimenu><guimenuitem>Search Text</guimenuitem>
+-<guimenuitem>PO Compendium</guimenuitem></menuchoice>
+-or by keeping the search button on the toolbar pressed down for a while.
++From &kbabel; 1.11.1 (of &kde; 3.5.1) on, there are five default path patterns:
+ </para>
++
++<itemizedlist>
++<listitem><para>
++<userinput>@PACKAGEDIR@</userinput>/<userinput>@PACKAGE@</userinput>/<userinput>@COMMENTPATH@</userinput>
++</para></listitem>
++<listitem><para>
++<userinput>@CODEROOT@</userinput>/<userinput>@PACKAGEDIR@</userinput>/<userinput>@PACKAGE@</userinput>/<userinput>@COMMENTPATH@</userinput>
++</para></listitem>
++<listitem><para>
++<userinput>@CODEROOT@</userinput>/<userinput>@PACKAGE@</userinput>/<userinput>@COMMENTPATH@</userinput>
++</para></listitem>
++<listitem><para>
++<userinput>@POFILEDIR@</userinput>/<userinput>@COMMENTPATH@</userinput>
++</para></listitem>
++<listitem><para>
++<userinput>@POFILEDIR@</userinput>/../<userinput>@COMMENTPATH@</userinput>
++</para></listitem>
++</itemizedlist>
++
++<note><para>
++&kde; projects need typically the third pattern.
++The last pattern is typical for &GNU; projects, where the source references are related to
++the parent of the directory where the PO file is.
++</para></note>
++
+ </sect3>
+ 
+-</sect2>
++<sect3>
++<title>Creating New Path Patterns</title>
+ 
+-<sect2 id="preferences-diffmode">
+-<title>Diff</title>
++<para>
++In most cases the default path patterns should be enough, whatever
++the project is for KDE (assuming that you have set the correct base directory)
++or if the project is a &GNU; one (or structured like a &GNU; project).
++</para>
+ 
+-<para>The <guilabel>Diff</guilabel> section holds settings how to
+-display differences in msgids. </para>
++<note><para>
++For &kde;, some <acronym>PO</acronym> files do not contain enough information
++(including the file path and name) for &kbabel; to find the right source file
++that is supposed to be refered. To fix that you would need precise path patterns
++for such files, which is nearly impossible to define by the numbers of such files
++in &kde;. But if you work often with such a file, may be it is worth to set
++a path pattern explicitely for supporting that <acronym>PO</acronym> file.
++</para></note>
+ 
+-<para>Every difference can be displayed by two added parts and by characters removed from the text. For both you can specify the method of display and the color to be used. <guilabel>Highlighted</guilabel> means that the background of the corresponding characters will be shown in the selected color, while 
+-<guilabel>Underlined</guilabel>(for added characters) or <guilabel>Stroked Out</guilabel>
+-(for removed characters) will denote the changed parts by colored lines.
++<para>
++For creating your own path patterns, you can use the variables defined above,
++but apart <userinput>@COMMENTPATH@</userinput> not any variable is mandatory to use.
++(To be exact, <userinput>@COMMENTPATH@</userinput> is not mandatory either,
++but not using it will probably lead to no result.)
+ </para>
++
+ <para>
+-Diff mode needs to find the original <acronym>msgid</acronym> to compare
+-with. For this purpose, &kbabel; can use the <link linkend="database">translation database</link>
+-if you turn in on by enabling <guilabel>Use messages from Translation Database</guilabel>.
+-A second possibility is to use a tree of original PO files and specifying the root of
+-the tree in <guilabel>Base folder for diff files</guilabel>.
++An example of path pattern could be that you want to display the source reference
++of &kde;'s file desktop_kdebase.po. In that case you will probably need a path  pattern like:
++<userinput>@CODEROOT@</userinput>/<userinput>@PACKAGEDIR@</userinput>/kdebase/<userinput>@COMMENTPATH@</userinput>
++(compared to one of the default path patterns, the sequence <userinput>@PACKAGE@</userinput> has been
++replaced by kdebase).
+ </para>
++
++<para>
++In case of really complex problems you can, of course, define an absolute path
++without any variables beside <userinput>@COMMENTPATH@</userinput>, like for example:
++/home/usr/kde-source/kdebase/<userinput>@COMMENTPATH@</userinput> assuming that
++/home/usr/kde-source/kdebase is the path where the kdebase source module is.
++</para>
++
++</sect3>
++
+ </sect2>
+ 
++<sect2 id="preferences-project-miscellaneous">
++<title>Miscellaneous</title>
+ 
+-<sect2 id="preferences-miscellaneous">
+-<title>Miscellaneous</title>
++<para>These settings are for &kbabel;.</para>
++
+ <para>
+ <guilabel>Miscellaneous</guilabel> section
+-holds settings which don't fit anywhere else. Currently there are two:
++holds &kbabel; settings that do not fit anywhere else.
+ </para>
+ 
+ <variablelist>
+@@ -701,22 +1174,17 @@
+ </variablelist>
+ </sect2>
+ 
++<!-- Catalog Manager project settings -->
+ 
+-</sect1>
++<sect2 id="preferences-project-folders">
++<title>Project folders</title>
+ 
+-<sect1 id="preferences-catalogmanager">
+-<title>&catalogmanager; preferences</title>
++<para>These settings are for &catalogmanager;.</para>
+ 
+ <para>
+-This dialog allows you to edit the options for the Catalog Manager.
+-</para>
+-
+-<sect2 id="preferences-catalogmanager-general">
+-<title>General</title>
+-<para>
+-Here are two edit lines with <guibutton>Browse...</guibutton> buttons.
+-Type in the folders which contains all your <acronym>PO</acronym>- and respectively
+-<acronym>POT</acronym>-files. The files and the folders in these folders will then be
++Here are two edit lines with folder buttons.
++Type in or select the folders that contains all your <acronym>PO</acronym> and respectively
++<acronym>POT</acronym> files. The files and the folders in these folders will then be
+ merged into one tree in Catalog Manager window.
+ </para>
+ 
+@@ -756,8 +1224,21 @@
+ </variablelist>
+ </sect2>
+ 
+-<sect2 id="preferences-catalogmanager-folders">
++<sect2 id="preferences-project-folder-commands">
+ <title>Folder Commands</title>
++
++<para>These settings are for &catalogmanager;.</para>
++
++<screenshot>
++<screeninfo>Project Settings,folder commands</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_proj_folder_commands.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Project Settings, folder commands</phrase></textobject>
++</mediaobject>
++</screenshot>
++
+ <para>
+ Here you can insert commands you want to execute in folders from the
+ Catalog Manager. The commands are then shown in the submenu
+@@ -765,8 +1246,8 @@
+ in the Catalog Manager's context menu.
+ 
+ </para><para>
+-Insert in the <guilabel>Name</guilabel> field the
+-name of the command. The name can be chosen freely and is only used to be displayed
++Insert in the <guilabel>Command Label</guilabel> field the
++label of the command. The label can be chosen freely and is only used to be displayed
+ in the menu. In the <guilabel>Command</guilabel> field insert the command you want to
+ have executed when selecting the corresponding menu item. Then press the <guibutton>Add</guibutton>
+ button to add the command to your available commands.
+@@ -810,8 +1291,21 @@
+ </para>
+ </sect2>
+ 
+-<sect2>
++<sect2 id="preferences-project-file-commands">
+ <title>File Commands</title>
++
++<para>These settings are for &catalogmanager;.</para>
++
++<screenshot>
++<screeninfo>Project Settings, file commands</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_proj_file_commands.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Project Settings, file commands</phrase></textobject>
++</mediaobject>
++</screenshot>
++
+ <para>
+ Here you can insert the commands you want to execute on files from the Catalog
+ Manager. The commands are then shown in the submenu
+@@ -820,7 +1314,7 @@
+ </para>
+ 
+ <para>
+-Insert in the <guilabel>Name</guilabel> field the name of the command. The name can be
++Insert in the <guilabel>Command Label</guilabel> field the label of the command. The label can be
+ chosen freely and is only used to be displayed in the menu. In the 
+ <guilabel>Command</guilabel> field insert the command you want to have executed when
+ selecting the corresponding menu item. Then press the <guibutton>Add</guibutton> button
+@@ -870,6 +1364,45 @@
+ from a file's context menu, the <acronym>PO</acronym> file will be merged with its template file.
+ </para>
+ </sect2>
++
++<sect2 id="preferences-project-catalog-manager">
++<title>Catalog Manager</title>
++
++<para>These settings are for &catalogmanager;.</para>
++
++<screenshot>
++<screeninfo>Project Settings, &catalogmanager;</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_proj_catman.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Project Settings, &catalogmanager;</phrase></textobject>
++</mediaobject>
++</screenshot>
++
++<para>The checkboxes switches on or off the corresponding column of the &catalogmanager;'s view.</para>
++
++</sect2>
++
++<sect2 id="preferences-project-diff">
++<title>Diff</title>
++
++<para>These settings are for &catalogmanager;.</para>
++
++<screenshot>
++<screeninfo>Project Settings, diff</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="pref_proj_diff.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Project Settings, diff</phrase></textobject>
++</mediaobject>
++</screenshot>
++
++<para><remark>TODO</remark></para>
++
++</sect2>
++
+ </sect1>
+ </chapter>
+ <!--
+--- doc/kbabel/catman.docbook	(revision 490305)
++++ doc/kbabel/catman.docbook	(revision 497528)
+@@ -38,6 +38,21 @@
+ entries, number of fuzzy entries, number of untranslated entries, the
+ date of the last revision and the last translator of the file.
+ </para>
++
++<important><para>
++KBabel's Catalog Manager is meant for projects structured like KDE,
++where the <acronym>POT</acronym> and <acronym>PO</acronym> files
++share a same name, save the extensions. However this is not the
++case of &GNU; projects and of many projects structured like &GNU; ones.
++Typically in such projects, the <acronym>PO</acronym> file is named
++following the language code and so is very different than the name
++of the <acronym>POT</acronym> files. Also such projects have
++one <acronym>POT</acronym> file sharing a directory with all its
++translated <acronym>PO</acronym> files. Unfortunately, all these reasons
++mean that the Catalog Manager is <emphasis>not</emphasis> suitable for
++such projects. (See <ulink url="http://bugs.kde.org/show_bug.cgi?id=76495">KDE bug #76495</ulink>.)
++</para></important>
++
+ <para>
+ To make it easier for you to find files that need work or are
+ missing the status of each file is also displayed using an icon:
+@@ -125,9 +140,9 @@
+ action="simul">&Ctrl;<keycap>O</keycap> </keycombo>.</para>
+ 
+ <para>You can configure the &catalogmanager; by
+-<menuchoice><guimenu>Settings</guimenu><guimenuitem>
+-Configure &catalogmanager;...</guimenuitem></menuchoice>.
+-See section <link linkend="preferences-catalogmanager">Preferences</link> for more
++<menuchoice><guimenu>Project</guimenu><guimenuitem>
++Configure...</guimenuitem></menuchoice>.
++See section <link linkend="preferences-project-settings">Project Settings</link> for more
+ details.</para>
+ 
+ <sect1 id="catman-features">
+@@ -176,10 +191,11 @@
+ Because &catalogmanager; cannot provide any functionality you would like
+ to use, you can extend it by defining your own commands.
+ </para>
++<!-- ### TODO: we should lik to preferences-project-file-commands too -->
+ <para>
+ There are two sets of commands. One for folders and one for single files.
+ You can set them in <link
+-linkend="preferences-catalogmanager">configuration dialog </link> and
++linkend="preferences-project-folder-commands">configuration dialog </link> and
+ access by pressing &RMB; on an entry in the file list.</para>
+ </sect2>
+ 
+--- doc/kbabel/index.docbook	(revision 490305)
++++ doc/kbabel/index.docbook	(revision 497528)
+@@ -26,12 +26,17 @@
+ <author>
+ &Matthias.Kiefer;
+ </author>
++<author>
++<firstname>Nicolas</firstname>
++<surname>Goutte</surname>
++<email>goutte at kde.org</email>
++</author>
+ <!-- TRANS:ROLES_OF_TRANSLATORS -->
+ </authorgroup>
+ 
+ 
+-<date>2003-09-18</date>
+-<releaseinfo>3.1.91</releaseinfo>
++<date>2005-12-29</date>
++<releaseinfo>3.5.1.03</releaseinfo>
+ 
+ <abstract>
+ <para>
+@@ -51,7 +56,9 @@
+ <keyword>gettext</keyword>
+ <keyword>translation</keyword>
+ <keyword>i18n</keyword>
++<keyword>internationalization</keyword>
+ <keyword>l10n</keyword>
++<keyword>localization</keyword>
+ </keywordset>
+ 
+ </bookinfo>
+@@ -59,6 +66,12 @@
+ <chapter id="introduction">
+ <title>Introduction</title>
+ 
++<important><para>
++In its current state, this KBabel documentation is partially outdated.
++The basic documentation was meant for KDE 3.2,
++the corrections are meant for KBabel 1.11.1 of KDE 3.5.1.
++</para></important>
++
+ <para>
+ &kbabel; is an advanced and easy to use <acronym>PO</acronym> file
+ (&GNU; gettext message catalogs) editor. It has many features, that
+@@ -117,6 +130,9 @@
+ <para>Update for &kde; 3.0 Copyright &copy; 2002 &Stanislav.Visnovsky;
+ &Stanislav.Visnovsky.mail;</para>
+ 
++<para>Update for &kde; 3.5.1 Copyright &copy; 2005 Nicolas Goutte
++<email>goutte at kde.org</email></para>
++
+ <!-- TRANS:CREDIT_FOR_TRANSLATORS -->
+ 
+ &underFDL;
+@@ -126,42 +142,26 @@
+ 
+ &glossary;
+ 
+-<appendix id="installation">
+-<title>Installation</title>
++<appendix id="mailing-list">
++<title>Mailing List For KBabel</title>
+ 
+-<sect1 id="getting-kbabel">
+-<title>How to obtain &kbabel;</title>
+-
+-&install.intro.documentation;
+-
+-</sect1>
+-
+-<sect1 id="requirements">
+-<title>Requirements</title>
+-
+ <para>
+-In order to successfully use &kbabel;, you need &kde; 3.x.
++There is a mailing list for KBabel named kbabel.
++It is a mixed list for developers and for users of KBabel.
+ </para>
+ 
+ <para>
+-All required libraries as well as &kbabel; itself can be found
+-on &kde-ftp;.
++You can subscribe it at 
++<ulink url="http://mail.kde.org/mailman/listinfo/kbabel/">the Mailman interface</ulink>.
+ </para>
+ 
+ <para>
+-If you want to use the translation database, you need Berkeley Database II.
++The mailing list has
++<ulink url="http://mail.kde.org/pipermail/kbabel/">a public archive</ulink>.
+ </para>
+ 
+-</sect1>
++</appendix>
+ 
+-<sect1 id="compilation">
+-<title>Compilation and Installation</title>
+-
+-&install.compile.documentation;
+-
+-</sect1>
+-
+-</appendix>
+ &documentation.index;
+ </book>
+ 
+--- doc/kbabel/man-catalogmanager.1.docbook	(revision 490305)
++++ doc/kbabel/man-catalogmanager.1.docbook	(revision 497528)
+@@ -5,7 +5,7 @@
+ 
+ <refentry lang="&language;">
+ <refentryinfo>
+-<date>March 7, 2003</date>
++<date>2003-03-07</date>
+ </refentryinfo>
+ 
+ <refmeta>
+--- doc/kbabel/kbabeldict.docbook	(revision 490305)
++++ doc/kbabel/kbabeldict.docbook	(revision 497528)
+@@ -4,6 +4,8 @@
+ <!-- standalone.  Be sure to recomment them before attempting to -->
+ <!-- process index.docbook -->
+ 
++<!-- Note: the id attribute "using-kbabeldict" is used in KBabelDict's source code to call the help.
++So if you change this id attribute, the name *must* be changed in KBabelDict's source code too! -->
+ <chapter id="using-kbabeldict">
+ <chapterinfo>
+ <!-- Fill in this section if this document has a different author -->
+--- doc/kbabel/using.docbook	(revision 490305)
++++ doc/kbabel/using.docbook	(revision 497528)
+@@ -30,7 +30,7 @@
+ includes translating the program's interfaces and documentation to the
+ various languages users need and, in some countries or regions, making
+ the inputs and outputs conform to particular conventions.  &kbabel; is
+-a tool which will assist you in the internationalization process to
++a tool which will assist you in the localization process to
+ make an application's interface speak many languages.</para>
+ 
+ <para> Every internationalization-aware program makes available for
+@@ -39,33 +39,33 @@
+ <acronym>POT</acronym> is an acronym for <quote>Portable Object
+ Template</quote>.</para>
+ 
+-
+-<para> Every translator takes a <acronym>POT</acronym> file copy and
+-begins translating messages. This file will became a
+-<acronym>PO</acronym> file - Portable Object and represents only one
+-language.</para>
+-
+-<para> Each translator takes a copy of one of these POT templates and
+-begins filling in the blanks: each message is translated into the
++<para>
++Each translator takes a copy of one of these <acronym>POT</acronym> templates and
++begins to fill in the blanks: each message is translated into the
+ language desired.  The file containing the translated text is referred
+-to as a <acronym>PO</acronym> (Portable Object) file.  </para>
++to as a <acronym>PO</acronym> (Portable Object) file.
++</para>
+ 
+-<para> Once all the messages have been translated, the
++<para>
++Once all the messages have been translated, the
+ <acronym>PO</acronym> file is compiled into a machine-readable binary
+ format, known as a <acronym>MO</acronym> (Machine Object) file.  These
+ files, which will be stored with a <literal
+-role="extension">.mo</literal> extension, act as a database to
++role="extension">.mo</literal> extension
++(or a <literal role="extension">.gmo</literal> extension to show
++that they were processed by &GNU; gettext), act as a database to
+ minimize the time taken by the applications to look up each translated
+-message.  </para>
++message.
++</para>
+ 
+ <para> This suggests a question: do I need to know what is
+ inside a <acronym>PO</acronym> file even though I have &kbabel;?  The
+ answer is, undoubtedly, yes.  There are situations when a message
+ catalog can become corrupted and needs to be manually fixed.  Most of
+-these problems are the so-hated <acronym>CVS</acronym> conflicts which
+-occur when a translating process is coordinated by a concurrent version
+-system (see the <ulink url="info:/cvs">CVS</ulink> documentation).
+-&kbabel; can't help you very much if a problem like this arises so a
++these problems are the so-hated <acronym>CVS</acronym> or <acronym>SVN</acronym> conflicts which
++occur when a translating process is coordinated by a version management
++system, like <acronym>CVS</acronym> or Subversion (<acronym>SVN</acronym>).
++&kbabel; cannot help you much if a problem like this arises so a
+ text editor and some knowledge of <acronym>PO</acronym>-files are
+ needed. Let's see how a <acronym>PO</acronym> file is made.</para>
+ 
+@@ -77,11 +77,13 @@
+ from a <acronym>PO</acronym> file for &noatun;, is <literal>msgid
+ &quot;Open a Playlist&quot;</literal> </para>
+ 
++<!-- ### TODO: we would need an example of an entry -->
++
+ <para>Empty lines and those starting with <literal>#</literal> are
+ ignored.  Lines starting with a # represent comments and are a useful
+-means of providing a note detailing which file this message is going
++way of providing a note detailing which file this message is going
+ to be used in and, in the case of the application writers, to provide
+-additional comments to aide translation.  &kbabel; displays these
++additional comments to help translation.  &kbabel; displays these
+ comment lines for every message.</para>
+ 
+ <para>In many cases the first msgid-msgstr pair in
+@@ -91,33 +93,49 @@
+ application name, translating date, translator name and so on.</para>
+ 
+ <para>
+-Recent versions of <application>&GNU; gettext</application> added
+-another useful i18n feature called <emphasis>plural forms</emphasis>.
++An useful feature is called <emphasis>plural forms</emphasis>.
+ English uses only singular and one plural form of nouns, &eg; <quote>1 file
+ </quote> and <quote>10 files</quote>. This leads many developers
+ to an idea that the world is that simple and they can use messages like
+ <quote>Do you want to delete %1 file(s)?</quote>, where
+ <literal>%1</literal> denotes a number of files to be deleted.
+-But this is fundamentally wrong. For Slovak translation you need 3 different
++But this is fundamentally wrong and for many languages such a kind of translation
++will not work. For Slovak translation you need 3 different
+ forms of the message. This number is  different for different languages
+ and even when it is the same, &eg; Czech uses 3 forms as well, the rule to decide which
+-form to use can be very different.
++form to use can be very different. Plural forms in <acronym>PO</acronym> files are here to help.
+ </para>
+-<para>
+-Plural forms in <acronym>PO</acronym> files are here to help. Unfortunately,
+-&kde; developers do not like the plural forms implementation in
++
++<note><para>
++&kde; developers have chosen a different implementation for the plural forms than
+ <application>&GNU; gettext</application> and they have introduced their own
+ format and handling for them.
+-</para>
++It is planned to use &GNU; gettext's plural forms in &kde; version 4.
++</para></note>
++
+ </sect1>
+ 
+ <sect1 id="using-editor">
+ <title>Editor</title>
+ 
+-<para>Here is a screenshot of &kbabel;.  For convenience &kbabel; has
++<para>Here is a screenshot of &kbabel;.</para>
++
++<screenshot>
++<screeninfo>Screenshot of &kbabel;</screeninfo>
++<mediaobject>
++<imageobject>
++<imagedata fileref="snap1.png" format="PNG"/>
++</imageobject>
++<textobject><phrase>Screenshot of &kbabel;</phrase></textobject>
++</mediaobject>
++</screenshot>
++
++<para>
++For convenience &kbabel; has
+ toolbars to speed up many operations and, for busy users, there are
+ many keyboard shortcuts.  The main window is divided into four
+-parts.</para>
++parts.
++</para>
+ 
+ <para>The <emphasis>upper-left</emphasis> edit box is read-only and
+ contains the current msgid field from the opened PO-file and its
+@@ -150,16 +168,6 @@
+ </para></listitem>
+ </itemizedlist>
+ 
+-<screenshot>
+-<screeninfo>Screenshot of &kbabel;</screeninfo>
+-<mediaobject>
+-<imageobject>
+-<imagedata fileref="snap1.png" format="PNG"/>
+-</imageobject>
+-<textobject><phrase>Screenshot of &kbabel;</phrase></textobject>
+-</mediaobject>
+-</screenshot>
+-
+ <para>
+ The editor window (in the bottom right) is the most sophisticated part
+ of &kbabel;'s main window.  Its size can be
+@@ -341,7 +349,7 @@
+ </informaltable>
+ <note>
+ <para>
+-If you want to see where are spaces, you can turn on <guibutton>Highlight background</guibutton>
++If you want to see where spaces are, you can turn on <guibutton>Highlight background</guibutton>
+ and/or <guibutton>Mark whitespaces with points</guibutton> in preferences dialog
+ on tab <guilabel>Edit</guilabel> <guilabel>Appearance</guilabel>.
+ </para>
+@@ -442,7 +450,7 @@
+      <listitem>
+        <para>
+        This invokes <command>msgfmt</command> to check validity of the PO file
+-       as seen by gettext package. It will show the result of the command
++       as seen by &GNU; gettext package. It will show the result of the command
+        and mark error <acronym>msgstr</acronym>s.
+        </para>
+      </listitem>
+@@ -506,6 +514,7 @@
+        must use this special format as well. This means that the translation must start (up to the
+        first occurrence of <literal>=</literal> with the same text as the original message, &eg;
+        <userinput>Name=</userinput>.
++       <!-- ### TODO: is this feature is specific to KDE too? How does e.g. GNOME translate them? -->
+        </para>
+      </listitem>
+    </varlistentry>
+@@ -517,8 +526,7 @@
+ <para>As always, it is very important to spell-check your translation before
+ using your result. This way you can find typos and other problems in your translation.
+ &kbabel; uses the standard &kde; library for spellchecking and its standard
+-settings can be found in <link linkend="preferences-spellcheck">the &kbabel;
+-configuration dialog</link>. Spell checking itself can be found in
++settings can be found in <link linkend="preferences-project-spellcheck">the project setting dialog</link>. Spell checking itself can be found in
+ <menuchoice><guimenu>Tools</guimenu><guisubmenu>Spelling</guisubmenu>
+ </menuchoice> submenu.
+ You can use a number of modes for spell checking:
+@@ -719,22 +727,32 @@
+ <title>Plural Forms</title>
+ <para>
+ Because plural forms are quite a complicated issue, we devote a special section
+-for their suport in &kbabel;.
++for their support in &kbabel;.
+ </para>
++
++<note><para>
++This section handles about &kde; plural forms (to be precise of &kde; version 3).
++From &kbabel; version 1.11 (KDE 3.5) on, &kbabel; should be able to
++read, edit and save the &GNU; gettext plural forms too.
++</para></note>
++
+ <para>
+-&kbabel; can read the &GNU; plural forms only, but cannot edit them. It only supports
+-the &kde; version of plural forms at the moment.
+-</para>
+-<para>
+ Every language to which &kde; is translated must have set a correct
+-number of plural forms. This is done by translating an entry in <filename>kdelibs.po</filename>.
++number of plural forms. This is done by translating a specific entry in <filename>kdelibs.po</filename>.
+ The number is set by selecting the name of a language, which uses
+ the same number and <emphasis>rules</emphasis> for finding the
+ right plural form. The up-to-date list of possible values can be found in the
+ kdelibs source code, in the file <filename>kdecore/klocale.cpp</filename>.
+ </para>
++
++<note><para>
++&GNU; gettext allows to define the number and type of plural forms by a formula and to set this
++formula independently for each PO file. &kde; can only define the number and type of plural forms
++one time in kdelibs.
++</para></note>
++
+ <para>
+-&kde; plural forms are denoted by comment <userinput>_:</userinput> containing
++&kde; plural forms are denoted by comment <userinput>_n:</userinput> (including a trailing space) containing
+ the <literal>%n</literal> argument. This argument is then used in the message
+ itself and it controls which plural form of your language should be used
+ depending on the rules for your language.
+@@ -742,8 +760,9 @@
+ <para>
+ The translation of a plural form message has to have a special format. 
+ It must contain the correct number of translations (one for each plural form)
+-separated by an end of the line <literal>\n</literal>. For example, 
+-<quote>Selected %n files</quote> translated to Slovak would be:
++separated by an end of the line <literal>\n</literal>,
++<emphasis>without</emphasis> any <userinput>_n:</userinput> sequence (without the space either). For example,
++<quote>_n: Selected 1 file\nSelected %n files</quote> translated to Slovak would be:
+ </para>
+ <programlisting>
+ Vybraný %n súbor\n
+--- doc/kbabel/menu.docbook	(revision 490305)
++++ doc/kbabel/menu.docbook	(revision 497528)
+@@ -1099,7 +1099,7 @@
+     characters is identical in both the original and the translated
+     string.</action>  Note that accelerator marker is &amp; in &kde;
+     (but not in every programming toolkit). See the
+-    <link linkend="preferences-miscellaneous">Miscellaneous</link> section 
++    <link linkend="preferences-project-miscellaneous">Miscellaneous</link> section 
+ 	below to find out how to change a keyboard accelerator.
+       </para>
+     </listitem>
+@@ -1399,7 +1399,7 @@
+     <listitem>
+       <para>
+         All &kbabel;-specific settings go here.
+-	Please read the <link linkend="preferences-kbabel">Preferences</link> section for specific topics.
++	Please read the <link linkend="preferences-global">&kbabel; Global Settings</link> section for specific topics.
+       </para>
+     </listitem>
+   </varlistentry>
+@@ -2297,22 +2297,6 @@
+       </para>
+     </listitem>
+   </varlistentry>
+-  <varlistentry>
+-    <term>
+-      <menuchoice>
+-        <guimenu>Settings</guimenu>
+-        <guimenuitem>Configure KBabel - Catalog Manager...</guimenuitem>
+-      </menuchoice>
+-    </term>
+-    <listitem>
+-      <para>
+-        <action>
+-        All &catalogmanager; specific settings go here.
+-	</action>
+-	Please read <link linkend="preferences-catalogmanager">Preferences</link> section for specific topics.
+-      </para>
+-    </listitem>
+-  </varlistentry>
+ </variablelist>
+ </sect2>
+ 
+--- doc/kbabel/faq.docbook	(revision 490305)
++++ doc/kbabel/faq.docbook	(revision 497528)
+@@ -18,34 +18,10 @@
+ 
+ <title>Questions and Answers</title>
+ <qandaset>
++  <!-- ### FIXME: describe better the situation of Qt3. (This text sounds like being for Qt2.) -->
+   <qandaentry>
+     <question>
+       <para>
+-      Why does &kbabel; show question marks when entering language specific
+-      characters?
+-      </para>
+-    </question>
+-    <answer>
+-
+-      <para>
+-        This is a problem with your locale settings. The following might help:
+-        Exit &kbabel;, in a shell set the environment variable
+-<envar>LANG</envar> to a locale, valid for your language. If you use
+-<command>bash</command> do
+-        <userinput><command>export
+-<envar>LANG</envar>=<replaceable>change
+-this</replaceable></command></userinput>. For example, when you use
+-german characters, do <userinput><command>export
+-<envar>LANG</envar>=de_DE.88591</command></userinput>. Then start
+-&kbabel; from this shell. If the problem is gone, insert
+-        this command in your <filename>~/.profile</filename>.
+-      </para>
+-
+-    </answer>
+-  </qandaentry>
+-  <qandaentry>
+-    <question>
+-      <para>
+       Why does &kbabel; show question marks instead of language specific
+ characters after loading a <acronym>PO</acronym> file?</para>
+     </question>
+@@ -62,6 +38,19 @@
+       </para>
+     </answer>
+   </qandaentry>
++<qandaentry>
++<question>
++<para>
++How can I translate &kde;?
++</para>
++</question>
++<answer>
++<para>
++You can look for information about how to translate KDE in the
++<ulink url="http://i18n.kde.org/translation-howto/">The KDE Translation HOWTO</ulink>.
++</para>
++</answer>
++</qandaentry> 
+ </qandaset>
+ </chapter>
+ <!--
+--- doc/kbabel/dictionaries.docbook	(revision 490305)
++++ doc/kbabel/dictionaries.docbook	(revision 497528)
+@@ -41,8 +41,9 @@
+ <!-- FIXME: settings -->
+ <title>Translation database</title>
+ 
++<!-- ### TODO: only *one* file? Seems more to be four... -->
+ <para>Translation database allows you to store translations in a
+-database based on Berkeley Database II, &ie; it is stored in a binary
++database based on Berkeley Database IV, &ie; it is stored in a binary
+ file on your disk. The database guarantees fast searching in a large
+ number of translations.</para>
+ 
+@@ -276,17 +277,23 @@
+ 
+ <para>This searching mode is based on matching the same original
+ English string (the msgid) translated in some other language in an
+-auxillary <acronym>PO</acronym> file.  It is very common for romanic
+-languages to have similar words, similarly for anglosaxon and
+-slavonic ones.</para>
++auxillary <acronym>PO</acronym> file.  It is very common for Romance
++<!-- ### TODO: is "Anglo-Saxon" not too Romance or too technical for an English text? -->
++languages to have similar words, similarly for Anglo-Saxon and
++Slavic ones.</para>
+ 
+-<para>For example, say I wanted to translate the word
++<para>
++For example, say I wanted to translate the word
+ <quote>on</quote>, from <filename>kdelibs.po</filename>, into Romanian
+ but have no clue.  I look in the same file for French and find
+-<quote>actif</quote>, and in the Spanish one find
+-<quote>activado</quote>.  So, I conclude that the best one in Romanian
+-will be <quote>active</quote>.  &kbabel; automates this task.
+-Currently you can define only one auxiliary file to search.</para>
++<foreignphrase lang="fr">actif</foreignphrase>, and in the Spanish one find
++<foreignphrase lang="es">activado</foreignphrase>.  So, I conclude that the best one in Romanian
++will be <foreignphrase lang="ro">active</foreignphrase>.
++(Of course, in English instead of <quote>on</quote> the word could have been
++<quote>active</quote> or <quote>activated</quote>,
++which would have made the translation process easier.)
++&kbabel; automates this task. Currently you can define only one auxiliary file to search.
++</para>
+ 
+ <sect2 id="auxiliary-settings">
+ <title>Settings</title>
+@@ -341,6 +348,7 @@
+ <para>I'm Romanian and I have some knowledge about French language and
+ I work on &kde; translation.</para>
+ 
++<!-- ### TODO: check URL, especially the kde-l10n part -->
+ <para>First step is to download a very fresh
+ <filename>kde-l10n-fr.tar.bz2</filename> from the <ulink
+ url="ftp://ftp.kde.org/pub/kde/snapshots/kde-l10n">&kde; &FTP;
+@@ -349,7 +357,7 @@
+ <filename>/home/clau/cvs-cvs.kde.org/kde-l10n/fr</filename>.</para>
+ 
+ <para>My <acronym>PO</acronym> sources folder is in
+-<filename>/home/clau/cvs-cvs.kde.org/kde-l10n/ro</filename>.  Don't
++<filename>/home/clau/cvs-cvs.kde.org/kde-l10n/ro</filename>.  Do not
+ forget to select <guilabel>PO Auxiliary</guilabel> as the default
+ dictionary and check <guilabel>Automatically start search</guilabel>
+ on the <guilabel>Search</guilabel> tab from &kbabel;'s
+@@ -415,6 +423,7 @@
+ path, it's possible to choose an absolute, real path to an existing
+ <acronym>PO</acronym> file to be used as a compendium.</para>
+ 
++<!-- ### TODO: check URL, especially the kde-l10n part -->
+ <para>A very fresh compendium for &kde; translation into &eg; French
+ you can download <filename>fr.messages.bz2</filename> from the <ulink
+ url="ftp://ftp.kde.org/pub/kde/snapshots/kde-l10n">&kde; &FTP;
+--- cervisia/cervisia.pod	(revision 490305)
++++ cervisia/cervisia.pod	(revision 497528)
+@@ -17,6 +17,7 @@
+          S<[ B<--geometry> I<geometry> ]>
+          S<[ B<--resolve> I<filename> ]>
+          S<[ B<--log> I<filename> ]>
++         S<[ B<--annotate> I<filename> ]>
+          S<[ I<directory> ]>
+ 
+ =head1 DESCRIPTION
+@@ -43,6 +44,10 @@
+ 
+ Shows a log dialog for the given file
+ 
++=item B<--annotate> I<filename>
++
++Shows a annotation dialog for the given file
++
+ =item B<--caption> I<caption>
+ 
+ Sets the caption, i. e. what is shown in the title bar
+@@ -92,12 +97,12 @@
+ 
+ L<cvs(1)>
+ 
+-F<http://www.kde.org/apps/cervisia>
++F<http://cervisia.kde.org/>
+ 
+ =head1 AUTHOR
+ 
+ Cervisia was originally developed by Bernd Gehrmann and is now maintained by
+-Christian Loose <christian.loose at hamburg.de>.
++Christian Loose <christian.loose at kdemail.net>.
+ 
+ =head1 REPORTING BUGS
+ 
+--- cervisia/cervisia.1.in	(revision 490305)
++++ cervisia/cervisia.1.in	(revision 497528)
+@@ -1,4 +1,4 @@
+-.\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13
++.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.3
+ .\"
+ .\" Standard preamble:
+ .\" ========================================================================
+@@ -129,7 +129,7 @@
+ .\" ========================================================================
+ .\"
+ .IX Title "CERVISIA 1"
+-.TH CERVISIA 1 "2003-07-16" "2.1" "Cervisia"
++.TH CERVISIA 1 "2006-01-05" "2.4.0" "Cervisia"
+ .SH "NAME"
+ Cervisia \- Graphical CVS frontend
+ .SH "SYNOPSIS"
+@@ -147,6 +147,7 @@
+          [\ \fB\-\-geometry\fR\ \fIgeometry\fR\ ]
+          [\ \fB\-\-resolve\fR\ \fIfilename\fR\ ]
+          [\ \fB\-\-log\fR\ \fIfilename\fR\ ]
++         [\ \fB\-\-annotate\fR\ \fIfilename\fR\ ]
+          [\ \fIdirectory\fR\ ]
+ .SH "DESCRIPTION"
+ .IX Header "DESCRIPTION"
+@@ -165,6 +166,9 @@
+ .IP "\fB\-\-log\fR \fIfilename\fR" 4
+ .IX Item "--log filename"
+ Shows a log dialog for the given file
++.IP "\fB\-\-annotate\fR \fIfilename\fR" 4
++.IX Item "--annotate filename"
++Shows a annotation dialog for the given file
+ .IP "\fB\-\-caption\fR \fIcaption\fR" 4
+ .IX Item "--caption caption"
+ Sets the caption, i. e. what is shown in the title bar
+@@ -203,11 +207,11 @@
+ .Sp
+ \&\fIcvs\fR\|(1)
+ .Sp
+-\&\fIhttp://www.kde.org/apps/cervisia\fR
++\&\fIhttp://cervisia.kde.org/\fR
+ .SH "AUTHOR"
+ .IX Header "AUTHOR"
+ Cervisia was originally developed by Bernd Gehrmann and is now maintained by
+-Christian Loose <christian.loose at hamburg.de>.
++Christian Loose <christian.loose at kdemail.net>.
+ .SH "REPORTING BUGS"
+ .IX Header "REPORTING BUGS"
+ Report bugs at http://bugs.kde.org.
+--- kbugbuster/kresources/bugzilla.desktop	(revision 490305)
++++ kbugbuster/kresources/bugzilla.desktop	(revision 497528)
+@@ -10,6 +10,7 @@
+ Name[eu]=Bugzilla-ren egiteke zerrenda
+ Name[fr]=Liste de tâches de Bugzilla
+ Name[ga]=Tascliosta Bugzilla
++Name[he]=רשימת מטלות של Bugzilla
+ Name[hu]=Bugzilla feladatlista
+ Name[is]=Bugzilla verklisti
+ Name[it]=Lista delle cosa da fare di Bugzilla
+--- kioslave/svn/svnhelper/subversion.desktop	(revision 490305)
++++ kioslave/svn/svnhelper/subversion.desktop	(revision 497528)
+@@ -20,6 +20,7 @@
+ Name[eu]=Gehitu biltegira
+ Name[fr]=Ajouter au référentiel
+ Name[ga]=Cuir leis an Stór
++Name[he]=הוסף למאגר
+ Name[hu]=Hozzáadás az adattárhoz
+ Name[is]=Bæta við geymslu
+ Name[it]=Aggiungi al deposito
+@@ -51,6 +52,7 @@
+ Name[et]=Hoidlast kustutamine
+ Name[eu]=Ezabatu biltegitik
+ Name[fr]=Supprimer du référentiel
++Name[he]=מחק ממאגר
+ Name[hu]=Törlés az adattárból
+ Name[is]=Eyða frá geymslu
+ Name[it]=Elimina dal deposito
+@@ -81,6 +83,7 @@
+ Name[et]=Kohalike muudatuste tühistamine
+ Name[eu]=Leheneratu aldaketa lokalak
+ Name[fr]=Annuler les modifications locales
++Name[he]=נקה שינויים מקומיים
+ Name[hu]=A helyi módosítások visszavonása
+ Name[is]=Afturkalla staðbundnar breytingar
+ Name[it]=Annulla i cambiamenti locali
+@@ -139,6 +142,7 @@
+ Name[eu]=Berrizendatu...
+ Name[fr]=Renommer...
+ Name[ga]=Athainmnigh...
++Name[he]=שנה שם...
+ Name[hu]=Átnevezés...
+ Name[is]=Endurnefna...
+ Name[it]=Rinomina...
+--- kioslave/svn/svnhelper/apply_patch.desktop	(revision 490305)
++++ kioslave/svn/svnhelper/apply_patch.desktop	(revision 497528)
+@@ -16,6 +16,7 @@
+ Name[eu]=Aplikatu adabakia...
+ Name[fr]=Appliquer le correctif...
+ Name[ga]=Cuir Paiste i bhFeidhm...
++Name[he]=החל את הטלאי...
+ Name[hu]=Folt alkalmazása...
+ Name[is]=Virkja plástur...
+ Name[it]=Applica correzione...




More information about the pkg-kde-commits mailing list