KDE/kdevelop/lib

Dukju Ahn dukjuahn at gmail.com
Mon May 28 08:04:41 UTC 2007


SVN commit 668957 by dukjuahn:

Make project loading totally asynchronous. 
1. Used threadweaver for ImportJob
2. Doesn't invoke setIcon() for the whole tree. Rather, setIcon()
is called whenever the item is expanded via QStandardItemModel::fetchMore()
This was necessary because items are created at separated thread, and KIO:: fails at multithreaded environment.

CCMAIL: kdevelop-devel at kdevelop.org



 M  +1 -0      project/CMakeLists.txt  
 M  +25 -21    project/importprojectjob.cpp  
 M  +13 -2     project/importprojectjob.h  
 A             project/importprojectthread.cpp   [License: LGPL (v2+)]
 A             project/importprojectthread.h   [License: LGPL (v2+)]
 M  +41 -3     project/projectmodel.cpp  
 M  +12 -0     project/projectmodel.h  
 M  +16 -4     shell/project.cpp  
 M  +4 -0      shell/project.h  
 M  +12 -5     shell/projectcontroller.cpp  
 M  +1 -0      shell/projectcontroller.h  


--- trunk/KDE/kdevelop/lib/project/CMakeLists.txt #668956:668957
@@ -7,6 +7,7 @@
     projectmodel.cpp
     projectconfigskeleton.cpp
     importprojectjob.cpp
+    importprojectthread.cpp
 	interfaces/iprojectbuilder.cpp
     interfaces/iprojectfilemanager.cpp
     interfaces/ibuildsystemmanager.cpp
--- trunk/KDE/kdevelop/lib/project/importprojectjob.cpp #668956:668957
@@ -19,34 +19,40 @@
 */
 
 #include "importprojectjob.h"
+#include "importprojectthread.h"
 
 #include "interfaces/iprojectfilemanager.h"
+#include "projectmodel.h"
 
 #include <kglobal.h>
 #include <kdebug.h>
+#include <threadweaver/ThreadWeaver.h>
 
 namespace KDevelop
 {
 
 struct ImportProjectJobPrivate
 {
-    ProjectFolderItem *m_folder;
-    IProjectFileManager *m_importer;
-    QList<ProjectFolderItem*> m_workingList;
+    ThreadWeaver::Weaver *m_weaver;
+    ImportProjectThread *m_weaverJob;
 };
 
 ImportProjectJob::ImportProjectJob(QStandardItem *folder, IProjectFileManager *importer)
     : KJob(0), d(new ImportProjectJobPrivate)
 
 {
-    d->m_importer = importer;
-    d->m_folder = 0;
+    d->m_weaver = new ThreadWeaver::Weaver( this );
+    d->m_weaverJob = new ImportProjectThread( this );
+
+    d->m_weaverJob->setProjectFileManager( importer );
+    ProjectFolderItem *folderItem = 0;
     if ( folder->type() == ProjectBaseItem::Folder ||
          folder->type() == ProjectBaseItem::BuildFolder ||
          folder->type() == ProjectBaseItem::Project )
     {
-        d->m_folder = dynamic_cast<ProjectFolderItem*>( folder );
+        folderItem = dynamic_cast<ProjectFolderItem*>( folder );
     }
+    d->m_weaverJob->setProjectFolderItem( folderItem );
 }
 
 ImportProjectJob::~ImportProjectJob()
@@ -56,28 +62,26 @@
 
 void ImportProjectJob::start()
 {
-    if ( d->m_folder )
-        startNextJob( d->m_folder );
+    if( !(d->m_weaverJob) )
+        return;
 
-    emitResult();
-}
+    d->m_weaver->enqueue( d->m_weaverJob );
+    connect( d->m_weaverJob, SIGNAL(done(ThreadWeaver::Job*)), this, SLOT(slotDone(ThreadWeaver::Job*)) );
 
-void ImportProjectJob::startNextJob(ProjectFolderItem *dom)
-{
-    d->m_workingList += d->m_importer->parse(dom);
-    while ( !d->m_workingList.isEmpty() )
-    {
-      ProjectFolderItem *folder = d->m_workingList.first();
-      d->m_workingList.pop_front();
-
-      startNextJob(folder);
-    }
+//     d->m_weaverJob->start();
+//     connect( d->m_weaverJob, SIGNAL(finished()), this, SLOT(slotFinished()) );
 }
 
-void ImportProjectJob::processList()
+void ImportProjectJob::slotDone(ThreadWeaver::Job*)
 {
+    emitResult();
 }
 
+// void ImportProjectJob::slotFinished()
+// {
+//     emitResult();
+// }
+
 }
 #include "importprojectjob.moc"
 
--- trunk/KDE/kdevelop/lib/project/importprojectjob.h #668956:668957
@@ -21,13 +21,21 @@
 #define KDEVIMPORTPROJECTJOB_H
 
 #include <kjob.h>
-#include "projectmodel.h"
+// #include "projectmodel.h"
 #include "kdevexport.h"
 
+class QStandardItem;
+
+namespace ThreadWeaver
+{
+class Job;
+}
+
 namespace KDevelop
 {
 
 class IProjectFileManager;
+class ProjectFolderItem;
 
 class KDEVPLATFORMPROJECT_EXPORT ImportProjectJob: public KJob
 {
@@ -42,8 +50,11 @@
 protected:
     void startNextJob(ProjectFolderItem *folder);
     void slotResult(KJob *job);
-    void processList();
 
+protected Q_SLOTS:
+    void slotDone(ThreadWeaver::Job*);
+//     void slotFinished();
+
 private:
     struct ImportProjectJobPrivate* const d;
 };
--- trunk/KDE/kdevelop/lib/project/projectmodel.cpp #668956:668957
@@ -95,6 +95,10 @@
         parent->setChild( parent->rowCount(), this );
 }
 
+void ProjectBaseItem::setIcon()
+{
+}
+
 void ProjectBaseItem::add( ProjectBaseItem* item )
 {
     setChild( rowCount(), item );
@@ -218,7 +222,29 @@
     reset();
 }
 
+void ProjectModel::fetchMore( const QModelIndex &parent )
+{
+    QStandardItem *parentItem = itemFromIndex( parent );
+    if( !parentItem )
+        return;
+    int rowcount = parentItem->rowCount();
+    for( int i=0; i<rowcount; i++ )
+    {
+        ProjectBaseItem *childItem = dynamic_cast<ProjectBaseItem*>(parentItem->child(i));
+        if( childItem && childItem->icon().isNull() )
+            childItem->setIcon();
+    }
+}
 
+bool ProjectModel::canFetchMore( const QModelIndex & parent ) const
+{
+    QStandardItem *parentItem = itemFromIndex( parent );
+    if( !parentItem )
+        return false;
+    return true;
+}
+
+
 ProjectFolderItem::ProjectFolderItem( IProject* project, const KUrl & dir, QStandardItem * parent )
         : ProjectBaseItem( *new ProjectFolderItemPrivate )
 {
@@ -227,7 +253,6 @@
     d->m_url = dir;
     setParent(parent);
     setText( dir.fileName() );
-    setIcon( KIO::pixmapForUrl( url(), 0, K3Icon::Small ) );
 }
 
 ProjectFolderItem::ProjectFolderItem( ProjectFolderItemPrivate& dd)
@@ -262,6 +287,11 @@
     setText( url.fileName() );
 }
 
+void ProjectFolderItem::setIcon()
+{
+    QStandardItem::setIcon( KIO::pixmapForUrl( url(), 0, K3Icon::Small ) );
+}
+
 ProjectBuildFolderItem::ProjectBuildFolderItem( ProjectBuildFolderItemPrivate& dd )
     : ProjectFolderItem( dd )
 {
@@ -274,7 +304,6 @@
     d->project = project;
     setUrl( dir );
     setParent( parent );
-    setIcon( KIcon("folder-development") );
 }
 
 int ProjectBuildFolderItem::type() const
@@ -300,6 +329,11 @@
     return d->m_env;
 }
 
+void ProjectBuildFolderItem::setIcon()
+{
+    QStandardItem::setIcon( KIcon("folder-development") );
+}
+
 ProjectFileItem::ProjectFileItem( ProjectFileItemPrivate& dd)
     : ProjectBaseItem(dd)
 {
@@ -313,7 +347,6 @@
     d->m_url = file;
     setText( file.fileName() );
     setParent( parent );
-    setIcon( KIO::pixmapForUrl( url(), 0, K3Icon::Small ) );
 }
 
 const KUrl & ProjectFileItem::url( ) const
@@ -338,6 +371,11 @@
     return const_cast<ProjectFileItem*>( this );
 }
 
+void ProjectFileItem::setIcon()
+{
+    QStandardItem::setIcon( KIO::pixmapForUrl( url(), 0, K3Icon::Small ) );
+}
+
 ProjectTargetItem::ProjectTargetItem( ProjectTargetItemPrivate& dd)
     : ProjectBaseItem( dd )
 {
--- trunk/KDE/kdevelop/lib/project/projectmodel.h #668956:668957
@@ -81,6 +81,7 @@
         virtual ProjectItem* projectItem() const;
 
         void setParent( QStandardItem* );
+        virtual void setIcon();
 
         QList<ProjectFolderItem*> folderList() const;
         QList<ProjectTargetItem*> targetList() const;
@@ -114,6 +115,9 @@
 
     /** Set the url of this folder */
     void setUrl( const KUrl& );
+
+    virtual void setIcon();
+
 protected:
     ProjectFolderItem( ProjectFolderItemPrivate& );
 private:
@@ -146,6 +150,9 @@
      * for all targets in this directory.
      */
     const QHash<QString, QString>& environment() const;
+
+    virtual void setIcon();
+
 protected:
     ProjectBuildFolderItem( ProjectBuildFolderItemPrivate& );
 private:
@@ -229,6 +236,8 @@
     const KUrl& url() const;
     void setUrl( const KUrl& );
 
+    virtual void setIcon();
+
 protected:
     ProjectFileItem( ProjectFileItemPrivate& );
 private:
@@ -247,6 +256,9 @@
 
         void resetModel();
 
+        virtual void fetchMore( const QModelIndex &parent );
+        virtual bool canFetchMore( const QModelIndex & parent ) const;
+
     private:
         class ProjectModelPrivate* const d;
 
--- trunk/KDE/kdevelop/lib/shell/project.cpp #668956:668957
@@ -73,6 +73,8 @@
     ProjectItem* topItem;
     QString name;
     KSharedConfig::Ptr m_cfg;
+    Project *project;
+
     QList<ProjectFileItem*> recurseFiles( ProjectBaseItem * projectItem )
     {
         QList<ProjectFileItem*> files;
@@ -103,9 +105,18 @@
         return files;
     }
 
-    void importDone( KJob* job )
+    void importDone( KJob* /*job*/ )
     {
-        job->deleteLater();
+        // set icon for toplevel file/dirs only. Subsequent children's icon will be set
+        // when the treeview is expanded
+        int rowcount = topItem->rowCount();
+        for( int i=0; i<rowcount; i++ )
+        {
+            ProjectBaseItem *childItem = dynamic_cast<ProjectBaseItem*>(topItem->child(i));
+            if( childItem )
+                childItem->setIcon();
+        }
+        emit project->importingFinished(project);
     }
 
 };
@@ -116,6 +127,7 @@
 {
     QDBusConnection::sessionBus().registerObject( "/org/kdevelop/Project", this, QDBusConnection::ExportScriptableSlots );
 
+    d->project = this;
     d->manager = 0;
     d->topItem = 0;
     d->tmp = 0;
@@ -244,9 +256,9 @@
     }
     if ( d->manager && iface )
     {
-        ProjectModel* model = Core::self()->projectController()->projectModel();
+//         ProjectModel* model = Core::self()->projectController()->projectModel();
         d->topItem = iface->import( this );
-        model->insertRow( model->rowCount(), d->topItem );
+//         model->insertRow( model->rowCount(), d->topItem );
 
         ImportProjectJob* importJob = new ImportProjectJob( d->topItem, iface );
         connect( importJob, SIGNAL( result( KJob* ) ), this, SLOT( importDone( KJob* ) ) );
--- trunk/KDE/kdevelop/lib/shell/project.h #668956:668957
@@ -81,6 +81,9 @@
     virtual KUrl projectFileUrl() const;
     virtual KSharedConfig::Ptr projectConfiguration() const;
 
+Q_SIGNALS:
+    void importingFinished(IProject*);
+
 public Q_SLOTS:
     /**
      * @brief Open a project
@@ -170,6 +173,7 @@
     Q_PRIVATE_SLOT(d, void importDone(KJob*) )
 
     class ProjectPrivate* const d;
+    friend class ProjectPrivate;
 };
 
 }
--- trunk/KDE/kdevelop/lib/shell/projectcontroller.cpp #668956:668957
@@ -220,7 +220,6 @@
     }
 
     //FIXME Create the hidden directory if it doesn't exist
-
     if ( loadProjectPart() )
     {
         //The project file has been opened.
@@ -231,23 +230,31 @@
     else
         return false;
 
-
-    IProject* project = new Project();
+    Project* project = new Project();
     if ( !project->open( url ) )
     {
         delete project;
         return false;
     }
+    connect( project, SIGNAL(importingFinished(IProject*)), this, SLOT(projectImportingFinished(IProject*)) );
+    return true;
+}
+
+bool ProjectController::projectImportingFinished( IProject* project )
+{
+    ProjectItem *topItem = project->projectItem();
+    ProjectModel *model = projectModel();
+    model->insertRow( model->rowCount(), topItem );
+
     d->m_projects.append( project );
 
-
 //     KActionCollection * ac = d->m_core->uiControllerInternal()->defaultMainWindow()->actionCollection();
 //     QAction * action;
 
     //action = ac->action( "project_close" );
     //action->setEnabled( true );
 
-    d->m_recentAction->addUrl( url );
+    d->m_recentAction->addUrl( project->projectFileUrl() );
     KSharedConfig * config = KGlobal::config().data();
     KConfigGroup recentGroup = config->group("RecentProjects");
     d->m_recentAction->saveEntries( recentGroup );
--- trunk/KDE/kdevelop/lib/shell/projectcontroller.h #668956:668957
@@ -53,6 +53,7 @@
 
 public Q_SLOTS:
     bool openProject( const KUrl &KDev4ProjectFile = KUrl() );
+    bool projectImportingFinished( IProject* );
     bool closeProject( IProject* );
 //     void changeCurrentProject( ProjectBaseItem* );
 




More information about the KDevelop-devel mailing list