Commit 285add70 authored by Michal Humpula's avatar Michal Humpula

project: use ThreadWeaver for background tasks

REVIEW: 120485
parent 2718644d
# detect aditional frameworks
find_package(KF5 OPTIONAL_COMPONENTS Wallet Plasma Service ItemModels Notifications)
find_package(KF5 OPTIONAL_COMPONENTS Wallet Plasma Service ItemModels Notifications ThreadWeaver)
set_package_properties(KF5Wallet PROPERTIES PURPOSE "Required to build the katesql addon")
set_package_properties(KF5Plasma PROPERTIES PURPOSE "Required to build the sessionapplet addon")
set_package_properties(KF5Service PROPERTIES PURPOSE "Required to build the sessionapplet addon")
set_package_properties(KF5ItemModels PROPERTIES PURPOSE "Required to build the project, konsole addon")
set_package_properties(KF5Notifications PROPERTIES PURPOSE "Required to build the katebuild, close-except-like addon")
set_package_properties(KF5ThreadWeaver PROPERTIES PURPOSE "Required to build the project addon")
# document switcher
ecm_optional_add_subdirectory (filetree)
......@@ -13,10 +14,11 @@ ecm_optional_add_subdirectory (filetree)
# search in open documents and files
ecm_optional_add_subdirectory (search)
if(KF5ItemModels_FOUND)
if(KF5ItemModels_FOUND AND KF5ThreadWeaver_FOUND)
# small & smart project manager
ecm_optional_add_subdirectory (project)
endif()
if(KF5ItemModels_FOUND)
# terminal tool view
ecm_optional_add_subdirectory (konsole)
endif()
......
......@@ -7,7 +7,6 @@ if(LIBGIT2_FOUND)
set (PROJECT_OPTIONAL_LIBS LibGit2::LibGit2)
endif()
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
add_definitions(-DTRANSLATION_DOMAIN=\"kateproject\")
......@@ -35,7 +34,7 @@ add_library(kateprojectplugin MODULE ${kateprojectplugin_PART_SRCS})
target_link_libraries(kateprojectplugin
KF5::TextEditor
KF5::Parts KF5::I18n
Qt5::Script KF5::ItemViews KF5::ItemModels KF5::IconThemes
Qt5::Script KF5::ItemViews KF5::ItemModels KF5::IconThemes KF5::ThreadWeaver
${PROJECT_OPTIONAL_LIBS}
)
......
......@@ -25,6 +25,8 @@
#include <ktexteditor/document.h>
#include <ThreadWeaver/Queue>
#include <QDir>
#include <QFile>
#include <QFileInfo>
......@@ -32,43 +34,16 @@
#include <QJsonDocument>
#include <QJsonParseError>
KateProject::KateProject()
KateProject::KateProject(ThreadWeaver::Queue *weaver)
: QObject()
, m_worker(new KateProjectWorker(this))
, m_thread(m_worker)
, m_notesDocument(nullptr)
, m_untrackedDocumentsRoot(nullptr)
, m_weaver(weaver)
{
/**
* move worker object over and start our worker thread
* thread will delete worker on run() exit
*/
m_worker->moveToThread(&m_thread);
m_thread.start();
}
KateProject::~KateProject()
{
/**
* only do this once
*/
Q_ASSERT(m_worker);
/**
* quit the thread event loop and wait for completion
* will delete worker on thread run() exit
*/
m_thread.quit();
m_thread.wait();
/**
* marks as deleted
*/
m_worker = nullptr;
/**
* save notes document, if any
*/
saveNotesDocument();
}
......@@ -160,10 +135,11 @@ bool KateProject::load(const QVariantMap &globalProject, bool force)
*/
emit projectMapChanged();
/**
* trigger worker to REALLY load the project model and stuff
*/
QMetaObject::invokeMethod(m_worker, "loadProject", Qt::QueuedConnection, Q_ARG(QString, m_baseDir), Q_ARG(QVariantMap, m_projectMap));
KateProjectWorker * w = new KateProjectWorker(m_baseDir, m_projectMap);
connect(w, &KateProjectWorker::loadDone, this, &KateProject::loadProjectDone);
connect(w, &KateProjectWorker::loadIndexDone, this, &KateProject::loadIndexDone);
m_weaver->stream() << w;
return true;
}
......
......@@ -21,7 +21,6 @@
#ifndef KATE_PROJECT_H
#define KATE_PROJECT_H
#include <QThread>
#include <QMap>
#include <QSharedPointer>
#include <QTextDocument>
......@@ -42,29 +41,9 @@ Q_DECLARE_METATYPE(KateProjectSharedQMapStringItem)
typedef QSharedPointer<KateProjectIndex> KateProjectSharedProjectIndex;
Q_DECLARE_METATYPE(KateProjectSharedProjectIndex)
/**
* Private worker thread.
* Will take care of worker object deletion.
*/
class KateProjectWorkerThread : public QThread
{
public:
KateProjectWorkerThread(QObject *worker)
: QThread()
, m_worker (worker)
{
}
protected:
virtual void run()
{
exec();
delete m_worker;
}
private:
QObject *m_worker;
};
namespace ThreadWeaver {
class Queue;
}
/**
* Class representing a project.
......@@ -78,7 +57,7 @@ public:
/**
* construct empty project
*/
KateProject();
KateProject(ThreadWeaver::Queue *weaver);
/**
* deconstruct project
......@@ -248,20 +227,6 @@ private:
void unregisterUntrackedItem(const KateProjectItem *item);
private:
/**
* the worker inside the background thread
* if this is NULL, we are in our deconstruction state and should
* ignore the feedback of our already stopped thread that
* may still come in because of queued connects
* only DELETE all stuff we need to cleanup in the slots
*/
QObject *m_worker;
/**
* our internal thread to load stuff and do things in background
*/
KateProjectWorkerThread m_thread;
/**
* project file name
*/
......@@ -311,6 +276,8 @@ private:
* Parent item for existing documents that are not in the project tree
*/
QStandardItem *m_untrackedDocumentsRoot;
ThreadWeaver::Queue *m_weaver;
};
#endif
......@@ -31,6 +31,7 @@
#include <KSharedConfig>
#include <KConfigGroup>
#include <ThreadWeaver/Queue>
#include <QFileInfo>
#include <QTime>
......@@ -65,6 +66,7 @@ KateProjectPlugin::KateProjectPlugin(QObject *parent, const QList<QVariant> &)
, m_autoGit(true)
, m_autoSubversion(true)
, m_autoMercurial(true)
, m_weaver(new ThreadWeaver::Queue(this))
{
qRegisterMetaType<KateProjectSharedQStandardItem>("KateProjectSharedQStandardItem");
qRegisterMetaType<KateProjectSharedQMapStringItem>("KateProjectSharedQMapStringItem");
......@@ -102,6 +104,11 @@ KateProjectPlugin::~KateProjectPlugin()
delete project;
}
m_projects.clear();
m_weaver->suspend();
m_weaver->dequeue();
m_weaver->finish();
delete m_weaver;
}
QObject *KateProjectPlugin::createView(KTextEditor::MainWindow *mainWindow)
......@@ -124,7 +131,7 @@ KTextEditor::ConfigPage *KateProjectPlugin::configPage(int number, QWidget *pare
KateProject *KateProjectPlugin::createProjectForFileName(const QString &fileName)
{
KateProject *project = new KateProject();
KateProject *project = new KateProject(m_weaver);
if (!project->loadFromFile(fileName)) {
delete project;
......@@ -273,7 +280,7 @@ KateProject *KateProjectPlugin::createProjectForRepository(const QString &type,
cnf[QLatin1String("name")] = dir.dirName();
cnf[QLatin1String("files")] = (QVariantList() << files);
KateProject *project = new KateProject ();
KateProject *project = new KateProject(m_weaver);
project->loadFromData(cnf, dir.canonicalPath());
m_projects.append(project);
......
......@@ -33,6 +33,10 @@
#include "kateproject.h"
#include "kateprojectcompletion.h"
namespace ThreadWeaver {
class Queue;
}
class KateProjectPlugin : public KTextEditor::Plugin
{
Q_OBJECT
......@@ -168,6 +172,8 @@ private:
bool m_autoGit : 1;
bool m_autoSubversion : 1;
bool m_autoMercurial : 1;
ThreadWeaver::Queue *m_weaver;
};
#endif
......@@ -36,42 +36,31 @@
#include <git2/repository.h>
#endif
KateProjectWorker::KateProjectWorker(QObject *project)
KateProjectWorker::KateProjectWorker(const QString &baseDir, const QVariantMap &projectMap)
: QObject()
, m_project(project)
, ThreadWeaver::Job()
, m_baseDir(baseDir)
, m_projectMap(projectMap)
{
Q_ASSERT(m_baseDir.isEmpty());
}
KateProjectWorker::~KateProjectWorker()
void KateProjectWorker::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread *)
{
}
void KateProjectWorker::loadProject(QString baseDir, QVariantMap projectMap)
{
/**
* setup project base directory
* this should be FIX after initial setting
*/
Q_ASSERT(m_baseDir.isEmpty() || (m_baseDir == baseDir));
m_baseDir = baseDir;
/**
* Create dummy top level parent item and empty map inside shared pointers
* then load the project recursively
*/
KateProjectSharedQStandardItem topLevel(new QStandardItem());
KateProjectSharedQMapStringItem file2Item(new QMap<QString, KateProjectItem *> ());
loadProject(topLevel.data(), projectMap, file2Item.data());
loadProject(topLevel.data(), m_projectMap, file2Item.data());
/**
* create some local backup of some data we need for further processing!
*/
QStringList files = file2Item->keys();
/**
* feed back our results
*/
QMetaObject::invokeMethod(m_project, "loadProjectDone", Qt::QueuedConnection, Q_ARG(KateProjectSharedQStandardItem, topLevel), Q_ARG(KateProjectSharedQMapStringItem, file2Item));
emit loadDone(topLevel, file2Item);
/**
* load index
......@@ -538,8 +527,5 @@ void KateProjectWorker::loadIndex(const QStringList &files)
*/
KateProjectSharedProjectIndex index(new KateProjectIndex(files));
/**
* send new index object back to project
*/
QMetaObject::invokeMethod(m_project, "loadIndexDone", Qt::QueuedConnection, Q_ARG(KateProjectSharedProjectIndex, index));
emit loadIndexDone(index);
}
......@@ -21,18 +21,21 @@
#ifndef KATE_PROJECT_WORKER_H
#define KATE_PROJECT_WORKER_H
#include "kateprojectitem.h"
#include "kateproject.h"
#include <ThreadWeaver/Job>
#include <QStandardItemModel>
#include <QMap>
#include "kateprojectitem.h"
class QDir;
/**
* Class representing a project background worker.
* This worker will build up the model for the project on load and do other stuff in the background.
*/
class KateProjectWorker : public QObject
class KateProjectWorker : public QObject, public ThreadWeaver::Job
{
Q_OBJECT
......@@ -42,26 +45,13 @@ public:
*/
typedef QMap<QString, KateProjectItem *> MapString2Item;
/**
* construct project worker for given project
* @param project our project
*/
KateProjectWorker(QObject *project);
explicit KateProjectWorker(const QString &baseDir, const QVariantMap &projectMap);
/**
* deconstruct worker
*/
~KateProjectWorker();
void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread);
private Q_SLOTS:
/**
* Load the project.
* Will be used to load project in background.
* Will inform the project after loading was done and pass over all needed data!
* @param baseDir project file name, should stay the same after initial setup
* @param projectMap full map containing the whole project as copy to work on
*/
void loadProject(QString baseDir, QVariantMap projectMap);
Q_SIGNALS:
void loadDone(KateProjectSharedQStandardItem topLevel, KateProjectSharedQMapStringItem file2Item);
void loadIndexDone(KateProjectSharedProjectIndex index);
private:
/**
......@@ -105,6 +95,7 @@ private:
* project base directory name
*/
QString m_baseDir;
QVariantMap m_projectMap;
};
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment