summaryrefslogtreecommitdiffstats
path: root/parts/classview/classviewwidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'parts/classview/classviewwidget.cpp')
-rw-r--r--parts/classview/classviewwidget.cpp1295
1 files changed, 1295 insertions, 0 deletions
diff --git a/parts/classview/classviewwidget.cpp b/parts/classview/classviewwidget.cpp
new file mode 100644
index 00000000..f26f1b92
--- /dev/null
+++ b/parts/classview/classviewwidget.cpp
@@ -0,0 +1,1295 @@
+/*
+ * Copyright (C) 2003 Roberto Raggi ([email protected])
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Partially based on KDE Studio ClassListView http://www.thekompany.com/projects/kdestudio/
+ */
+
+#include "classviewpart.h"
+#include "classviewwidget.h"
+
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kurl.h>
+#include <kaction.h>
+#include <kactionclasses.h>
+#include <kpopupmenu.h>
+#include <kconfig.h>
+
+#include <urlutil.h>
+#include <kdevcore.h>
+#include <kdevlanguagesupport.h>
+#include <kdevproject.h>
+#include <kdevpartcontroller.h>
+#include <codemodel.h>
+#include <codemodel_utils.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qheader.h>
+#include <qdir.h>
+#include <qstylesheet.h>
+#include <qstringlist.h>
+
+// namespace ?!?
+
+ClassViewWidget::ClassViewWidget( ClassViewPart * part )
+ : KListView( 0, "ClassViewWidget" ), QToolTip( viewport() ), m_part( part ), m_projectDirectoryLength( 0 )
+{
+ addColumn( "" );
+ header()->hide();
+ setSorting( 0 );
+ setRootIsDecorated( true );
+ setAllColumnsShowFocus( true );
+
+ m_projectItem = 0;
+
+ connect( this, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(slotExecuted(QListViewItem*)) );
+ connect( this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotExecuted(QListViewItem*)) );
+ connect( m_part->core(), SIGNAL(projectOpened()), this, SLOT(slotProjectOpened()) );
+ connect( m_part->core(), SIGNAL(projectClosed()), this, SLOT(slotProjectClosed()) );
+ connect( m_part->core(), SIGNAL(languageChanged()), this, SLOT(slotProjectOpened()) );
+
+ QStringList lst;
+ lst << i18n( "Group by Directories" ) << i18n( "Plain List" ) << i18n( "Java Like Mode" );
+ m_actionViewMode = new KSelectAction( i18n("View Mode"), KShortcut(), m_part->actionCollection(), "classview_mode" );
+ m_actionViewMode->setItems( lst );
+ m_actionViewMode->setWhatsThis(i18n("<b>View mode</b><p>Class browser items can be grouped by directories, listed in a plain or java like view."));
+
+ m_actionNewClass = new KAction( i18n("New Class..."), KShortcut(), this, SLOT(slotNewClass()),
+ m_part->actionCollection(), "classview_new_class" );
+ m_actionNewClass->setWhatsThis(i18n("<b>New class</b><p>Calls the <b>New Class</b> wizard."));
+
+ m_actionCreateAccessMethods = new KAction( i18n("Create get/set Methods"), KShortcut(), this, SLOT(slotCreateAccessMethods()), m_part->actionCollection(), "classview_create_access_methods" );
+
+
+ m_actionAddMethod = new KAction( i18n("Add Method..."), KShortcut(), this, SLOT(slotAddMethod()),
+ m_part->actionCollection(), "classview_add_method" );
+ m_actionAddMethod->setWhatsThis(i18n("<b>Add method</b><p>Calls the <b>New Method</b> wizard."));
+ m_actionAddAttribute = new KAction( i18n("Add Attribute..."), KShortcut(), this, SLOT(slotAddAttribute()),
+ m_part->actionCollection(), "classview_add_attribute" );
+ m_actionAddAttribute->setWhatsThis(i18n("<b>Add attribute</b><p>Calls the <b>New Attribute</b> wizard."));
+
+ m_actionOpenDeclaration = new KAction( i18n("Open Declaration"), KShortcut(), this, SLOT(slotOpenDeclaration()),
+ m_part->actionCollection(), "classview_open_declaration" );
+ m_actionOpenDeclaration->setWhatsThis(i18n("<b>Open declaration</b><p>Opens a file where the selected item is declared and jumps to the declaration line."));
+ m_actionOpenImplementation = new KAction( i18n("Open Implementation"), KShortcut(), this, SLOT(slotOpenImplementation()),
+ m_part->actionCollection(), "classview_open_implementation" );
+ m_actionOpenImplementation->setWhatsThis(i18n("<b>Open implementation</b><p>Opens a file where the selected item is defined (implemented) and jumps to the definition line."));
+
+ m_actionFollowEditor = new KToggleAction( i18n("Follow Editor"), KShortcut(), this, SLOT(slotFollowEditor()), m_part->actionCollection(), "classview_follow_editor" );
+
+ KConfig* config = m_part->instance()->config();
+ config->setGroup( "General" );
+ setViewMode( config->readNumEntry( "ViewMode", KDevelop3ViewMode ) );
+ m_doFollowEditor = config->readBoolEntry( "FollowEditor", false );
+}
+
+ClassViewWidget::~ClassViewWidget( )
+{
+ KConfig* config = m_part->instance()->config();
+ config->setGroup( "General" );
+ config->writeEntry( "ViewMode", viewMode() );
+ config->writeEntry( "FollowEditor", m_doFollowEditor );
+ config->sync();
+}
+
+template <class ModelType, class ListItemType>
+ static bool selectItemG( ItemDom item, const QMap<KSharedPtr<ModelType>, ListItemType*>& map )
+{
+ ModelType* c = dynamic_cast<ModelType*>( &(*item) );
+
+ if( c ) {
+ KSharedPtr<ModelType> d( c );
+ typename QMap<KSharedPtr<ModelType>, ListItemType*>::ConstIterator it = map.find(d);
+ if( it != map.end() ) {
+ ( *it )->select();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void ClassViewWidget::slotExecuted( QListViewItem* item )
+{
+ if( ClassViewItem* cbitem = dynamic_cast<ClassViewItem*>( item ) ){
+ if( cbitem->hasImplementation() )
+ cbitem->openImplementation();
+ else
+ cbitem->openDeclaration();
+ }
+}
+
+void ClassViewWidget::clear( )
+{
+ KListView::clear();
+ removedText.clear();
+ m_projectItem = 0;
+}
+
+void restoreOpenNodes( QStringList & list, QListViewItem * item )
+{
+ if ( item && !list.isEmpty() )
+ {
+ if ( item->text( 0 ) == list.first() )
+ {
+ item->setOpen( true );
+ list.pop_front();
+ restoreOpenNodes( list, item->firstChild() );
+ }
+ else
+ {
+ restoreOpenNodes( list, item->nextSibling() );
+ }
+ }
+}
+
+void storeOpenNodes( QValueList<QStringList> & openNodes, QStringList const & list, QListViewItem * item )
+{
+ if ( item )
+ {
+ if ( item->isOpen() )
+ {
+ QStringList mylist( list );
+ mylist << item->text( 0 );
+ openNodes << mylist;
+ storeOpenNodes( openNodes, mylist, item->firstChild() );
+ }
+ storeOpenNodes( openNodes, list, item->nextSibling() );
+ }
+}
+
+void ClassViewWidget::refresh()
+{
+ if( !m_part->project() )
+ return;
+
+ QValueList<QStringList> openNodes;
+ storeOpenNodes( openNodes, QStringList(), firstChild() );
+ int scrollbarPos = verticalScrollBar()->value();
+
+ clear();
+ m_projectItem = new FolderBrowserItem( this, this, m_part->project()->projectName() );
+ m_projectItem->setOpen( true );
+ blockSignals( true );
+
+ FileList fileList = m_part->codeModel()->fileList();
+ FileList::Iterator it = fileList.begin();
+ while( it != fileList.end() ){
+ insertFile( (*it)->name() );
+ ++it;
+ }
+
+ QValueList<QStringList>::iterator itt = openNodes.begin();
+ while ( itt != openNodes.end() )
+ {
+ restoreOpenNodes ( *itt, firstChild() );
+ ++itt;
+ }
+ verticalScrollBar()->setValue( scrollbarPos );
+
+ blockSignals( false );
+}
+
+void ClassViewWidget::slotProjectOpened( )
+{
+ m_projectItem = new FolderBrowserItem( this, this, m_part->project()->projectName() );
+ m_projectItem->setOpen( true );
+
+ m_projectDirectory = URLUtil::canonicalPath( m_part->project()->projectDirectory() );
+ if( m_projectDirectory.isEmpty() )
+ m_projectDirectory = m_part->project()->projectDirectory();
+
+ m_projectDirectoryLength = m_projectDirectory.length() + 1;
+
+ connect( m_part->languageSupport(), SIGNAL(updatedSourceInfo()),
+ this, SLOT(refresh()) );
+ connect( m_part->languageSupport(), SIGNAL(aboutToRemoveSourceInfo(const QString&)),
+ this, SLOT(removeFile(const QString&)) );
+ connect( m_part->languageSupport(), SIGNAL(addedSourceInfo(const QString&)),
+ this, SLOT(insertFile(const QString&)) );
+}
+
+void ClassViewWidget::slotProjectClosed( )
+{
+}
+
+
+void ClassViewWidget::insertFile( const QString& fileName )
+{
+ QString fn = URLUtil::canonicalPath( fileName );
+ //kdDebug() << "======================== insertFile(" << fn << ")" << endl;
+
+ FileDom dom = m_part->codeModel()->fileByName( fn );
+ if( !dom )
+ return;
+
+ fn = URLUtil::relativePathToFile(m_part->project()->projectDirectory(), fn);
+ QStringList path;
+
+ switch( viewMode() )
+ {
+ case KDevelop3ViewMode:
+ {
+ path = QStringList::split( "/", fn );
+ path.pop_back();
+ }
+ break;
+
+ case KDevelop2ViewMode:
+ {
+ }
+ break;
+
+ case JavaLikeViewMode:
+ {
+ QStringList l = QStringList::split( "/", fn );
+ l.pop_back();
+
+ QString package = l.join(".");
+ if( !package.isEmpty() )
+ path.push_back( package );
+ }
+ break;
+ }
+
+ m_projectItem->processFile( dom, path );
+}
+
+void ClassViewWidget::removeFile( const QString& fileName )
+{
+ QString fn = URLUtil::canonicalPath( fileName );
+ //kdDebug() << "======================== removeFile(" << fn << ")" << endl;
+
+ FileDom dom = m_part->codeModel()->fileByName( fn );
+ if( !dom )
+ return;
+
+ fn = URLUtil::relativePathToFile(m_part->project()->projectDirectory(), fn);
+ QStringList path;
+
+ switch( viewMode() )
+ {
+ case KDevelop3ViewMode:
+ {
+ path = QStringList::split( "/", fn );
+ path.pop_back();
+ }
+ break;
+
+ case KDevelop2ViewMode:
+ {
+ }
+ break;
+
+ case JavaLikeViewMode:
+ {
+ QStringList l = QStringList::split( "/", fn );
+ l.pop_back();
+
+ QString package = l.join(".");
+ if( !package.isEmpty() )
+ path.push_back( package );
+ }
+ break;
+ }
+
+ m_projectItem->processFile( dom, path, true );
+}
+
+void ClassViewWidget::contentsContextMenuEvent( QContextMenuEvent * ev )
+{
+ KPopupMenu menu( this );
+
+ ClassViewItem* item = dynamic_cast<ClassViewItem*>( selectedItem() );
+
+ m_actionFollowEditor->plug( &menu );
+ m_actionFollowEditor->setChecked( m_doFollowEditor );
+ menu.insertSeparator();
+
+ m_actionOpenDeclaration->setEnabled( item && item->hasDeclaration() );
+ m_actionOpenImplementation->setEnabled( item && item->hasImplementation() );
+
+ m_actionOpenDeclaration->plug( &menu );
+ m_actionOpenImplementation->plug( &menu );
+ menu.insertSeparator();
+
+ bool sep = false;
+ if( item && item->isClass() ){
+ if( m_part->langHasFeature(KDevLanguageSupport::AddMethod) ) {
+ m_actionAddMethod->plug( &menu );
+ sep = true;
+ }
+
+ if( m_part->langHasFeature(KDevLanguageSupport::AddAttribute) ) {
+ m_actionAddAttribute->plug( &menu );
+ sep = true;
+ }
+ }
+
+ if (item && item->isVariable()){
+ if( m_part->langHasFeature(KDevLanguageSupport::CreateAccessMethods) )
+ m_actionCreateAccessMethods->plug( &menu );
+ }
+
+ if( item && item->model() ){
+ CodeModelItemContext context( item->model() );
+ m_part->core()->fillContextMenu( &menu, &context );
+// sep = true;
+ }
+ if (sep)
+ menu.insertSeparator();
+
+ int oldViewMode = viewMode();
+ m_actionViewMode->plug( &menu );
+
+ menu.exec( ev->globalPos() );
+
+ if( viewMode() != oldViewMode )
+ refresh();
+
+ ev->consume();
+}
+
+void ClassViewWidget::setViewMode( int mode ) {
+ m_actionViewMode->setCurrentItem( mode );
+}
+
+int ClassViewWidget::viewMode( ) const
+{
+ return m_actionViewMode->currentItem();
+}
+
+QString ClassViewItem::comment() {
+ return QString();
+}
+
+void ClassViewItem::select( ) {
+ setOpen(true);
+ listView()->setCurrentItem(this);
+ QListViewItem* c = firstChild();
+ int size = 0;
+ if(c != 0) {
+ while(c->nextSibling()) {
+ c = c->nextSibling();
+ size++;
+ }
+ listView()->ensureItemVisible(c);
+ }
+ listView()->ensureItemVisible(this);
+}
+
+
+bool ClassViewWidget::selectItem( ItemDom item ) {
+ if(!m_projectItem || !isVisible()) return false;
+ if(item->isFunctionDefinition() && dynamic_cast<FunctionDefinitionModel*>(&(*item)) != 0) {
+ FunctionList lst;
+ FileList fileList = m_part->codeModel()->fileList();
+ CodeModelUtils::findFunctionDeclarations( FindOp2(FunctionDefinitionDom( (FunctionDefinitionModel*)&(*item) )), fileList, lst );
+ if(lst.isEmpty()) return false;
+
+ item = *lst.begin();
+ }
+
+ return m_projectItem->selectItem( item );
+}
+
+
+QString NamespaceDomBrowserItem::comment() {
+ return m_dom->comment();
+}
+
+bool FolderBrowserItem::selectItem(ItemDom item)
+{
+ if(item->kind() == CodeModelItem::Class) {
+ if( selectItemG ( item, m_classes ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::Function) {
+ if( selectItemG ( item, m_functions ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::TypeAlias) {
+ if( selectItemG ( item, m_typeAliases ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::Variable) {
+ if( selectItemG ( item, m_variables ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::Namespace) {
+ ///searching for namespaces is currently not supported and not useful
+ }
+
+ for( QMap<ClassDom, ClassDomBrowserItem*>::Iterator it = m_classes.begin(); it != m_classes.end(); ++it ) {
+ if( (*it)->selectItem(item) )
+ return true;
+ }
+
+ for( QMap<QString, NamespaceDomBrowserItem*>::Iterator it = m_namespaces.begin(); it != m_namespaces.end(); ++it ) {
+ if( (*it)->selectItem(item) )
+ return true;
+ }
+
+ for( QMap<QString, FolderBrowserItem*>::Iterator it = m_folders.begin(); it != m_folders.end(); ++it ) {
+ if( (*it)->selectItem(item) ) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void FolderBrowserItem::processFile( FileDom file, QStringList& path, bool remove )
+{
+ if( path.isEmpty() ){
+ NamespaceList namespaceList = file->namespaceList();
+ ClassList classList = file->classList();
+ TypeAliasList typeAliasList = file->typeAliasList();
+ FunctionList functionList = file->functionList();
+ VariableList variableList = file->variableList();
+
+ for( NamespaceList::Iterator it=namespaceList.begin(); it!=namespaceList.end(); ++it )
+ processNamespace( *it, remove );
+ for( ClassList::Iterator it=classList.begin(); it!=classList.end(); ++it )
+ processClass( *it, remove );
+ for( TypeAliasList::Iterator it=typeAliasList.begin(); it!=typeAliasList.end(); ++it )
+ processTypeAlias( *it, remove );
+ for( FunctionList::Iterator it=functionList.begin(); it!=functionList.end(); ++it )
+ processFunction( *it, remove );
+ for( VariableList::Iterator it=variableList.begin(); it!=variableList.end(); ++it )
+ processVariable( *it, remove );
+
+ return;
+ }
+
+ QString current = path.front();
+ path.pop_front();
+
+ FolderBrowserItem* item = m_folders.contains( current ) ? m_folders[ current ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new FolderBrowserItem( m_widget, this, current );
+ if( listView()->removedText.contains(current) )
+ item->setOpen( true );
+ m_folders.insert( current, item );
+ }
+
+ item->processFile( file, path, remove );
+
+ if( remove && item->childCount() == 0 ){
+ m_folders.remove( current );
+ if( item->isOpen() ){
+ listView()->removedText << current;
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void FolderBrowserItem::processNamespace( NamespaceDom ns, bool remove )
+{
+ NamespaceDomBrowserItem* item = m_namespaces.contains( ns->name() ) ? m_namespaces[ ns->name() ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new NamespaceDomBrowserItem( this, ns );
+ if( listView()->removedText.contains(ns->name()) )
+ item->setOpen( true );
+ m_namespaces.insert( ns->name(), item );
+ }
+
+ NamespaceList namespaceList = ns->namespaceList();
+ ClassList classList = ns->classList();
+ TypeAliasList typeAliasList = ns->typeAliasList();
+ FunctionList functionList = ns->functionList();
+ VariableList variableList = ns->variableList();
+
+ for( NamespaceList::Iterator it=namespaceList.begin(); it!=namespaceList.end(); ++it )
+ item->processNamespace( *it, remove );
+ for( ClassList::Iterator it=classList.begin(); it!=classList.end(); ++it )
+ item->processClass( *it, remove );
+ for( TypeAliasList::Iterator it=typeAliasList.begin(); it!=typeAliasList.end(); ++it )
+ item->processTypeAlias( *it, remove );
+ for( FunctionList::Iterator it=functionList.begin(); it!=functionList.end(); ++it )
+ item->processFunction( *it, remove );
+ for( VariableList::Iterator it=variableList.begin(); it!=variableList.end(); ++it )
+ item->processVariable( *it, remove );
+
+ if( remove && item->childCount() == 0 ){
+ m_namespaces.remove( ns->name() );
+ if( item->isOpen() ){
+ listView()->removedText << ns->name();
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void FolderBrowserItem::processClass( ClassDom klass, bool remove )
+{
+ ClassDomBrowserItem* item = m_classes.contains( klass ) ? m_classes[ klass ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new ClassDomBrowserItem( this, klass );
+ if( listView()->removedText.contains(klass->name()) )
+ item->setOpen( true );
+ m_classes.insert( klass, item );
+ }
+
+ ClassList classList = klass->classList();
+ TypeAliasList typeAliasList = klass->typeAliasList();
+ FunctionList functionList = klass->functionList();
+ VariableList variableList = klass->variableList();
+
+ for( ClassList::Iterator it=classList.begin(); it!=classList.end(); ++it )
+ item->processClass( *it, remove );
+ for( TypeAliasList::Iterator it=typeAliasList.begin(); it!=typeAliasList.end(); ++it )
+ item->processTypeAlias( *it, remove );
+ for( FunctionList::Iterator it=functionList.begin(); it!=functionList.end(); ++it )
+ item->processFunction( *it, remove );
+ for( VariableList::Iterator it=variableList.begin(); it!=variableList.end(); ++it )
+ item->processVariable( *it, remove );
+
+ if( remove && item->childCount() == 0 ){
+ m_classes.remove( klass );
+ if( item->isOpen() ){
+ listView()->removedText << klass->name();
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void FolderBrowserItem::processTypeAlias( TypeAliasDom typeAlias, bool remove )
+{
+ TypeAliasDomBrowserItem* item = m_typeAliases.contains( typeAlias ) ? m_typeAliases[ typeAlias ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new TypeAliasDomBrowserItem( this, typeAlias );
+ if( listView()->removedText.contains(typeAlias->name()) )
+ item->setOpen( true );
+ m_typeAliases.insert( typeAlias, item );
+ }
+
+ if( remove && item->childCount() == 0 ){
+ m_typeAliases.remove( typeAlias );
+ if( item->isOpen() ){
+ listView()->removedText << typeAlias->name();
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void FolderBrowserItem::processFunction( FunctionDom fun, bool remove )
+{
+ FunctionDomBrowserItem* item = m_functions.contains( fun ) ? m_functions[ fun ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new FunctionDomBrowserItem( this, fun );
+ m_functions.insert( fun, item );
+ }
+
+ if( remove ){
+ m_functions.remove( fun );
+ delete( item );
+ item = 0;
+ }
+}
+
+void FolderBrowserItem::processVariable( VariableDom var, bool remove )
+{
+ VariableDomBrowserItem* item = m_variables.contains( var ) ? m_variables[ var ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new VariableDomBrowserItem( this, var );
+ m_variables.insert( var, item );
+ }
+
+ if( remove ){
+ m_variables.remove( var );
+ delete( item );
+ item = 0;
+ }
+}
+
+// ------------------------------------------------------------------------
+bool NamespaceDomBrowserItem::selectItem( ItemDom item)
+{
+ if(item->kind() == CodeModelItem::Class) {
+ if( selectItemG ( item, m_classes ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::Function) {
+ if( selectItemG ( item, m_functions ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::TypeAlias) {
+ if( selectItemG ( item, m_typeAliases ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::Variable) {
+ if( selectItemG ( item, m_variables ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::Namespace) {
+ ///currently not neccessary..
+ }
+
+ for(QMap<ClassDom, ClassDomBrowserItem*>::Iterator it = m_classes.begin(); it != m_classes.end(); ++it) {
+ if( (*it)->selectItem(item) )
+ return true;
+ }
+
+ for(QMap<QString, NamespaceDomBrowserItem*>::Iterator it = m_namespaces.begin(); it != m_namespaces.end(); ++it) {
+ if( (*it)->selectItem(item) )
+ return true;
+ }
+ return false;
+}
+
+
+void NamespaceDomBrowserItem::processNamespace( NamespaceDom ns, bool remove )
+{
+ NamespaceDomBrowserItem* item = m_namespaces.contains( ns->name() ) ? m_namespaces[ ns->name() ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new NamespaceDomBrowserItem( this, ns );
+ if( listView()->removedText.contains(ns->name()) )
+ item->setOpen( true );
+ m_namespaces.insert( ns->name(), item );
+ }
+
+ NamespaceList namespaceList = ns->namespaceList();
+ ClassList classList = ns->classList();
+ TypeAliasList typeAliasList = ns->typeAliasList();
+ FunctionList functionList = ns->functionList();
+ VariableList variableList = ns->variableList();
+
+ for( NamespaceList::Iterator it=namespaceList.begin(); it!=namespaceList.end(); ++it )
+ item->processNamespace( *it, remove );
+ for( ClassList::Iterator it=classList.begin(); it!=classList.end(); ++it )
+ item->processClass( *it, remove );
+ for( TypeAliasList::Iterator it=typeAliasList.begin(); it!=typeAliasList.end(); ++it )
+ item->processTypeAlias( *it, remove );
+ for( FunctionList::Iterator it=functionList.begin(); it!=functionList.end(); ++it )
+ item->processFunction( *it, remove );
+ for( VariableList::Iterator it=variableList.begin(); it!=variableList.end(); ++it )
+ item->processVariable( *it, remove );
+
+ if( remove && item->childCount() == 0 ){
+ m_namespaces.remove( ns->name() );
+ if( item->isOpen() ){
+ listView()->removedText << ns->name();
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void NamespaceDomBrowserItem::processClass( ClassDom klass, bool remove )
+{
+ ClassDomBrowserItem* item = m_classes.contains( klass ) ? m_classes[ klass ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new ClassDomBrowserItem( this, klass );
+ if( listView()->removedText.contains(klass->name()) )
+ item->setOpen( true );
+ m_classes.insert( klass, item );
+ }
+
+ ClassList classList = klass->classList();
+ TypeAliasList typeAliasList = klass->typeAliasList();
+ FunctionList functionList = klass->functionList();
+ VariableList variableList = klass->variableList();
+
+ for( ClassList::Iterator it=classList.begin(); it!=classList.end(); ++it )
+ item->processClass( *it, remove );
+ for( TypeAliasList::Iterator it=typeAliasList.begin(); it!=typeAliasList.end(); ++it )
+ item->processTypeAlias( *it, remove );
+ for( FunctionList::Iterator it=functionList.begin(); it!=functionList.end(); ++it )
+ item->processFunction( *it, remove );
+ for( VariableList::Iterator it=variableList.begin(); it!=variableList.end(); ++it )
+ item->processVariable( *it, remove );
+
+ if( remove && item->childCount() == 0 ){
+ m_classes.remove( klass );
+ if( item->isOpen() ){
+ listView()->removedText << klass->name();
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void NamespaceDomBrowserItem::processTypeAlias( TypeAliasDom typeAlias, bool remove )
+{
+ TypeAliasDomBrowserItem* item = m_typeAliases.contains( typeAlias ) ? m_typeAliases[ typeAlias ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new TypeAliasDomBrowserItem( this, typeAlias );
+ if( listView()->removedText.contains(typeAlias->name()) )
+ item->setOpen( true );
+ m_typeAliases.insert( typeAlias, item );
+ }
+
+ if( remove && item->childCount() == 0 ){
+ m_typeAliases.remove( typeAlias );
+ if( item->isOpen() ){
+ listView()->removedText << typeAlias->name();
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void NamespaceDomBrowserItem::processFunction( FunctionDom fun, bool remove )
+{
+ FunctionDomBrowserItem* item = m_functions.contains( fun ) ? m_functions[ fun ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new FunctionDomBrowserItem( this, fun );
+ m_functions.insert( fun, item );
+ }
+
+ if( remove ){
+ m_functions.remove( fun );
+ delete( item );
+ item = 0;
+ }
+}
+
+void NamespaceDomBrowserItem::processVariable( VariableDom var, bool remove )
+{
+ VariableDomBrowserItem* item = m_variables.contains( var ) ? m_variables[ var ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new VariableDomBrowserItem( this, var );
+ m_variables.insert( var, item );
+ }
+
+ if( remove ){
+ m_variables.remove( var );
+ delete( item );
+ item = 0;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+
+bool ClassDomBrowserItem::selectItem(ItemDom item)
+{
+ if(item->kind() == CodeModelItem::Class) {
+ if( selectItemG ( item, m_classes ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::Function) {
+ if( selectItemG ( item, m_functions ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::TypeAlias) {
+ if( selectItemG ( item, m_typeAliases ) ) return true;
+ }
+
+ if(item->kind() == CodeModelItem::Variable) {
+ if( selectItemG ( item, m_variables ) ) return true;
+ }
+
+ for(QMap<ClassDom, ClassDomBrowserItem*>::Iterator it = m_classes.begin(); it != m_classes.end(); ++it) {
+ if( (*it)->selectItem(item) )
+ return true;
+ }
+ return false;
+}
+
+
+void ClassDomBrowserItem::processClass( ClassDom klass, bool remove )
+{
+ ClassDomBrowserItem* item = m_classes.contains( klass ) ? m_classes[ klass ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new ClassDomBrowserItem( this, klass );
+ if( listView()->removedText.contains(klass->name()) )
+ item->setOpen( true );
+ m_classes.insert( klass, item );
+ }
+
+ ClassList classList = klass->classList();
+ TypeAliasList typeAliasList = klass->typeAliasList();
+ FunctionList functionList = klass->functionList();
+ VariableList variableList = klass->variableList();
+
+ for( ClassList::Iterator it=classList.begin(); it!=classList.end(); ++it )
+ item->processClass( *it, remove );
+ for( TypeAliasList::Iterator it=typeAliasList.begin(); it!=typeAliasList.end(); ++it )
+ item->processTypeAlias( *it, remove );
+ for( FunctionList::Iterator it=functionList.begin(); it!=functionList.end(); ++it )
+ item->processFunction( *it, remove );
+ for( VariableList::Iterator it=variableList.begin(); it!=variableList.end(); ++it )
+ item->processVariable( *it, remove );
+
+ if( remove && item->childCount() == 0 ){
+ m_classes.remove( klass );
+ if( item->isOpen() ){
+ listView()->removedText << klass->name();
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void ClassDomBrowserItem::processTypeAlias( TypeAliasDom typeAlias, bool remove )
+{
+ TypeAliasDomBrowserItem* item = m_typeAliases.contains( typeAlias ) ? m_typeAliases[ typeAlias ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new TypeAliasDomBrowserItem( this, typeAlias );
+ if( listView()->removedText.contains(typeAlias->name()) )
+ item->setOpen( true );
+ m_typeAliases.insert( typeAlias, item );
+ }
+
+ if( remove && item->childCount() == 0 ){
+ m_typeAliases.remove( typeAlias );
+ if( item->isOpen() ){
+ listView()->removedText << typeAlias->name();
+ }
+ delete( item );
+ item = 0;
+ }
+}
+
+void ClassDomBrowserItem::processFunction( FunctionDom fun, bool remove )
+{
+ FunctionDomBrowserItem* item = m_functions.contains( fun ) ? m_functions[ fun ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new FunctionDomBrowserItem( this, fun );
+ m_functions.insert( fun, item );
+ }
+
+ if( remove ){
+ m_functions.remove( fun );
+ delete( item );
+ item = 0;
+ }
+}
+
+void ClassDomBrowserItem::processVariable( VariableDom var, bool remove )
+{
+ VariableDomBrowserItem* item = m_variables.contains( var ) ? m_variables[ var ] : 0;
+ if( !item ){
+ if( remove )
+ return;
+
+ item = new VariableDomBrowserItem( this, var );
+ m_variables.insert( var, item );
+ }
+
+ if( remove ){
+ m_variables.remove( var );
+ delete( item );
+ item = 0;
+ }
+}
+
+void FolderBrowserItem::setup( )
+{
+ ClassViewItem::setup();
+ setPixmap( 0, SmallIcon("folder") );
+ setExpandable( true );
+}
+
+void NamespaceDomBrowserItem::setup( )
+{
+ ClassViewItem::setup();
+ setPixmap( 0, UserIcon("CVnamespace", KIcon::DefaultState, listView()->m_part->instance()) );
+ setExpandable( true );
+
+ QString txt = listView()->m_part->languageSupport()->formatModelItem(m_dom.data(), true);
+ setText( 0, txt );
+}
+
+void ClassDomBrowserItem::setup( )
+{
+ ClassViewItem::setup();
+ setPixmap( 0, UserIcon("CVclass", KIcon::DefaultState, listView()->m_part->instance()) );
+ setExpandable( true );
+
+ QString txt = listView()->m_part->languageSupport()->formatModelItem(m_dom.data(), true);
+ setText( 0, txt );
+}
+
+void TypeAliasDomBrowserItem::setup( )
+{
+ ClassViewItem::setup();
+ setPixmap( 0, UserIcon("CVtypedef", KIcon::DefaultState, listView()->m_part->instance()) );
+ setExpandable( false );
+
+ QString txt = listView()->m_part->languageSupport()->formatModelItem(m_dom.data(), true);
+ setText( 0, txt );
+}
+
+void FunctionDomBrowserItem::setup( )
+{
+ ClassViewItem::setup();
+
+ QString iconName;
+ QString methodType;
+
+ if ( m_dom->isSignal() )
+ methodType = "signal";
+ else if (m_dom->isSlot() )
+ methodType = "slot";
+ else
+ methodType = "meth";
+
+ if( m_dom->access() == CodeModelItem::Private )
+ iconName = "CVprivate_" + methodType;
+ else if( m_dom->access() == CodeModelItem::Protected )
+ iconName = "CVprotected_" + methodType;
+ else
+ iconName = "CVpublic_" + methodType;
+
+ setPixmap( 0, UserIcon(iconName, KIcon::DefaultState, listView()->m_part->instance()) );
+
+ QString txt = listView()->m_part->languageSupport()->formatModelItem(m_dom.data(), true);
+
+ item() = highlightFunctionName(txt, 1, m_styles);
+}
+
+void FunctionDomBrowserItem::openDeclaration()
+{
+ int startLine, startColumn;
+ m_dom->getStartPosition( &startLine, &startColumn );
+ listView()->m_part->partController()->editDocument( KURL(m_dom->fileName()), startLine );
+}
+
+void FunctionDomBrowserItem::openImplementation()
+{
+ FunctionDefinitionList lst;
+ FileList fileList = listView()->m_part->codeModel()->fileList();
+ CodeModelUtils::findFunctionDefinitions( FindOp(m_dom), fileList, lst );
+
+ if( lst.isEmpty() )
+ return;
+
+ FunctionDefinitionDom fun;
+ QFileInfo fileInfo( m_dom->fileName() );
+ QString path = fileInfo.dirPath( true );
+
+ for( FunctionDefinitionList::Iterator it=lst.begin(); it!=lst.end(); ++it )
+ {
+ QFileInfo defFileInfo( (*it)->fileName() );
+ QString defPath = defFileInfo.dirPath( true );
+
+ if( path != defPath )
+ continue;
+
+ if( defFileInfo.baseName() == fileInfo.baseName() ) {
+ fun = *it;
+ } else if( !fun ) {
+ fun = *it;
+ }
+ }
+
+ if( !fun ) {
+ fun = lst.front();
+ }
+
+ int startLine, startColumn;
+ fun->getStartPosition( &startLine, &startColumn );
+ listView()->m_part->partController()->editDocument( KURL(fun->fileName()), startLine );
+}
+
+void VariableDomBrowserItem::setup( )
+{
+ ClassViewItem::setup();
+ QString iconName;
+ if( m_dom->access() == CodeModelItem::Private )
+ iconName = "CVprivate_var";
+ else if( m_dom->access() == CodeModelItem::Protected )
+ iconName = "CVprotected_var";
+ else
+ iconName = "CVpublic_var";
+
+ setPixmap( 0, UserIcon(iconName, KIcon::DefaultState, listView()->m_part->instance()) );
+
+ QString txt = listView()->m_part->languageSupport()->formatModelItem(m_dom.data(), true);
+ setText( 0, txt );
+}
+
+void VariableDomBrowserItem::openDeclaration()
+{
+ int startLine, startColumn;
+ m_dom->getStartPosition( &startLine, &startColumn );
+
+ listView()->m_part->partController()->editDocument( KURL(m_dom->fileName()), startLine );
+}
+
+void VariableDomBrowserItem::openImplementation()
+{
+}
+
+QString FolderBrowserItem::key( int , bool ) const
+{
+ return "0 " + text( 0 );
+}
+
+QString NamespaceDomBrowserItem::key( int , bool ) const
+{
+ return "1 " + text( 0 );
+}
+
+QString ClassDomBrowserItem::key( int , bool ) const
+{
+ return "2 " + text( 0 );
+}
+
+QString TypeAliasDomBrowserItem::key( int , bool ) const
+{
+ return "3 " + text( 0 );
+}
+
+QString FunctionDomBrowserItem::key( int , bool ) const
+{
+ return "4 " + text( 0 );
+}
+
+QString VariableDomBrowserItem::key( int , bool ) const
+{
+ return "5 " + text( 0 );
+}
+
+void ClassViewWidget::slotNewClass( )
+{
+ if( m_part->languageSupport()->features() & KDevLanguageSupport::NewClass )
+ m_part->languageSupport()->addClass();
+}
+
+void ClassViewWidget::slotAddMethod( )
+{
+ if ( !selectedItem() ) return;
+
+ if( m_part->languageSupport()->features() & KDevLanguageSupport::AddMethod )
+ m_part->languageSupport()->addMethod( static_cast<ClassDomBrowserItem*>( selectedItem() )->dom() );
+}
+
+void ClassViewWidget::slotAddAttribute( )
+{
+ if ( !selectedItem() ) return;
+
+ if( m_part->languageSupport()->features() & KDevLanguageSupport::AddAttribute )
+ m_part->languageSupport()->addAttribute( static_cast<ClassDomBrowserItem*>( selectedItem() )->dom() );
+}
+
+void ClassViewWidget::slotOpenDeclaration( )
+{
+ if ( !selectedItem() ) return;
+
+ static_cast<ClassViewItem*>( selectedItem() )->openDeclaration();
+}
+
+void ClassViewWidget::slotOpenImplementation( )
+{
+ if ( !selectedItem() ) return;
+
+ static_cast<ClassViewItem*>( selectedItem() )->openImplementation();
+}
+
+void ClassDomBrowserItem::openDeclaration( )
+{
+ int startLine, startColumn;
+ m_dom->getStartPosition( &startLine, &startColumn );
+ listView()->m_part->partController()->editDocument( KURL(m_dom->fileName()), startLine );
+}
+
+void TypeAliasDomBrowserItem::openDeclaration( )
+{
+ int startLine, startColumn;
+ m_dom->getStartPosition( &startLine, &startColumn );
+ listView()->m_part->partController()->editDocument( KURL(m_dom->fileName()), startLine );
+}
+
+bool FunctionDomBrowserItem::hasImplementation() const
+{
+ FunctionDefinitionList lst;
+ FileList fileList = listView()->m_part->codeModel()->fileList();
+ CodeModelUtils::findFunctionDefinitions( FindOp(m_dom), fileList, lst );
+
+ return !lst.isEmpty();
+}
+
+void ClassViewWidget::maybeTip( QPoint const & p )
+{
+ ClassViewItem * item = dynamic_cast<ClassViewItem*>( itemAt( p ) );
+ if ( !item ) return;
+
+ QString tooltip;
+
+ if ( item->isNamespace() )
+ {
+ NamespaceDomBrowserItem * nitem = dynamic_cast<NamespaceDomBrowserItem*>( item );
+ if ( nitem )
+ {
+ tooltip = nitem->dom()->scope().join("::") + "::" + nitem->dom()->name();
+ }
+ }
+ else if ( item->isClass() )
+ {
+ ClassDomBrowserItem * citem = dynamic_cast<ClassDomBrowserItem*>( item );
+ if ( citem )
+ {
+ tooltip = citem->dom()->scope().join("::") + "::"
+ + citem->dom()->name() + " : "
+ + citem->dom()->baseClassList().join(", ");
+ }
+ }
+ else if ( item->isFunction() )
+ {
+ FunctionDomBrowserItem * fitem = dynamic_cast<FunctionDomBrowserItem*>( item );
+ if ( fitem )
+ {
+ QString access;
+ if ( fitem->dom()->access() == CodeModelItem::Private )
+ access = "[private] ";
+ else if ( fitem->dom()->access() == CodeModelItem::Protected )
+ access = "[protected] ";
+ else if ( fitem->dom()->access() == CodeModelItem::Public )
+ access = "[public] ";
+
+ QStringList arguments;
+ ArgumentList const & list = fitem->dom()->argumentList();
+ ArgumentList::ConstIterator it( list.begin() );
+ while ( it != list.end() )
+ {
+ arguments << ((*it)->type() + " " + (*it)->name());
+ ++it;
+ }
+
+ QString strstatic = fitem->dom()->isStatic() ? QString( "[static] " ) : QString::null;
+ QString strsignal = fitem->dom()->isSignal() ? QString( "[signal] " ) : QString::null;
+ QString strslot = fitem->dom()->isSlot() ? QString( "[slot] " ) : QString::null;
+ QString strresult = !fitem->dom()->resultType().isEmpty() ? fitem->dom()->resultType() + " " : QString::null;
+
+ QString strconstant = fitem->dom()->isConstant() ? QString( " [const]" ) : QString::null;
+ QString strabstract = fitem->dom()->isAbstract() ? QString( " [abstract]" ) : QString::null;
+
+ tooltip = access + strstatic + strsignal + strslot + strresult
+ + fitem->dom()->scope().join("::") + "::" + fitem->dom()->name()
+ + "(" + arguments.join(", ") + ")" + strconstant + strabstract;
+ }
+ }
+ else if ( item->isVariable() )
+ {
+ VariableDomBrowserItem * vitem = dynamic_cast<VariableDomBrowserItem*>( item );
+ if ( vitem )
+ {
+ QString access;
+ if ( vitem->dom()->access() == CodeModelItem::Private )
+ access = "[private] ";
+ else if ( vitem->dom()->access() == CodeModelItem::Protected )
+ access = "[protected] ";
+ else if ( vitem->dom()->access() == CodeModelItem::Public )
+ access = "[public] ";
+
+ QString strstatic = vitem->dom()->isStatic() ? QString( "[static] " ) : QString::null;
+ tooltip = access + strstatic + vitem->dom()->type() + " " + vitem->dom()->name();
+ }
+ }
+ else if ( item->isTypeAlias() )
+ {
+ if( TypeAliasDomBrowserItem * titem = dynamic_cast<TypeAliasDomBrowserItem*>( item ) )
+ {
+ tooltip = QString( "[Type] " ) + titem->dom()->type() + " " + titem->dom()->name();
+ }
+ }
+
+ const int maxCommentSize = 300;
+
+ if( !item->comment().isEmpty() ) {
+ tooltip += "\n";
+ tooltip += item->comment().length() > maxCommentSize ? item->comment().left( maxCommentSize ) + " [...]" : item->comment();
+ }
+
+ kdDebug(0) << tooltip << endl;
+
+ QRect r = itemRect( item );
+
+ if ( item && r.isValid() && !tooltip.isEmpty() )
+ {
+ tip( r, QString("<qt><pre>") + QStyleSheet::escape( tooltip ) + QString("</pre></qt>") );
+ }
+}
+
+void ClassViewWidget::slotCreateAccessMethods( )
+{
+ if ( !selectedItem() ) return;
+
+ if( m_part->languageSupport()->features() & KDevLanguageSupport::CreateAccessMethods )
+ {
+ VariableDomBrowserItem* item = dynamic_cast<VariableDomBrowserItem*>( selectedItem() );
+ if (item == 0)
+ return;
+
+ m_part->languageSupport()->createAccessMethods(static_cast<ClassModel*>(static_cast<ClassDomBrowserItem*>(item->parent())->dom()),static_cast<VariableModel*>(item->dom()));
+ }
+}
+
+void ClassViewWidget::slotFollowEditor()
+{
+ m_doFollowEditor = m_actionFollowEditor->isChecked();
+}
+
+bool ClassViewWidget::doFollowEditor()
+{
+ return m_doFollowEditor;
+}
+
+
+#include "classviewwidget.moc"