1 /* This file is part of the KDE project
2 Copyright 2001 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
3 Copyright 2002-2003 Roberto Raggi <roberto@kdevelop.org>
4 Copyright 2002 Simon Hausmann <hausmann@kde.org>
5 Copyright 2003 Jens Dagerbo <jens.dagerbo@swipnet.se>
6 Copyright 2003 Mario Scalas <mario.scalas@libero.it>
7 Copyright 2003-2004 Alexander Dymo <adymo@kdevelop.org>
8 Copyright 2006 Matt Rogers <mattr@kde.org>
9 Copyright 2007 Andreas Pakulat <apaku@gmx.de>
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Library General Public License for more details.
21 You should have received a copy of the GNU Library General Public License
22 along with this library; see the file COPYING.LIB. If not, write to
23 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 Boston, MA 02110-1301, USA.
32 #include <QtDBus/QtDBus>
33 #include <QStandardItemModel>
36 #include <kconfiggroup.h>
39 #include <kio/netaccess.h>
40 #include <kio/global.h>
41 #include <kmessagebox.h>
42 #include <kio/jobclasses.h>
43 #include <ktemporaryfile.h>
46 #include <project/interfaces/iprojectfilemanager.h>
47 #include <project/interfaces/ibuildsystemmanager.h>
48 #include <interfaces/iplugin.h>
49 #include <interfaces/iplugincontroller.h>
50 #include <interfaces/iruncontroller.h>
51 #include <project/importprojectjob.h>
52 #include <project/projectmodel.h>
53 #include <language/duchain/indexedstring.h>
56 #include "mainwindow.h"
57 #include "projectcontroller.h"
58 #include "uicontroller.h"
68 KUrl developerFileUrl
;
69 QString developerTempFile
;
70 QString projectTempFile
;
74 ProjectFolderItem
* topItem
;
76 KSharedConfig::Ptr m_cfg
;
78 QSet
<KDevelop::IndexedString
> fileSet
;
80 QList
<ProjectFileItem
*> recurseFiles( ProjectBaseItem
* projectItem
)
82 QList
<ProjectFileItem
*> files
;
83 if ( ProjectFolderItem
* folder
= projectItem
->folder() )
85 QList
<ProjectFolderItem
*> folder_list
= folder
->folderList();
86 for ( QList
<ProjectFolderItem
*>::Iterator it
= folder_list
.begin(); it
!= folder_list
.end(); ++it
)
88 files
+= recurseFiles( ( *it
) );
91 QList
<ProjectTargetItem
*> target_list
= folder
->targetList();
92 for ( QList
<ProjectTargetItem
*>::Iterator it
= target_list
.begin(); it
!= target_list
.end(); ++it
)
94 files
+= recurseFiles( ( *it
) );
97 files
+= folder
->fileList();
99 else if ( ProjectTargetItem
* target
= projectItem
->target() )
101 files
+= target
->fileList();
103 else if ( ProjectFileItem
* file
= projectItem
->file() )
105 files
.append( file
);
110 QList
<ProjectBaseItem
*> itemsForUrlInternal( const KUrl
& url
, ProjectFolderItem
* folder
) const
112 QList
<ProjectBaseItem
*> files
;
116 if( folder
->url().equals( url
, KUrl::CompareWithoutTrailingSlash
) )
121 // Check top level files
122 foreach( ProjectFileItem
* file
, folder
->fileList() )
124 if( file
->url() == url
)
130 // Check top level targets
131 foreach( ProjectTargetItem
* target
, folder
->targetList() )
133 foreach( ProjectFileItem
* file
, target
->fileList() )
135 if( file
->url() == url
)
142 foreach( ProjectFolderItem
* top
, folder
->folderList() )
144 files
+= itemsForUrlInternal( url
, top
);
148 QList
<ProjectBaseItem
*> itemsForUrl( const KUrl
& url
) const
150 // TODO: This is moderately efficient, but could be much faster with a
151 // QHash<QString, ProjectFolderItem> member. Would it be worth it?
152 KUrl u
= topItem
->url();
153 if ( u
.protocol() != url
.protocol() || u
.host() != url
.host() )
154 return QList
<ProjectBaseItem
*>();
156 return itemsForUrlInternal( url
, topItem
);
160 void importDone( KJob
* )
162 Core::self()->projectControllerInternal()->projectImportingFinished( project
);
166 Project::Project( QObject
*parent
)
168 , d( new ProjectPrivate
)
170 QDBusConnection::sessionBus().registerObject( "/org/kdevelop/Project", this, QDBusConnection::ExportScriptableSlots
);
184 QString
Project::name() const
189 QString
Project::developerTempFile() const
191 return d
->developerTempFile
;
194 QString
Project::projectTempFile() const
196 return d
->projectTempFile
;
199 KSharedConfig::Ptr
Project::projectConfiguration() const
201 d
->m_cfg
->reparseConfiguration();
205 // void Project::setLocalFile( const KUrl& u )
210 // void Project::setGlobalFile( const KUrl& u )
212 // d->globalFile = u;
215 const KUrl
Project::folder() const
220 void Project::reloadModel()
222 ProjectModel
* model
= Core::self()->projectController()->projectModel();
223 model
->removeRow( d
->topItem
->row() );
224 IProjectFileManager
* iface
= d
->manager
->extension
<IProjectFileManager
>();
227 d
->topItem
= iface
->import( this );
230 KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(),
231 i18n("Could not open project") );
234 d
->topItem
->setIcon();
235 model
->appendRow(d
->topItem
);
236 // model->insertRow( model->rowCount(), d->topItem );
237 ImportProjectJob
* importJob
= new ImportProjectJob( d
->topItem
, iface
);
238 Core::self()->runController()->registerJob( importJob
);
242 bool Project::open( const KUrl
& projectFileUrl_
)
244 //Canonicalize the project url, because we do the same in many other cases with files,
245 //so we must canonicalize the project url too.
246 KUrl projectFileUrl
= projectFileUrl_
;
248 if ( projectFileUrl
.isLocalFile() )
250 QString path
= QFileInfo( projectFileUrl
.toLocalFile() ).canonicalFilePath();
251 if ( !path
.isEmpty() )
252 projectFileUrl
.setPath( path
);
255 KIO::StatJob
* statJob
= KIO::stat( projectFileUrl
, KIO::HideProgressInfo
);
256 if ( !statJob
->exec() ) //be sync for right now
258 KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(),
259 i18n( "Unable to load the project file %1",
260 projectFileUrl
.pathOrUrl() ) );
264 d
->projectFileUrl
= projectFileUrl
;
265 d
->developerFileUrl
= KUrl( projectFileUrl
.directory( KUrl::AppendTrailingSlash
) );
266 d
->developerFileUrl
.addPath(".kdev4");
267 d
->developerFileUrl
.addPath( projectFileUrl
.fileName() );
269 statJob
= KIO::stat( d
->developerFileUrl
, KIO::HideProgressInfo
);
270 if( !statJob
->exec() )
272 KUrl dir
= KUrl( projectFileUrl
.directory( KUrl::AppendTrailingSlash
) + ".kdev4");
273 statJob
= KIO::stat( dir
, KIO::HideProgressInfo
);
274 if( !statJob
->exec() )
276 KIO::SimpleJob
* mkdirJob
= KIO::mkdir( dir
);
277 if( !mkdirJob
->exec() )
280 Core::self()->uiController()->activeMainWindow(),
281 i18n("Unable to create hidden dir (%1) for developer file",
289 if( !KIO::NetAccess::download( d
->projectFileUrl
, d
->projectTempFile
,
290 Core::self()->uiController()->activeMainWindow() ) )
292 KMessageBox::sorry( Core::self()->uiController()->activeMainWindow(),
293 i18n("Unable to get project file: %1",
294 d
->projectFileUrl
.pathOrUrl() ) );
299 statJob
= KIO::stat( d
->developerFileUrl
, KIO::HideProgressInfo
);
300 if( !statJob
->exec() || !KIO::NetAccess::download( d
->developerFileUrl
, d
->developerTempFile
,
301 Core::self()->uiController()->activeMainWindow() ) )
304 d
->tmp
= new KTemporaryFile();
306 d
->developerTempFile
= d
->tmp
->fileName();
310 kDebug() << "Creating KConfig object for project files" << d
->developerTempFile
<< d
->projectTempFile
;
311 d
->m_cfg
= KSharedConfig::openConfig( d
->developerTempFile
);
312 d
->m_cfg
->addConfigSources( QStringList() << d
->projectTempFile
);
314 KConfigGroup
projectGroup( d
->m_cfg
, "Project" );
316 d
->name
= projectGroup
.readEntry( "Name", projectFileUrl
.fileName() );
317 d
->folder
= projectFileUrl
.directory( KUrl::AppendTrailingSlash
);
319 QString managerSetting
= projectGroup
.readEntry( "Manager", "KDevGenericManager" );
322 IPluginController
* pluginManager
= Core::self()->pluginController();
323 d
->manager
= pluginManager
->pluginForExtension( "org.kdevelop.IProjectFileManager", managerSetting
);
324 IProjectFileManager
* iface
= 0;
326 iface
= d
->manager
->extension
<IProjectFileManager
>();
329 KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(),
330 i18n( "Could not load project management plugin %1.",
335 if ( d
->manager
&& iface
)
337 // ProjectModel* model = Core::self()->projectController()->projectModel();
338 d
->topItem
= iface
->import( this );
341 KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(),
342 i18n("Could not open project") );
345 d
->topItem
->setIcon();
346 // model->insertRow( model->rowCount(), d->topItem );
347 ImportProjectJob
* importJob
= new ImportProjectJob( d
->topItem
, iface
);
348 connect( importJob
, SIGNAL( result( KJob
* ) ), this, SLOT( importDone( KJob
* ) ) );
349 importJob
->start(); //be asynchronous
353 KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(),
354 i18n( "project importing plugin (%1) does not support the IProjectFileManager interface.", managerSetting
) );
360 QString vcsPlugin
= projectGroup
.readEntry("VersionControlSupport", "");
361 if( !vcsPlugin
.isEmpty() )
363 d
->vcsPlugin
= pluginManager
->pluginForExtension( "org.kdevelop.IBasicVersionControl", vcsPlugin
);
369 void Project::close()
371 // unloaded by project controller, depending on shared count
372 // KPluginInfo* pluginInfo = Core::self()->pluginController()->pluginInfo( d->manager );
375 // Core::self()->pluginController()->unloadPlugin( pluginInfo->pluginName() );
378 //the manager plugin will be deleted in the plugin controller, so just set
379 //the manager to zero.
381 Core::self()->projectController()->projectModel()->removeRow( d
->topItem
->row() );
388 if( !KIO::NetAccess::upload( d
->developerTempFile
, d
->developerFileUrl
,
389 Core::self()->uiController()->activeMainWindow() ) )
391 KMessageBox::sorry( Core::self()->uiController()->activeMainWindow(),
392 i18n("Could not store developer specific project configuration.\n"
393 "Attention: The project settings you changed will be lost."
399 bool Project::inProject( const KUrl
& url
) const
401 if( url
.isLocalFile() && QFileInfo( url
.path() ).isFile() )
402 return d
->fileSet
.contains( IndexedString( url
) );
403 return ( !d
->itemsForUrl( url
).isEmpty() );
406 ProjectFileItem
* Project::fileAt( int num
) const
408 QList
<ProjectFileItem
*> files
;
410 files
= d
->recurseFiles( d
->topItem
);
412 if( !files
.isEmpty() && num
>= 0 && num
< files
.count() )
413 return files
.at( num
);
417 QList
<ProjectFileItem
*> KDevelop::Project::files() const
419 QList
<ProjectFileItem
*> files
;
421 files
= d
->recurseFiles( d
->topItem
);
425 QList
<ProjectFileItem
*> Project::filesForUrl(const KUrl
& url
) const
427 QList
<ProjectFileItem
*> items
;
428 foreach(ProjectBaseItem
* item
, d
->itemsForUrl( url
) )
430 if( item
->type() == ProjectBaseItem::File
)
431 items
<< dynamic_cast<ProjectFileItem
*>( item
);
436 QList
<ProjectFolderItem
*> Project::foldersForUrl(const KUrl
& url
) const
438 QList
<ProjectFolderItem
*> items
;
439 foreach(ProjectBaseItem
* item
, d
->itemsForUrl( url
) )
441 if( item
->type() == ProjectBaseItem::Folder
)
442 items
<< dynamic_cast<ProjectFolderItem
*>( item
);
447 int Project::fileCount() const
449 QList
<ProjectFileItem
*> files
;
451 files
= d
->recurseFiles( d
->topItem
);
452 return files
.count();
455 KUrl
Project::relativeUrl( const KUrl
& absolute
) const
457 kDebug() << "Creating relative url between: " << folder() << absolute
;
458 return KUrl::relativeUrl( folder(), absolute
);
461 KUrl
Project::urlRelativeToProject( const KUrl
& relativeUrl
) const
463 if ( KUrl::isRelativeUrl( relativeUrl
.toLocalFile() ) )
464 return KUrl( folder(), relativeUrl
.toLocalFile() );
469 IProjectFileManager
* Project::projectFileManager() const
471 return d
->manager
->extension
<IProjectFileManager
>();
474 IBuildSystemManager
* Project::buildSystemManager() const
476 return d
->manager
->extension
<IBuildSystemManager
>();
479 IPlugin
* Project::managerPlugin() const
484 void Project::setManagerPlugin( IPlugin
* manager
)
486 d
->manager
= manager
;
489 // PersistentHash * Project::persistentHash() const
491 // return &d->persistentHash;
494 KUrl
Project::projectFileUrl() const
496 return d
->projectFileUrl
;
499 KUrl
Project::developerFileUrl() const
501 return d
->developerFileUrl
;
504 ProjectFolderItem
* Project::projectItem() const
509 IPlugin
* Project::versionControlPlugin() const
515 void Project::addToFileSet( const IndexedString
& file
)
517 d
->fileSet
.insert( file
);
520 void Project::removeFromFileSet( const IndexedString
& file
)
522 d
->fileSet
.remove( file
);
525 QSet
<IndexedString
> Project::fileSet() const
532 #include "project.moc"